120 lines
7.2 KiB
JavaScript
120 lines
7.2 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { Button, Modal, Alert, Descriptions, QRCode } from 'antd';
|
|
import { PlusCircleOutlined } from '@ant-design/icons';
|
|
import Styles from './web.pc.module.less';
|
|
import Upsert from '../upsert';
|
|
import { OakAttrNotNullException, OakException } from 'oak-domain/lib/types';
|
|
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
|
import { ToYuan } from 'oak-domain/lib/utils/money';
|
|
export function OfflineAccount(props) {
|
|
const { data: account, t, onUpdate, onRemove, onQrCodeClick } = props;
|
|
const { type, channel, name, qrCode, allowDeposit, allowPay, color, enabled, price, taxLossRatio, refundCompensateRatio, refundGapDays, allowWithdrawTransfer, withdrawTransferLossRatio } = account;
|
|
return (<Descriptions style={{ width: 380 }} title={t(`offlineAccount:v.type.${type}`)} extra={<>
|
|
{onUpdate && <Button style={{ marginRight: 4 }} size="small" onClick={() => onUpdate()}>
|
|
{t('common::action.update')}
|
|
</Button>}
|
|
{onRemove && <Button danger size="small" onClick={() => onRemove()}>
|
|
{t('common::action.remove')}
|
|
</Button>}
|
|
</>} column={1} bordered size="small" labelStyle={{ width: 198 }}>
|
|
<Descriptions.Item label={t('offlineAccount:attr.type')}>{t(`offlineAccount:v.type.${type}`)}</Descriptions.Item>
|
|
{channel && <Descriptions.Item label={t(`offlineAccount::label.channel.${type}`)}>{channel}</Descriptions.Item>}
|
|
{name && <Descriptions.Item label={t(`offlineAccount::label.name.${type}`)}>{name}</Descriptions.Item>}
|
|
{qrCode && <Descriptions.Item label={t(`offlineAccount::label.qrCode.${type}`)}>
|
|
{type === 'bank' ? qrCode : <span className={Styles.qrCode} onClick={onQrCodeClick}><QRCode value={qrCode} size={name ? 80 : 128} color={color}/></span>}
|
|
</Descriptions.Item>}
|
|
<Descriptions.Item label={t('offlineAccount:attr.price')}>{ToYuan(price)}{t('common::pay.scale')}</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.allowPay')}>{t(`common::${allowPay}`)}</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.enabled')}>{t(`common::${enabled}`)}</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.taxLossRatio')}>{taxLossRatio}%</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.refundCompensateRatio')}>{refundCompensateRatio}%</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.refundGapDays')}>{refundGapDays}</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.taxLossRatio')}>{taxLossRatio}%</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.allowWithdrawTransfer')}>{t(`common::${allowWithdrawTransfer}`)}</Descriptions.Item>
|
|
<Descriptions.Item label={t('offlineAccount:attr.withdrawTransferLossRatio')}>{withdrawTransferLossRatio}%</Descriptions.Item>
|
|
</Descriptions>);
|
|
}
|
|
export default function render(props) {
|
|
const { accounts, oakFullpath, oakExecutable, systemId, canCreate } = props.data;
|
|
const { t, addItem, execute, clean } = props.methods;
|
|
const [upsertId, setUpsertId] = useState('');
|
|
const getNotNullMessage = (attr) => {
|
|
if (['channel', 'name', 'qrCode'].includes(attr)) {
|
|
const upsertRow = accounts?.find(ele => ele.id === upsertId);
|
|
// @oak-ignore
|
|
return t('notnull', { value: t(`offlineAccount::label.${attr}.${upsertRow.type}`) });
|
|
}
|
|
// @oak-ignore
|
|
return t('notnull', { value: t(`offlineAccount:attr.${attr}`) });
|
|
};
|
|
const errMsg = oakExecutable instanceof OakException && (
|
|
// @oak-ignore
|
|
oakExecutable instanceof OakAttrNotNullException ? getNotNullMessage(oakExecutable.getAttributes()[0]) : t(oakExecutable.message));
|
|
const U = (<Modal destroyOnClose width={920} title={`${t('offlineAccount:name')}${t('common::action.add')}`} open={!!upsertId} onCancel={() => {
|
|
clean();
|
|
setUpsertId('');
|
|
}} closeIcon={null} onOk={async () => {
|
|
await execute();
|
|
setUpsertId('');
|
|
}} okButtonProps={{
|
|
disabled: oakExecutable !== true,
|
|
}} okText={t('common::confirm')} cancelText={(t('common::action.cancel'))}>
|
|
<div style={{ padding: 10 }}>
|
|
{errMsg && <Alert type="error" message={errMsg} style={{ marginBottom: 20 }}/>}
|
|
<Upsert oakPath={`${oakFullpath}.${upsertId}`} systemId={systemId}/>
|
|
</div>
|
|
</Modal>);
|
|
const [showQrCodeId, setShowQrCodeId] = useState('');
|
|
const showQrCodeRow = showQrCodeId ? accounts.find(ele => ele.id === showQrCodeId) : undefined;
|
|
if (accounts && accounts.length > 0) {
|
|
return (<div className={Styles.container}>
|
|
<Alert type='info' message={t('tips')}/>
|
|
{U}
|
|
<div className={Styles.list}>
|
|
{accounts.filter(ele => ele.$$createAt$$ > 1).map((ele, idx) => <div className={Styles.item} key={idx}>
|
|
<OfflineAccount data={ele} t={t} onRemove={ele['#oakLegalActions']?.includes('remove') ? () => {
|
|
Modal.confirm({
|
|
title: t('confirmDelete'),
|
|
content: t('areYouSure'),
|
|
onOk: async () => execute(undefined, undefined, undefined, [
|
|
{
|
|
entity: 'offlineAccount',
|
|
operation: {
|
|
id: await generateNewIdAsync(),
|
|
action: 'remove',
|
|
data: {},
|
|
filter: {
|
|
id: ele.id,
|
|
},
|
|
}
|
|
}
|
|
]),
|
|
});
|
|
} : undefined} onUpdate={ele['#oakLegalActions']?.includes('update') ? () => setUpsertId(ele.id) : undefined} onQrCodeClick={() => setShowQrCodeId(ele.id)}/>
|
|
</div>)}
|
|
</div>
|
|
<div className={Styles.btnBar}>
|
|
{canCreate && <Button type="primary" onClick={() => {
|
|
const id = addItem({ systemId });
|
|
setUpsertId(id);
|
|
}}>
|
|
{t('common::action.add')}
|
|
</Button>}
|
|
</div>
|
|
{showQrCodeRow && <Modal open={!!showQrCodeId} closeIcon={null} footer={null} onCancel={() => setShowQrCodeId('')}>
|
|
<QRCode value={showQrCodeRow.qrCode} size={480} color={showQrCodeRow.color}/>
|
|
</Modal>}
|
|
</div>);
|
|
}
|
|
return (<div className={Styles.container2}>
|
|
<Alert type='info' message={t('tips')}/>
|
|
{U}
|
|
<div className={Styles.body}>
|
|
{canCreate ? <PlusCircleOutlined className={Styles.add} shape="circle" style={{ fontSize: 50 }} onClick={() => {
|
|
const id = addItem({ systemId });
|
|
setUpsertId(id);
|
|
}}/> : t('noData')}
|
|
</div>
|
|
</div>);
|
|
}
|