diff --git a/es/aspects/AspectDict.d.ts b/es/aspects/AspectDict.d.ts index c73755fb..8d6487da 100644 --- a/es/aspects/AspectDict.d.ts +++ b/es/aspects/AspectDict.d.ts @@ -1,9 +1,9 @@ -import { BRC } from '../types/RuntimeCxt'; +import { BackendRuntimeContext } from '../context/BackendRuntimeContext'; import { EntityDict } from '../oak-app-domain'; -export type AspectDict = { +export type AspectDict = { getWithdrawCreateData: (params: { accountId: string; price: number; withdrawAccountId?: string; - }, context: BRC) => Promise; + }, context: BackendRuntimeContext) => Promise; }; diff --git a/es/aspects/index.d.ts b/es/aspects/index.d.ts index b1a25f64..aa69f7a8 100644 --- a/es/aspects/index.d.ts +++ b/es/aspects/index.d.ts @@ -1,4 +1,5 @@ +import { EntityDict } from '../oak-app-domain'; import { AspectDict } from './AspectDict'; -declare const aspectDict: AspectDict; +declare const aspectDict: AspectDict; export default aspectDict; export { AspectDict, }; diff --git a/es/checkers/accountOper.js b/es/checkers/accountOper.js index 5ae6a27f..23c53d0b 100644 --- a/es/checkers/accountOper.js +++ b/es/checkers/accountOper.js @@ -54,14 +54,15 @@ const checkers = [ case 'refund': case 'withdraw': { if (totalPlus >= 0 || availPlus >= 0 || totalPlus !== availPlus) { - throw new OakInputIllegalException('accountOper', ['availPlus'], 'accountOper为withdraw时,其totalPlus和availPlus必须为不相等的负数'); + throw new OakInputIllegalException('accountOper', ['availPlus'], `accountOper为${type}时,其totalPlus和availPlus必须为不相等的负数`); } break; } case 'refundFailure': - case 'withdrawBack': { + case 'withdrawBack': + case 'consumeBack': { if (totalPlus <= 0 || availPlus <= 0 || totalPlus !== availPlus) { - throw new OakInputIllegalException('accountOper', ['availPlus'], 'accountOper为withdraw时,其totalPlus和availPlus必须为不相等的正数'); + throw new OakInputIllegalException('accountOper', ['availPlus'], `accountOper为${type}时,其totalPlus和availPlus必须为不相等的正数`); } break; } diff --git a/es/checkers/offlineAccount.js b/es/checkers/offlineAccount.js index dc10df25..3ec31547 100644 --- a/es/checkers/offlineAccount.js +++ b/es/checkers/offlineAccount.js @@ -27,13 +27,16 @@ function checkAttributes(data) { } } } - const { refundCompensateRatio, refundGapDays } = data; + const { refundCompensateRatio, refundGapDays, withdrawTransferLossRatio } = data; if (typeof refundGapDays !== 'number' || refundGapDays < 0) { throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundGapDaysNotNegative'); } if (typeof refundCompensateRatio !== 'number' || refundCompensateRatio < 0 || refundCompensateRatio > 100) { throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundCompensateIllegal'); } + if (typeof withdrawTransferLossRatio !== 'number' || withdrawTransferLossRatio < 0) { + throw new OakInputIllegalException('offlineAccount', ['withdrawTransferLossRatio'], 'offlineAccount::error.withdrawTransferLossRatioNotNegative'); + } } const checkers = [ { diff --git a/es/checkers/refund.js b/es/checkers/refund.js index f1126648..d58aad90 100644 --- a/es/checkers/refund.js +++ b/es/checkers/refund.js @@ -15,6 +15,7 @@ const checkers = [ }, }, action: 'create', + errMsg: 'error::refund.create.hasAnotherRefunding', }, { entity: 'refund', diff --git a/es/components/AbstractComponents.d.ts b/es/components/AbstractComponents.d.ts index 7bc4fdd2..80de4eed 100644 --- a/es/components/AbstractComponents.d.ts +++ b/es/components/AbstractComponents.d.ts @@ -16,8 +16,8 @@ declare const List: (props: ReactComponentProps[]; loading: boolean; - tablePagination?: any; - rowSelection?: any; + tablePagination?: false | import("antd").TablePaginationConfig | undefined; + rowSelection?: import("antd/es/table/interface").TableRowSelection> | undefined; hideHeader?: boolean | undefined; disableSerialNumber?: boolean | undefined; size?: "small" | "middle" | "large" | undefined; @@ -27,7 +27,7 @@ declare const List: (props: ReactComponentProps) => React.ReactElement; declare const ListPro: (props: { @@ -43,29 +43,34 @@ declare const ListPro: (props: { attributes: OakAbsAttrDef[]; data: RowWithActions[]; loading?: boolean | undefined; - tablePagination?: any; - rowSelection?: any; + tablePagination?: false | import("antd").TablePaginationConfig | undefined; + rowSelection?: import("antd/es/table/interface").TableRowSelection> | undefined; disableSerialNumber?: boolean | undefined; size?: "small" | "middle" | "large" | undefined; - scroll?: any; - locale?: any; + scroll?: ({ + x?: string | number | true | undefined; + y?: string | number | undefined; + } & { + scrollToFirstRowOnChange?: boolean | undefined; + }) | undefined; + locale?: import("antd/es/table/interface").TableLocale | undefined; opWidth?: number | undefined; }) => React.ReactElement; declare const Detail: (props: ReactComponentProps | undefined; + column?: number | Record | undefined; entity: T; attributes: OakAbsAttrDef[]; data: Partial; title?: string | undefined; bordered?: boolean | undefined; - layout?: "horizontal" | "vertical" | undefined; + layout?: "vertical" | "horizontal" | undefined; }>) => React.ReactElement; declare const Upsert: (props: ReactComponentProps; entity: T; attributes: OakAbsAttrUpsertDef[]; data: EntityDict[T]["Schema"]; - layout: "horizontal" | "vertical"; + layout: "vertical" | "horizontal"; mode: "default" | "card"; }>) => React.ReactElement; export { FilterPanel, List, ListPro, Detail, Upsert, ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, }; diff --git a/es/components/offlineAccount/upsert/web.pc.js b/es/components/offlineAccount/upsert/web.pc.js index 8ef0feb5..bae900c2 100644 --- a/es/components/offlineAccount/upsert/web.pc.js +++ b/es/components/offlineAccount/upsert/web.pc.js @@ -74,7 +74,7 @@ export default function render(props) { update({ allowWithdrawTransfer }); }}/> - + { const withdrawTransferLossRatio = value; update({ withdrawTransferLossRatio }); diff --git a/es/components/sysAccount/survey/locales/zh-CN.json b/es/components/sysAccount/survey/locales/zh-CN.json index fa4a8821..c110687b 100644 --- a/es/components/sysAccount/survey/locales/zh-CN.json +++ b/es/components/sysAccount/survey/locales/zh-CN.json @@ -24,5 +24,7 @@ "orderPriceSum": "订单总额", "orderManage": "订单管理", "orderList": "订单列表", - "tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额" + "tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额", + "move": "移动资金", + "history": "账单" } diff --git a/es/components/sysAccount/survey/web.pc.js b/es/components/sysAccount/survey/web.pc.js index 37ef8cc7..93377e61 100644 --- a/es/components/sysAccount/survey/web.pc.js +++ b/es/components/sysAccount/survey/web.pc.js @@ -1,10 +1,13 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Descriptions, Tag, Modal, Flex, Button, Divider, Alert } from 'antd'; import { AlipayOutlined, WechatOutlined } from '@ant-design/icons'; import Styles from './web.pc.module.less'; import { ThousandCont, ToYuan } from "oak-domain/lib/utils/money"; import { OfflineAccount as OADetail } from '../../offlineAccount/config/web.pc'; import { WpAccount as WADetail } from '../../wpAccount/config/web.pc'; +import TransferList from '../transferList'; +import SysAccountMoveCreate from '../../sysAccountMove/create'; +import SysAccountOperList from '../../sysAccountOper/list'; function OfflineAccount(props) { const { data, t } = props; const { type, channel, color, name } = data; @@ -65,6 +68,10 @@ export default function render(props) { const { accounts, total, systemId, accountNum, accountTotalSum, accountAvailSum, refundCnt, refundPriceSum, transferCnt, transferPriceSum, orderCnt, orderPaidSum, orderRefundSum, } = props.data; const { t, setMessage } = props.methods; if (accounts && systemId) { + const [showTransferList, setShowTransferList] = useState(false); + const [showMoveCreate, setShowMoveCreate] = useState(false); + const [showHistoryList, setShowHistoryList] = useState(false); + const [showHistoryAcc, setShowHistoryAcc] = useState(undefined); return (
+ ]} column={2} extra={<> + + setShowMoveCreate(false)} closeIcon={null} width={800} title={t('move')} footer={null}> + setShowMoveCreate(false)}/> + + }/>
{accounts.map(({ entity, data }, idx) => { const TopRender = RenderSysAccountCardTopDict[entity]; @@ -92,6 +106,12 @@ export default function render(props) {
+ + + {!!showHistoryAcc && showHistoryList && + { + setShowHistoryAcc(undefined); + setShowHistoryList(false); + }} width={800} title={showHistoryAcc.entity === 'offlineAccount' ? + (showHistoryAcc.data.type === 'bank' ? + `${t(`${showHistoryAcc.entity}:v.type.${showHistoryAcc.data.type}`)}-${showHistoryAcc.data.channel}-${t('history')}` + : `${t(`${showHistoryAcc.entity}:v.type.${showHistoryAcc.data.type}`)}-${showHistoryAcc.data.name}-${t('history')}`) : `${t(`${showHistoryAcc.entity}:name`)}-${t('history')}`} footer={null}> +
+ +
+ +
}
); })} @@ -119,16 +153,16 @@ export default function render(props) { { label: t('accountTotalSum'), children:
- {t('common::pay.symbol')} - {ThousandCont(ToYuan(accountTotalSum || 0), 2)} -
+ {t('common::pay.symbol')} + {ThousandCont(ToYuan(accountTotalSum || 0), 2)} + }, { label: t('accountAvailSum'), children:
- {t('common::pay.symbol')} - {ThousandCont(ToYuan(accountAvailSum || 0), 2)} -
+ {t('common::pay.symbol')} + {ThousandCont(ToYuan(accountAvailSum || 0), 2)} + }, { label: t('accountNum'), @@ -142,14 +176,14 @@ export default function render(props) { label: t('refundPriceSum'), span: 2, children: (
- - {t('common::pay.symbol')} - {ThousandCont(ToYuan(refundPriceSum || 0), 2)} - - -
) + + {t('common::pay.symbol')} + {ThousandCont(ToYuan(refundPriceSum || 0), 2)} + + + ) }, { label: t('transferCnt'), @@ -159,14 +193,17 @@ export default function render(props) { label: t('transferPriceSum'), span: 2, children: (
- - {t('common::pay.symbol')} - {ThousandCont(ToYuan(transferPriceSum || 0), 2)} - - -
) + + {t('common::pay.symbol')} + {ThousandCont(ToYuan(transferPriceSum || 0), 2)} + + + setShowTransferList(false)} footer={null} closeIcon={null} width={800}> + + + ) }, { label: t('orderCnt'), @@ -175,14 +212,14 @@ export default function render(props) { { label: t('orderPriceSum'), children: (
-
- {t('common::pay.symbol')} - {ThousandCont(ToYuan((orderPaidSum || 0) - (orderRefundSum || 0)), 2)} -
- -
) +
+ {t('common::pay.symbol')} + {ThousandCont(ToYuan((orderPaidSum || 0) - (orderRefundSum || 0)), 2)} +
+ + ) } ]} column={3}/>} ); diff --git a/es/components/sysAccount/survey/web.pc.module.less b/es/components/sysAccount/survey/web.pc.module.less index b7a8facb..e52e4727 100644 --- a/es/components/sysAccount/survey/web.pc.module.less +++ b/es/components/sysAccount/survey/web.pc.module.less @@ -19,13 +19,14 @@ padding: 8px; flex-wrap: wrap; margin-top: 12px; + gap: 14px; .sysAccount { width: 244px; height: 284px; border: solid 0.1px silver; border-radius: 5px; - margin-right: 14px; + // margin-right: 14px; display: flex; flex-direction: column; align-items: stretch; @@ -64,7 +65,7 @@ } } } - + .span2 { display: flex; flex-direction: row; diff --git a/es/components/sysAccount/transferList/index.d.ts b/es/components/sysAccount/transferList/index.d.ts new file mode 100644 index 00000000..a0335de1 --- /dev/null +++ b/es/components/sysAccount/transferList/index.d.ts @@ -0,0 +1,3 @@ +/// +declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; +export default _default; diff --git a/es/components/sysAccount/transferList/index.js b/es/components/sysAccount/transferList/index.js new file mode 100644 index 00000000..476277f3 --- /dev/null +++ b/es/components/sysAccount/transferList/index.js @@ -0,0 +1,52 @@ +export default OakComponent({ + entity: 'withdrawTransfer', + isList: true, + projection: { + id: 1, + price: 1, + loss: 1, + externalId: 1, + iState: 1, + withdrawAccount: { + org: 1, + name: 1, + code: 1, + channel: { + entity: 1, + entityId: 1, + offlineAccount: { + id: 1, + type: 1, + } + }, + id: 1, + } + }, + filters: [ + { + filter() { + const systemId = this.features.application.getApplication().systemId; + return { + withdrawAccount: { + ofSystemId: systemId, + }, + iState: 'transferring', + }; + } + } + ], + formData({ data }) { + return { + transfers: data?.map((ele) => { + const { withdrawAccount, ...rest } = ele; + const { entity, offlineAccount } = withdrawAccount.channel; + const channel = entity === 'offlineAccount' ? this.t(`withdraw::channel.offlineAccount.${offlineAccount?.type}`) : this.t(`withdraw::channel.${entity}`); + return { + ...rest, + withdrawAccount, + channel, + }; + }), + }; + }, +}); diff --git a/es/components/sysAccount/transferList/index.json b/es/components/sysAccount/transferList/index.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/es/components/sysAccount/transferList/index.json @@ -0,0 +1 @@ +{} diff --git a/es/components/sysAccount/transferList/locales/zh-CN.json b/es/components/sysAccount/transferList/locales/zh-CN.json new file mode 100644 index 00000000..b2691130 --- /dev/null +++ b/es/components/sysAccount/transferList/locales/zh-CN.json @@ -0,0 +1,6 @@ +{ + "label": { + "channel": "转账渠道" + }, + "tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作" +} diff --git a/es/components/sysAccount/transferList/web.pc.d.ts b/es/components/sysAccount/transferList/web.pc.d.ts new file mode 100644 index 00000000..07962832 --- /dev/null +++ b/es/components/sysAccount/transferList/web.pc.d.ts @@ -0,0 +1,12 @@ +import React from 'react'; +import { RowWithActions, WebComponentProps } from 'oak-frontend-base'; +import { EntityDict } from '../../../oak-app-domain'; +export default function Render(props: WebComponentProps & { + creatorName: string; + creatorMobile: string; + operatorName: string; + operatorMobile: string; + channel: string; + })[]; +}>): React.JSX.Element; diff --git a/es/components/sysAccount/transferList/web.pc.js b/es/components/sysAccount/transferList/web.pc.js new file mode 100644 index 00000000..e3d52107 --- /dev/null +++ b/es/components/sysAccount/transferList/web.pc.js @@ -0,0 +1,45 @@ +import React from 'react'; +import { Result, Alert } from 'antd'; +import ListPro from 'oak-frontend-base/es/components/listPro'; +import { ThousandCont, ToYuan } from 'oak-domain/lib/utils/money'; +export default function Render(props) { + const { transfers, oakFullpath, oakExecutable } = props.data; + const { t } = props.methods; + if (transfers?.length) { + return (} attributes={[ + { + path: 'price', + label: t('withdrawTransfer:attr.price'), + width: 100, + render: (row) => { + return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row.price), 2)}`; + } + }, + { + path: 'loss', + label: t('withdrawTransfer:attr.loss'), + width: 100, + render: (row) => { + return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row.loss), 2)}`; + } + }, + { + path: '$$createAt$$', + label: t('common::$$createAt$$'), + width: 100, + }, + { + path: 'channel', + label: t('label.channel'), + type: 'string', + width: 100, + }, + { + path: 'externalId', + label: t('withdrawTransfer:attr.externalId'), + width: 120, + }, + ]} disabledOp={true}/>); + } + return (); +} diff --git a/es/components/sysAccountMove/create/index.d.ts b/es/components/sysAccountMove/create/index.d.ts new file mode 100644 index 00000000..155cf52d --- /dev/null +++ b/es/components/sysAccountMove/create/index.d.ts @@ -0,0 +1,7 @@ +import { EntityDict } from "../../../oak-app-domain"; +declare const _default: (props: import("oak-frontend-base").ReactComponentProps void; +}>) => React.ReactElement; +export default _default; diff --git a/es/components/sysAccountMove/create/index.js b/es/components/sysAccountMove/create/index.js new file mode 100644 index 00000000..d26a46db --- /dev/null +++ b/es/components/sysAccountMove/create/index.js @@ -0,0 +1,145 @@ +import { uniq } from "oak-domain/lib/utils/lodash"; +import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid'; +import { ThousandCont, ToCent, ToYuan } from 'oak-domain/lib/utils/money'; +export default OakComponent({ + properties: { + systemId: '', + entities: [], + onSuccess: (id) => undefined, + }, + data: { + accounts: [], + fromEntity: '', + fromEntityId: '', + toEntity: '', + toEntityId: '', + price: 0, + externalId: '', + remark: '', + max: 0, + }, + lifetimes: { + ready() { + this.refreshSysAccount(); + } + }, + methods: { + async refreshSysAccount() { + const { entities, systemId } = this.props; + const accounts2 = await Promise.all(uniq(['wpAccount', 'offlineAccount'].concat(entities || [])).map(async (entity) => { + const { data: rows } = await this.features.cache.refresh(entity, { + data: entity === 'offlineAccount' ? { + id: 1, + price: 1, + name: 1, + type: 1, + channel: 1, + } : { + id: 1, + price: 1, + }, + filter: { + systemId, + } + }); + const accounts = rows.map((row) => { + const { id, price, name, type, channel } = row; + return { + id: id, + entity: entity, + priceStr: ThousandCont(ToYuan(price)), + price: price, + label: entity === 'offlineAccount' ? `${this.t(`${entity}:name`)}-${this.t(`offlineAccount:v.type.${type}`)}` : this.t(`${entity}:name`), + name: name || undefined, + }; + }); + return accounts; + })); + this.setState({ + accounts: accounts2.flat(), + }); + }, + setFromId(id) { + const { accounts } = this.state; + const account = accounts.find(ele => ele.id === id); + this.setState({ + fromEntity: account.entity, + fromEntityId: account.id, + max: ToYuan(account.price), + }); + }, + setToId(id) { + const { accounts } = this.state; + const account = accounts.find(ele => ele.id === id); + this.setState({ + toEntity: account.entity, + toEntityId: account.id, + }); + }, + setPrice(price) { + this.setState({ + price, + }); + }, + setExternalId(externalId) { + this.setState({ + externalId, + }); + }, + setRemark(remark) { + this.setState({ + remark, + }); + }, + async createMove() { + const { fromEntity, fromEntityId, toEntity, toEntityId, price, remark, externalId } = this.state; + const userId = this.features.token.getUserId(); + const systemId = this.features.application.getApplication().systemId; + const id = await generateNewIdAsync(); + const price2 = ToCent(price); + const { onSuccess } = this.props; + await this.execute(undefined, undefined, undefined, [ + { + entity: 'sysAccountMove', + operation: { + id: await generateNewIdAsync(), + action: 'create', + data: { + id, + price: price2, + externalId, + remark, + systemId, + operatorId: userId, + sysAccountOper$sysAccountMove: [ + { + id: await generateNewIdAsync(), + action: 'create', + data: { + id: await generateNewIdAsync(), + entity: fromEntity, + entityId: fromEntityId, + delta: -price2, + type: 'moveOut', + }, + }, + { + id: await generateNewIdAsync(), + action: 'create', + data: { + id: await generateNewIdAsync(), + entity: toEntity, + entityId: toEntityId, + delta: price2, + type: 'moveIn', + }, + }, + ] + } + }, + } + ]); + onSuccess && onSuccess(id); + } + } +}); diff --git a/es/components/sysAccountMove/create/index.json b/es/components/sysAccountMove/create/index.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/es/components/sysAccountMove/create/index.json @@ -0,0 +1 @@ +{} diff --git a/es/components/sysAccountMove/create/locales/zh-CN.json b/es/components/sysAccountMove/create/locales/zh-CN.json new file mode 100644 index 00000000..60ca427e --- /dev/null +++ b/es/components/sysAccountMove/create/locales/zh-CN.json @@ -0,0 +1,6 @@ +{ + "label": { + "from": "从账户", + "to": "到账户" + } +} diff --git a/es/components/sysAccountMove/create/web.pc.d.ts b/es/components/sysAccountMove/create/web.pc.d.ts new file mode 100644 index 00000000..76e62e23 --- /dev/null +++ b/es/components/sysAccountMove/create/web.pc.d.ts @@ -0,0 +1,26 @@ +import React from 'react'; +import { WebComponentProps } from 'oak-frontend-base'; +import { EntityDict } from '../../../oak-app-domain'; +export default function Render(props: WebComponentProps; +}, { + setFromId: (id: string) => void; + setToId: (id: string) => void; + setPrice: (price: number) => void; + setExternalId: (externalId: string) => void; + setRemark: (remark: string) => void; + createMove: () => Promise; +}>): React.JSX.Element | null; diff --git a/es/components/sysAccountMove/create/web.pc.js b/es/components/sysAccountMove/create/web.pc.js new file mode 100644 index 00000000..3e471510 --- /dev/null +++ b/es/components/sysAccountMove/create/web.pc.js @@ -0,0 +1,68 @@ +import React from 'react'; +import { Button, Form, Input, InputNumber, Radio, Space, Flex } from 'antd'; +export default function Render(props) { + const { price, externalId, max, remark, fromEntityId, toEntityId, accounts } = props.data; + const { t, setFromId, setToId, setPrice, setExternalId, setRemark, createMove } = props.methods; + if (accounts.length) { + return (<> +
+ + { + setFromId(target.value); + }} value={fromEntityId}> + + {accounts.filter(ele => ele.price > 0).map(ele => { + const { id, label, price, priceStr } = ele; + return ( + {`${label}: ${t('common::pay.symbol')}${priceStr}`} + ); + })} + + + + {fromEntityId && + { + setToId(target.value); + }} value={toEntityId}> + + {accounts.filter(ele => ele.id !== fromEntityId).map(ele => { + const { id, label, price, priceStr } = ele; + return ( + {`${label}: ${t('common::pay.symbol')}${priceStr}`} + ); + })} + + + } + {fromEntityId && toEntityId && + { + const price = value; + setPrice(price); + }}/> + } + {fromEntityId && toEntityId && + { + const externalId = currentTarget.value; + setExternalId(externalId); + }} maxLength={64}/> + } + {fromEntityId && toEntityId && + { + const remark = currentTarget.value; + setRemark(remark); + }} rows={4}/> + } +
+ + + + ); + } + return null; +} diff --git a/es/components/sysAccountOper/list/index.d.ts b/es/components/sysAccountOper/list/index.d.ts new file mode 100644 index 00000000..adec0308 --- /dev/null +++ b/es/components/sysAccountOper/list/index.d.ts @@ -0,0 +1,5 @@ +declare const _default: (props: import("oak-frontend-base").ReactComponentProps) => React.ReactElement; +export default _default; diff --git a/es/components/sysAccountOper/list/index.js b/es/components/sysAccountOper/list/index.js new file mode 100644 index 00000000..24eccd08 --- /dev/null +++ b/es/components/sysAccountOper/list/index.js @@ -0,0 +1,127 @@ +import dayjs from 'dayjs'; +import { ToYuan, ThousandCont } from "oak-domain/lib/utils/money"; +export default OakComponent({ + entity: 'sysAccountOper', + isList: true, + projection: { + id: 1, + delta: 1, + type: 1, + entity: 1, + entityId: 1, + $$createAt$$: 1, + }, + filters: [ + { + filter() { + const { entity, entityId } = this.props; + return { + entity, + entityId, + }; + } + } + ], + formData({ data }) { + return { + sysAccountOpers: data.map((oper) => { + const { $$createAt$$, type, delta } = oper; + const num = Math.abs(delta); + const plus = ThousandCont(ToYuan(num), 2); + const sign = delta > 0 ? '+' : '-'; + const time = dayjs($$createAt$$).format('YYYY-MM-DD HH:mm'); + const symbol = this.t(`sysAccountOper:v.type.${type}`)[0]; + const bgColor = this.features.style.getColor('sysAccountOper', 'type', type); + return { + value: `${sign}${plus}`, + time, + type: this.t(`sysAccountOper:v.type.${type}`), + symbol, + bgColor, + }; + }), + }; + }, + pagination: { + pageSize: 7, + currentPage: 1, + }, + getTotal: 100, + properties: { + entity: '', + entityId: '', + }, + data: { + month: new Date(), + monthStr: '', + type: 'all', + typesOptions: [] + }, + lifetimes: { + ready() { + let typesOptions = [{ + label: this.t('all'), + value: 'all', + }]; + const types = ['withdrawTransfer', 'pay', 'refund', 'compensate', 'moveIn', 'moveOut']; + types.forEach((ele) => { + typesOptions.push({ + label: this.t(`sysAccountOper:v.type.${ele}`), + value: ele, + }); + }); + this.setState({ + typesOptions, + }); + this.setTypeFilter(); + } + }, + methods: { + setType(type) { + this.setState({ + type, + }, () => this.setTypeFilter()); + }, + setTypeFilter() { + const { type } = this.state; + if (type === 'all') { + this.removeNamedFilterByName('type', true); + } + else { + this.addNamedFilter({ + '#name': 'type', + filter: { + type, + } + }, true); + } + }, + setMonth(month) { + if (month) { + const m = dayjs(month); + const begin = m.startOf('month').valueOf(); + const end = m.endOf('month').valueOf(); + this.setState({ + monthStr: m.format('YYYY-MM'), + month, + }, () => this.addNamedFilter({ + '#name': 'month', + filter: { + $$createAt$$: { + $between: [begin, end], + } + } + }, true)); + } + else { + this.setState({ + monthStr: '', + month: undefined, + }, () => this.removeNamedFilter({ + '#name': 'month', + filter: {} + }, true)); + } + }, + } +}); diff --git a/es/components/sysAccountOper/list/index.json b/es/components/sysAccountOper/list/index.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/es/components/sysAccountOper/list/index.json @@ -0,0 +1 @@ +{} diff --git a/es/components/sysAccountOper/list/locales/zh-CN.json b/es/components/sysAccountOper/list/locales/zh-CN.json new file mode 100644 index 00000000..e9bad02d --- /dev/null +++ b/es/components/sysAccountOper/list/locales/zh-CN.json @@ -0,0 +1,5 @@ +{ + "history": "账户历史", + "chooseMonth": "选择月份", + "all": "全部" +} diff --git a/es/components/sysAccountOper/list/web.module.less b/es/components/sysAccountOper/list/web.module.less new file mode 100644 index 00000000..f9d46980 --- /dev/null +++ b/es/components/sysAccountOper/list/web.module.less @@ -0,0 +1,42 @@ +.container { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.control { + padding: 4px; +} + +.value { + font-size: x-large; + font-weight: bold; +} + +.content{ + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.types { + padding: 20px; + width: 100%; +} + +.pagi{ + display: flex; + align-items: center; + justify-content: center; +} + +.empty { + display: flex; + width: 100%; + flex: 1; + background-color: white; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/es/components/sysAccountOper/list/web.pc.d.ts b/es/components/sysAccountOper/list/web.pc.d.ts new file mode 100644 index 00000000..6d17dd9a --- /dev/null +++ b/es/components/sysAccountOper/list/web.pc.d.ts @@ -0,0 +1,25 @@ +import React from 'react'; +import { WebComponentProps } from 'oak-frontend-base'; +import { EntityDict } from '../../../oak-app-domain'; +import { SysAccountOperType } from '../../../types/sysAccountOper'; +type SAOType = SysAccountOperType | 'all'; +export default function Render(props: WebComponentProps; + month?: Date; + monthStr: string; + type: SAOType; + typesOptions: { + label: string; + value: SAOType; + }[]; +}, { + setMonth: (month?: Date) => void; + setType: (type: SAOType) => void; +}>): React.JSX.Element; +export {}; diff --git a/es/components/sysAccountOper/list/web.pc.js b/es/components/sysAccountOper/list/web.pc.js new file mode 100644 index 00000000..4969d434 --- /dev/null +++ b/es/components/sysAccountOper/list/web.pc.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { Avatar, List, Select, Flex, DatePicker, Empty, Pagination } from 'antd'; +import Styles from './web.module.less'; +import dayJs from 'dayjs'; +export default function Render(props) { + const { sysAccountOpers, month, type, monthStr, oakLoading, oakLoadingMore, typesOptions, oakPagination } = props.data; + const { t, setType, setMonth, setPageSize, setCurrentPage } = props.methods; + const { pageSize, total, currentPage } = oakPagination || {}; + return (
+ + { + setMonth(value?.toDate()); + }} maxDate={dayJs()}/> + { + const externalId = currentTarget.value; + setExternalId(externalId); + }} + maxLength={64} + /> + + } + { + fromEntityId && toEntityId && + { + const remark = currentTarget.value; + setRemark(remark); + }} + rows={4} + /> + + } + + + + + + ); + } + + return null; +} \ No newline at end of file diff --git a/src/components/sysAccountOper/list/index.json b/src/components/sysAccountOper/list/index.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/src/components/sysAccountOper/list/index.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/components/sysAccountOper/list/index.ts b/src/components/sysAccountOper/list/index.ts new file mode 100644 index 00000000..1c9fbe1c --- /dev/null +++ b/src/components/sysAccountOper/list/index.ts @@ -0,0 +1,137 @@ +import { SysAccountOperType } from '@project/types/sysAccountOper'; +import dayjs from 'dayjs'; +import { ToYuan, ThousandCont } from "oak-domain/lib/utils/money"; + +type SAOType = SysAccountOperType | 'all'; + +export default OakComponent({ + entity: 'sysAccountOper', + isList: true, + projection: { + id: 1, + delta: 1, + type: 1, + entity: 1, + entityId: 1, + $$createAt$$: 1, + }, + filters: [ + { + filter() { + const { entity, entityId } = this.props; + return { + entity, + entityId, + }; + } + } + ], + formData({ data }) { + return { + sysAccountOpers: data.map( + (oper) => { + const { $$createAt$$, type, delta } = oper; + const num = Math.abs(delta!); + const plus = ThousandCont(ToYuan(num!), 2); + const sign = delta! > 0 ? '+' : '-'; + const time = dayjs($$createAt$$ as number).format('YYYY-MM-DD HH:mm'); + const symbol = this.t(`sysAccountOper:v.type.${type}`)[0]; + const bgColor = this.features.style.getColor('sysAccountOper', 'type', type!); + + return { + value: `${sign}${plus}`, + time, + type: this.t(`sysAccountOper:v.type.${type}`), + symbol, + bgColor, + } + } + ), + }; + }, + pagination: { + pageSize: 7, + currentPage: 1, + }, + getTotal: 100, + properties: { + entity: '', + entityId: '', + }, + data: { + month: new Date(), + monthStr: '', + type: 'all' as SAOType, + typesOptions: [] as { + label: string, + value: SAOType, + }[] + }, + lifetimes: { + ready() { + let typesOptions = [{ + label: this.t('all'), + value: 'all' as SAOType, + }]; + const types: SysAccountOperType[] = ['withdrawTransfer', 'pay', 'refund', 'compensate', 'moveIn', 'moveOut'] + types.forEach((ele) => { + typesOptions.push({ + label: this.t(`sysAccountOper:v.type.${ele}`), + value: ele, + }) + }); + this.setState({ + typesOptions, + }); + this.setTypeFilter(); + } + }, + methods: { + setType(type: SAOType) { + this.setState({ + type, + }, () => this.setTypeFilter()) + }, + setTypeFilter() { + const { type } = this.state; + if (type === 'all') { + this.removeNamedFilterByName('type', true); + } else { + this.addNamedFilter({ + '#name': 'type', + filter: { + type, + } + }, true); + } + }, + setMonth(month?: Date) { + if (month) { + const m = dayjs(month); + const begin = m.startOf('month').valueOf(); + const end = m.endOf('month').valueOf(); + this.setState({ + monthStr: m.format('YYYY-MM'), + month, + }, () => this.addNamedFilter({ + '#name': 'month', + filter: { + $$createAt$$: { + $between: [begin, end], + } + } + }, true)); + } + else { + this.setState({ + monthStr: '', + month: undefined, + }, () => this.removeNamedFilter({ + '#name': 'month', + filter: { + } + }, true)); + } + }, + } +}) \ No newline at end of file diff --git a/src/components/sysAccountOper/list/locales/zh-CN.json b/src/components/sysAccountOper/list/locales/zh-CN.json new file mode 100644 index 00000000..02ba7642 --- /dev/null +++ b/src/components/sysAccountOper/list/locales/zh-CN.json @@ -0,0 +1,5 @@ +{ + "history": "账户历史", + "chooseMonth": "选择月份", + "all": "全部" +} \ No newline at end of file diff --git a/src/components/sysAccountOper/list/web.module.less b/src/components/sysAccountOper/list/web.module.less new file mode 100644 index 00000000..f9d46980 --- /dev/null +++ b/src/components/sysAccountOper/list/web.module.less @@ -0,0 +1,42 @@ +.container { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.control { + padding: 4px; +} + +.value { + font-size: x-large; + font-weight: bold; +} + +.content{ + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.types { + padding: 20px; + width: 100%; +} + +.pagi{ + display: flex; + align-items: center; + justify-content: center; +} + +.empty { + display: flex; + width: 100%; + flex: 1; + background-color: white; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/src/components/sysAccountOper/list/web.pc.tsx b/src/components/sysAccountOper/list/web.pc.tsx new file mode 100644 index 00000000..0452cdac --- /dev/null +++ b/src/components/sysAccountOper/list/web.pc.tsx @@ -0,0 +1,113 @@ +import React, { useState } from 'react'; +import { Radio, Avatar, List, Select, Flex, Button, Card, Result, DatePicker, Empty, Pagination } from 'antd'; +import { CaretDownFilled, SearchOutlined } from '@ant-design/icons'; +import { RowWithActions, WebComponentProps } from 'oak-frontend-base'; +import { EntityDict } from '../../../oak-app-domain'; +import Styles from './web.module.less'; +import dayJs from 'dayjs'; +import { SysAccountOperType } from '@project/types/sysAccountOper'; + +type SAOType = SysAccountOperType | 'all'; + +export default function Render(props: WebComponentProps; + month?: Date; + monthStr: string; + type: SAOType; + typesOptions: { + label: string; + value: SAOType; + }[]; +}, { + setMonth: (month?: Date) => void; + setType: (type: SAOType) => void; +}>) { + const { sysAccountOpers, month, type, monthStr, oakLoading, oakLoadingMore, typesOptions, oakPagination } = props.data; + const { t, setType, setMonth, setPageSize, setCurrentPage } = props.methods; + const { pageSize, total, currentPage } = oakPagination || {}; + return ( +
+ + { + setMonth(value?.toDate()); + }} + maxDate={dayJs()} + /> +