微信支付相关设置对象的管理
This commit is contained in:
parent
771968ec6b
commit
23d7134152
|
|
@ -1,5 +1,5 @@
|
|||
import { BRC } from '@project/types/RuntimeCxt';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { BRC } from '../types/RuntimeCxt';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
export type AspectDict = {
|
||||
getAccountPayRefunds: (params: {
|
||||
accountId: string;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ import aoCheckers from './accountOper';
|
|||
import payCheckers from './pay';
|
||||
import orderCheckers from './order';
|
||||
import applicationCheckers from './application';
|
||||
import offlineAccountCheckers from './offlineAccount';
|
||||
const checkers = [
|
||||
...aoCheckers,
|
||||
...payCheckers,
|
||||
...orderCheckers,
|
||||
...applicationCheckers,
|
||||
...offlineAccountCheckers,
|
||||
];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
import { Checker } from 'oak-domain/lib/types/Auth';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
declare const checkers: Checker<EntityDict, 'offlineAccount', RuntimeCxt>[];
|
||||
export default checkers;
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import assert from 'assert';
|
||||
import { OakAttrNotNullException, OakInputIllegalException } from 'oak-domain/lib/types';
|
||||
import { pipeline } from 'oak-domain/lib/utils/executor';
|
||||
function checkAttributes(data) {
|
||||
const { type, channel, name, qrCode } = data;
|
||||
switch (type) {
|
||||
case 'bank': {
|
||||
if (!channel || !name || !qrCode) {
|
||||
throw new OakAttrNotNullException('offlineAccount', ['channel', 'name', 'qrCode'].filter(ele => !data[ele]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'shouqianba':
|
||||
case 'wechat':
|
||||
case 'alipay': {
|
||||
if (!name && !qrCode) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['name', 'qrCode'], 'offlineAccount::error.nameQrCodeBothNull');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'others': {
|
||||
if (!name && !qrCode) {
|
||||
throw new OakAttrNotNullException('offlineAccount', ['name', 'qrCode']);
|
||||
}
|
||||
if (!channel) {
|
||||
throw new OakAttrNotNullException('offlineAccount', ['channel']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const checkers = [
|
||||
{
|
||||
entity: 'offlineAccount',
|
||||
action: 'create',
|
||||
type: 'data',
|
||||
checker(data) {
|
||||
assert(!(data instanceof Array));
|
||||
checkAttributes(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
entity: 'offlineAccount',
|
||||
action: 'update',
|
||||
type: 'logicalData',
|
||||
checker: (operation, context) => {
|
||||
const { data, filter } = operation;
|
||||
return pipeline(() => context.select('offlineAccount', {
|
||||
data: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
channel: 1,
|
||||
name: 1,
|
||||
qrCode: 1,
|
||||
},
|
||||
filter
|
||||
}, { dontCollect: true }), (accounts) => {
|
||||
accounts.forEach((ele) => checkAttributes(Object.assign(ele, data)));
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
export default checkers;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { Checker } from 'oak-domain/lib/types/Auth';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
declare const checkers: Checker<EntityDict, 'pay', RuntimeCxt>[];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Checker } from 'oak-domain/lib/types/Auth';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { RuntimeCxt } from '../types/RuntimeCxt';
|
||||
declare const checkers: Checker<EntityDict, 'refund', RuntimeCxt>[];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* 抽象组件在业务层根据EntityDict的重新声明
|
||||
* by Xc 20230807
|
||||
*/
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, ListButtonProps, OakAbsAttrUpsertDef } from 'oak-frontend-base';
|
||||
declare const FilterPanel: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
||||
entity: T;
|
||||
|
|
@ -20,7 +20,7 @@ declare const List: <T extends keyof EntityDict>(props: ReactComponentProps<Enti
|
|||
rowSelection?: any;
|
||||
hideHeader?: boolean | undefined;
|
||||
disableSerialNumber?: boolean | undefined;
|
||||
size?: "small" | "large" | "middle" | undefined;
|
||||
size?: "small" | "middle" | "large" | undefined;
|
||||
scroll?: ({
|
||||
x?: string | number | true | undefined;
|
||||
y?: string | number | undefined;
|
||||
|
|
@ -46,7 +46,7 @@ declare const ListPro: <T extends keyof EntityDict>(props: {
|
|||
tablePagination?: any;
|
||||
rowSelection?: any;
|
||||
disableSerialNumber?: boolean | undefined;
|
||||
size?: "small" | "large" | "middle" | undefined;
|
||||
size?: "small" | "middle" | "large" | undefined;
|
||||
scroll?: any;
|
||||
locale?: any;
|
||||
opWidth?: number | undefined;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '@project/types/PayConfig';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'account', false, {
|
||||
depositMax: number;
|
||||
payConfig: PayConfig;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '@project/types/PayConfig';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'account', false, {
|
||||
depositMax: number;
|
||||
payConfig: PayConfig;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'account', false, {
|
||||
account: RowWithActions<EntityDict, 'account'>;
|
||||
depositMaxCent: number;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'account', false, {
|
||||
account: RowWithActions<EntityDict, 'account'>;
|
||||
depositMaxCent: number;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'accountOper', false, {
|
||||
accountOpers: RowWithActions<EntityDict, 'accountOper'>[];
|
||||
}>): string;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'accountOper', false, {
|
||||
accountOpers: RowWithActions<EntityDict, 'accountOper'>[];
|
||||
}>): string;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from "@project/oak-app-domain";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
export default function Render(props: {
|
||||
accountOpers: EntityDict['accountOper']['OpSchema'][];
|
||||
t: (k: string) => string;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "offlineAccount", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "offlineAccount", true, {
|
||||
systemId: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,27 @@ export default OakComponent({
|
|||
channel: 1,
|
||||
name: 1,
|
||||
qrCode: 1,
|
||||
desc: 1,
|
||||
allowDeposit: 1,
|
||||
allowPay: 1,
|
||||
systemId: 1,
|
||||
price: 1,
|
||||
enabled: 1,
|
||||
},
|
||||
formData({ data }) {
|
||||
properties: {
|
||||
systemId: '',
|
||||
},
|
||||
formData({ data, legalActions }) {
|
||||
return {
|
||||
accounts: data,
|
||||
accounts: data.map((ele) => {
|
||||
const { type } = ele;
|
||||
const color = this.features.style.getColor('offlineAccount', 'type', type);
|
||||
return {
|
||||
color,
|
||||
...ele,
|
||||
};
|
||||
}),
|
||||
canCreate: legalActions?.includes('create'),
|
||||
};
|
||||
}
|
||||
},
|
||||
actions: ['create', 'update', 'remove'],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"tips": "线下账户是需要system的相关工作人员手动同步收款和打款结果的账户",
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
|
|
@ -2,5 +2,9 @@ import React from 'react';
|
|||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'offlineAccount', true, {
|
||||
accounts: RowWithActions<EntityDict, 'offlineAccount'>[];
|
||||
accounts?: (RowWithActions<EntityDict, 'offlineAccount'> & {
|
||||
color: string;
|
||||
})[];
|
||||
systemId: string;
|
||||
canCreate?: boolean;
|
||||
}>): React.JSX.Element;
|
||||
|
|
|
|||
|
|
@ -1,32 +1,110 @@
|
|||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Modal, Alert, Descriptions, QRCode } from 'antd';
|
||||
import { PlusCircleOutlined } from '@ant-design/icons';
|
||||
import { Detail } from '../../../components/AbstractComponents';
|
||||
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';
|
||||
function OfflineAccount(props) {
|
||||
const { account, t, onUpdate, onRemove, onQrCodeClick } = props;
|
||||
const { type, channel, name, qrCode, allowDeposit, allowPay, color, enabled, price } = account;
|
||||
const legalActions = account['#oakLegalActions'];
|
||||
return (<Descriptions style={{ width: 280, height: 415 }} title={t(`offlineAccount:v.type.${type}`)} extra={<>
|
||||
{legalActions.includes('update') && <Button style={{ marginRight: 4 }} size="small" onClick={() => onUpdate()}>
|
||||
{t('common::action.update')}
|
||||
</Button>}
|
||||
{legalActions.includes('remove') && <Button danger size="small" onClick={() => onRemove()}>
|
||||
{t('common::action.remove')}
|
||||
</Button>}
|
||||
</>} column={1} bordered size="small" labelStyle={{ width: 98 }}>
|
||||
<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')}>{price}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('offlineAccount:attr.allowDeposit')}>{t(`common::${allowDeposit}`)}</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>);
|
||||
}
|
||||
export default function render(props) {
|
||||
const { accounts } = props.data;
|
||||
const { t } = props.methods;
|
||||
if (accounts.length > 0) {
|
||||
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);
|
||||
return t('notnull', { value: t(`offlineAccount::label.${attr}.${upsertRow.type}`) });
|
||||
}
|
||||
return t('notnull', { value: t(`offlineAccount:attr.${attr}`) });
|
||||
};
|
||||
const errMsg = oakExecutable instanceof OakException && (oakExecutable instanceof OakAttrNotNullException ? getNotNullMessage(oakExecutable.getAttributes()[0]) : t(oakExecutable.message));
|
||||
const U = (<Modal destroyOnClose 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.map((ele) => <div className={Styles.item}>
|
||||
<Detail entity="offlineAccount" data={ele} attributes={[
|
||||
'id',
|
||||
'type',
|
||||
'name',
|
||||
'allowDeposit',
|
||||
'allowPay'
|
||||
]} column={1} bordered={true}/>
|
||||
</div>)}
|
||||
{accounts.filter(ele => ele.$$createAt$$ > 1).map((ele, idx) => <div className={Styles.item} key={idx}>
|
||||
<OfflineAccount account={ele} t={t} onRemove={() => {
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
||||
]),
|
||||
});
|
||||
}} onUpdate={() => setUpsertId(ele.id)} onQrCodeClick={() => setShowQrCodeId(ele.id)}/>
|
||||
</div>)}
|
||||
</div>
|
||||
<div className={Styles.btnBar}>
|
||||
<Button>
|
||||
{canCreate && <Button type="primary" onClick={() => {
|
||||
const id = addItem({ systemId });
|
||||
setUpsertId(id);
|
||||
}}>
|
||||
{t('common::action.add')}
|
||||
</Button>
|
||||
</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}>
|
||||
<Button icon={<PlusCircleOutlined style={{ fontSize: 50 }}/>}/>
|
||||
<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>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ export default OakComponent({
|
|||
channel: 1,
|
||||
name: 1,
|
||||
qrCode: 1,
|
||||
desc: 1,
|
||||
allowDeposit: 1,
|
||||
allowPay: 1,
|
||||
systemId: 1,
|
||||
},
|
||||
isList: false,
|
||||
|
|
@ -15,4 +16,16 @@ export default OakComponent({
|
|||
offlineAccount: data,
|
||||
};
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
if (this.isCreation()) {
|
||||
this.update({
|
||||
allowDeposit: false,
|
||||
allowPay: false,
|
||||
price: 0,
|
||||
enabled: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,26 @@
|
|||
{
|
||||
"tips": "线下交易账户是需要人工同步收款和打款行为的账户",
|
||||
"label": {
|
||||
"channel": {
|
||||
"bank": "银行及所属支行"
|
||||
}
|
||||
},
|
||||
"placeholder": {
|
||||
"channel": {
|
||||
"bank": "银行-所属支行"
|
||||
"bank": "银行/支行",
|
||||
"others": "请输入途径名称"
|
||||
},
|
||||
"name": {
|
||||
"bank": "输入户主姓名",
|
||||
"alipay": "输入支付宝帐号",
|
||||
"wechat": "输入微信号",
|
||||
"shouqianba": "输入收钱吧商户号",
|
||||
"others": "输入该收款途径的唯一账号"
|
||||
},
|
||||
"qrCode": {
|
||||
"bank": "请输入银行账号",
|
||||
"alipay": "请将二维码解析后的字符串填入",
|
||||
"wechat": "请将二维码解析后的字符串填入",
|
||||
"shouqianba": "请将二维码解析后的字符串填入",
|
||||
"others": "请将二维码解析后的字符串填入"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"allowDeposit": "是否允许用户在系统中主动向此账号发起充值",
|
||||
"allowPay": "是否允许用户在系统中主动向此账号发起支付"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,61 @@
|
|||
import React from 'react';
|
||||
import { Alert, Form, Input, Select } from 'antd';
|
||||
import { Form, Switch, Input, Select } from 'antd';
|
||||
export default function render(props) {
|
||||
const { offlineAccount } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
if (offlineAccount) {
|
||||
return (<Form labelCol={{ span: 6 }} wrapperCol={{ span: 12 }} layout="horizontal" style={{ minWidth: 600 }}>
|
||||
<Alert type='info' message={t('tips')}/>
|
||||
<Form.Item label={t('offlineAccount:attr.type')}>
|
||||
<Select value={offlineAccount.type} options={['bank', 'alipay', 'wechat', 'shouqianba'].map(ele => ({
|
||||
<Form.Item label={t('offlineAccount:attr.type')} required>
|
||||
<Select value={offlineAccount.type} options={['bank', 'alipay', 'wechat', 'shouqianba', 'others'].map(ele => ({
|
||||
label: t(`offlineAccount:v.type.${ele}`),
|
||||
value: ele,
|
||||
}))}/>
|
||||
}))} onSelect={(value) => update({ type: value })}/>
|
||||
</Form.Item>
|
||||
{offlineAccount.type === 'bank' && <Form.Item label={t(`channle.${offlineAccount.type}`)}>
|
||||
{['bank', 'others'].includes(offlineAccount.type) && <Form.Item label={t(`offlineAccount::label.channel.${offlineAccount.type}`)} required>
|
||||
<Input value={offlineAccount.channel || ''} onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
update({
|
||||
channel: value,
|
||||
});
|
||||
}} placeholder={t('placeholder.channel.bank')}/>
|
||||
}} placeholder={t(`placeholder.channel.${offlineAccount.type}`)}/>
|
||||
</Form.Item>}
|
||||
{!!offlineAccount.type && <Form.Item label={t(`offlineAccount::label.name.${offlineAccount.type}`)} required={['bank'].includes(offlineAccount.type)}>
|
||||
<Input value={offlineAccount.name || ''} onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
update({
|
||||
name: value,
|
||||
});
|
||||
}} placeholder={t(`placeholder.name.${offlineAccount.type}`)}/>
|
||||
</Form.Item>}
|
||||
{!!offlineAccount.type && <Form.Item label={t(`offlineAccount::label.qrCode.${offlineAccount.type}`)} required={offlineAccount.type === 'bank'}>
|
||||
{offlineAccount.type === 'bank' && <Input value={offlineAccount.qrCode || ''} onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
update({
|
||||
qrCode: value,
|
||||
});
|
||||
}} placeholder={t(`placeholder.qrCode.${offlineAccount.type}`)}/>}
|
||||
{offlineAccount.type !== 'bank' && <Input.TextArea rows={8} value={offlineAccount.qrCode || ''} onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
update({
|
||||
qrCode: value,
|
||||
});
|
||||
}} placeholder={t(`placeholder.qrCode.${offlineAccount.type}`)}/>}
|
||||
</Form.Item>}
|
||||
{!!offlineAccount.type && <Form.Item label={t('offlineAccount:attr.allowDeposit')} required help={t('help.allowDeposit')}>
|
||||
<Switch value={offlineAccount.allowDeposit} onChange={(allowDeposit) => {
|
||||
update({ allowDeposit });
|
||||
}}/>
|
||||
</Form.Item>}
|
||||
{!!offlineAccount.type && <Form.Item label={t('offlineAccount:attr.allowPay')} required help={t('help.allowPay')}>
|
||||
<Switch value={offlineAccount.allowPay} onChange={(allowPay) => {
|
||||
update({ allowPay });
|
||||
}}/>
|
||||
</Form.Item>}
|
||||
<Form.Item label={t('offlineAccount:attr.enabled')} required>
|
||||
<Switch value={offlineAccount.enabled} onChange={(enabled) => {
|
||||
update({ enabled });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</Form>);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EntityDict } from "@project/oak-app-domain";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "order", false, {
|
||||
accountId: string;
|
||||
accountAvailMax: number;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, keyof EntityDict, false, {
|
||||
payConfig: PayConfig;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, keyof EntityDict, false, {
|
||||
payConfig: PayConfig;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export declare function RenderOffline(props: {
|
||||
pay: RowWithActions<EntityDict, 'pay'>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export declare function RenderOffline(props: {
|
||||
pay: RowWithActions<EntityDict, 'pay'>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
pays: (RowWithActions<EntityDict, 'pay'> & {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import { composeServerUrl } from 'oak-general-business/es/utils/domain';
|
||||
export default OakComponent({
|
||||
entity: 'system',
|
||||
isList: false,
|
||||
projection: {
|
||||
id: 1,
|
||||
payConfig: 1,
|
||||
wpAccount$system: {
|
||||
$entity: 'wpAccount',
|
||||
data: {
|
||||
|
|
@ -17,25 +15,12 @@ export default OakComponent({
|
|||
id: 1,
|
||||
},
|
||||
},
|
||||
domain$system: {
|
||||
$entity: 'domain',
|
||||
data: {
|
||||
id: 1,
|
||||
protocol: 1,
|
||||
url: 1,
|
||||
apiPath: 1,
|
||||
port: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
formData({ data, features }) {
|
||||
const operation = this.state.oakFullpath && this.features.runningTree.getOperations(this.state.oakFullpath);
|
||||
const domain = data && data.domain$system[0];
|
||||
const serverUrl = domain && composeServerUrl(domain);
|
||||
return {
|
||||
operation: operation && operation[0].operation,
|
||||
system: data,
|
||||
serverUrl,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export declare function registerPayChannelConfigDict<ED extends EntityDict & BaseEntityDict, T extends keyof ED>(entity: T, component: (option: {
|
||||
oakPath: string;
|
||||
systemId: string;
|
||||
}) => React.ReactElement): void;
|
||||
export default function render(props: WebComponentProps<EntityDict, 'system', false, {
|
||||
system: RowWithActions<EntityDict, 'system'>;
|
||||
operation?: EntityDict['system']['Update'];
|
||||
|
|
|
|||
|
|
@ -2,20 +2,37 @@ import React, { useState } from 'react';
|
|||
import { Tabs } from 'antd';
|
||||
import Styles from './web.pc.module.less';
|
||||
import OfflineConfig from '../../offlineAccount/config';
|
||||
import WpAccountConfig from '../../wpAccount/config';
|
||||
const PayChannelConfigDict = {
|
||||
'wpAccount': WpAccountConfig,
|
||||
};
|
||||
export function registerPayChannelConfigDict(entity, component) {
|
||||
PayChannelConfigDict[entity] = component;
|
||||
}
|
||||
export default function render(props) {
|
||||
const { system, oakFullpath, operation, oakDirty, serverUrl, oakExecutable } = props.data;
|
||||
const { t, update, setMessage, execute } = props.methods;
|
||||
const [key, setKey] = useState('');
|
||||
if (system && oakFullpath) {
|
||||
return (<div className={Styles.container}>
|
||||
<Tabs tabPosition="left" items={[
|
||||
<Tabs className={Styles.tabs} tabPosition="left" items={[
|
||||
{
|
||||
label: (<div className={Styles.systemLabel}>
|
||||
{t('system')}
|
||||
{t('offlineAccount:name')}
|
||||
</div>),
|
||||
key: 'offlineAccount',
|
||||
children: (<OfflineConfig oakPath={`${oakFullpath}.offlineAccount$entity`}/>),
|
||||
children: (<OfflineConfig oakPath={`${oakFullpath}.offlineAccount$system`} systemId={system.id}/>),
|
||||
},
|
||||
...Object.keys(PayChannelConfigDict).map((ele) => {
|
||||
const C = PayChannelConfigDict[ele];
|
||||
return {
|
||||
label: (<div className={Styles.systemLabel}>
|
||||
{t(`${ele}:name`)}
|
||||
</div>),
|
||||
key: 'ele',
|
||||
children: <C oakPath={`${oakFullpath}.${ele}$system`} systemId={system.id}/>
|
||||
};
|
||||
})
|
||||
]}/>
|
||||
</div>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { AccountPayConfig } from '@project/types/PayConfig';
|
||||
import { AccountPayConfig } from '../../../types/PayConfig';
|
||||
import React from 'react';
|
||||
export default function Account(props: {
|
||||
config: AccountPayConfig;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { PayConfig, ConfigBase } from '@project/types/PayConfig';
|
||||
import { PayConfig, ConfigBase } from '../../../types/PayConfig';
|
||||
type FC<T extends ConfigBase> = React.FC<{
|
||||
config: T;
|
||||
update: (config: Omit<T, 'channel'>) => void;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { OfflinePayConfig } from '@project/types/PayConfig';
|
||||
import { OfflinePayConfig } from '../../../types/PayConfig';
|
||||
export default function Offline(props: {
|
||||
config: OfflinePayConfig;
|
||||
update: (config: Omit<OfflinePayConfig, 'channel'>) => void;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { WechatPayConfig } from '@project/types/PayConfig';
|
||||
import { WechatPayConfig } from '../../../types/PayConfig';
|
||||
import React from 'react';
|
||||
export default function WechatPay(props: {
|
||||
config: WechatPayConfig;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wechatPay", false, {
|
||||
systemId: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { composeServerUrl } from "oak-general-business/es/utils/domain";
|
||||
export default OakComponent({
|
||||
entity: 'wechatPay',
|
||||
projection: {
|
||||
id: 1,
|
||||
refundNotifyUrl: 1,
|
||||
payNotifyUrl: 1,
|
||||
system: {
|
||||
id: 1,
|
||||
domain$system: {
|
||||
$entity: 'domain',
|
||||
data: {
|
||||
id: 1,
|
||||
protocol: 1,
|
||||
url: 1,
|
||||
apiPath: 1,
|
||||
port: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
isList: false,
|
||||
formData({ data }) {
|
||||
const domain = data && data.system?.domain$system?.[0];
|
||||
const serverUrl = domain && composeServerUrl(domain);
|
||||
return {
|
||||
wechatPay: data,
|
||||
serverUrl,
|
||||
};
|
||||
},
|
||||
properties: {
|
||||
systemId: '',
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
const { systemId } = this.props;
|
||||
if (this.isCreation()) {
|
||||
this.update({
|
||||
systemId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"placeholder": {
|
||||
"lossRatio": "填百分比(0.6就代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import React from 'react';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'wechatPay', false, {
|
||||
wechatPay?: (RowWithActions<EntityDict, 'wechatPay'>);
|
||||
serverUrl: string;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { Form, Input } from 'antd';
|
||||
export default function render(props) {
|
||||
const { wechatPay, serverUrl } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
if (wechatPay) {
|
||||
return (<>
|
||||
<Form.Item label={t('wechatPay:attr.payNotifyUrl')}>
|
||||
<Input prefix={`${serverUrl}/endpoint`} suffix='/${payId}' value={wechatPay.payNotifyUrl} placeholder={t('placeholder.payNotifyUrl')} onChange={({ currentTarget }) => {
|
||||
const payNotifyUrl = currentTarget.value;
|
||||
update({ payNotifyUrl });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wechatPay:attr.refundNotifyUrl')}>
|
||||
<Input prefix={`${serverUrl}/endpoint`} suffix='/${refundId}' value={wechatPay.refundNotifyUrl} placeholder={t('placeholder.refundNotifyUrl')} onChange={({ currentTarget }) => {
|
||||
const refundNotifyUrl = currentTarget.value;
|
||||
update({ refundNotifyUrl });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Detail(props: {
|
||||
createAt?: string;
|
||||
withdrawMethod?: 'refund' | 'channel';
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function Detail(props) {
|
|||
<Steps current={step}>
|
||||
<Steps.Step title={<span className={step >= 0 ? classNames(Styles.label, Styles.active) : Styles.label}>{t('steps.1.title')}</span>} description={<span className={step >= 0 ? classNames(Styles.label, Styles.active) : Styles.label}>{createAt}</span>} key="1"/>
|
||||
<Steps.Step title={<span className={step >= 1 ? classNames(Styles.label, Styles.active) : Styles.label}>{t('steps.2.title')}</span>} description={<span className={step >= 1 ? classNames(Styles.label, Styles.active) : Styles.label}>{t(`method.v.${withdrawMethod}`)}</span>} key="2"/>
|
||||
<Steps.Step title={<span className={step >= 2 ? classNames(Styles.label, iState === 'failed' ? Styles.failed : Styles.success) : Styles.label}>{iState === 'failed' ? t('steps.3.failed') : (iState === 'partiallySuccess' ? t('steps.3.partiallySuccess') : t('steps.3.success'))}</span>} key="3"/>
|
||||
<Steps.Step title={<span className={step >= 2 ? classNames(Styles.label, iState === 'failed' ? Styles.failed : Styles.success) : Styles.label}>{iState === 'failed' ? t('steps.3.failed') : (iState === 'partiallySuccessful' ? t('steps.3.partiallySuccess') : t('steps.3.success'))}</span>} key="3"/>
|
||||
</Steps>
|
||||
</div>
|
||||
{refundData.map((data, idx) => (<div className={Styles.refundItem} key={idx}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Detail(props: {
|
||||
createAt?: string;
|
||||
withdrawMethod?: 'refund' | 'channel';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from "@project/oak-app-domain";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'withdrawChannel', true, {
|
||||
channels: RowWithActions<EntityDict, 'withdrawChannel'>[];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from "@project/oak-app-domain";
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'withdrawChannel', false, {
|
||||
channel: RowWithActions<EntityDict, 'withdrawChannel'>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wpAccount", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
export default OakComponent({
|
||||
entity: 'wpAccount',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
mchId: 1,
|
||||
refundGapDays: 1,
|
||||
enabled: 1,
|
||||
},
|
||||
formData({ data, legalActions }) {
|
||||
return {
|
||||
accounts: data,
|
||||
canCreate: legalActions?.includes('create'),
|
||||
};
|
||||
},
|
||||
actions: ['create', 'update', 'remove'],
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"tips": "微信支付账户是用来配置微信支付的账户相关信息",
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'wpAccount', true, {
|
||||
accounts?: (RowWithActions<EntityDict, 'wpAccount'> & {})[];
|
||||
systemId: string;
|
||||
canCreate?: boolean;
|
||||
}>): React.JSX.Element;
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button, Modal, Alert, Descriptions, Tabs } from 'antd';
|
||||
import { PlusCircleOutlined } from '@ant-design/icons';
|
||||
import Styles from './web.pc.module.less';
|
||||
import Upsert from '../upsert';
|
||||
import WpProductConfig from '../../wpProduct/config';
|
||||
import { OakAttrNotNullException, OakException } from 'oak-domain/lib/types';
|
||||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
function WpAccount(props) {
|
||||
const { account, t, onUpdate, onRemove, oakFullpath, systemId } = props;
|
||||
const { refundGapDays, mchId, enabled, price } = account;
|
||||
const legalActions = account['#oakLegalActions'];
|
||||
const [activeKey, setActiveKey] = useState("1");
|
||||
return (<Tabs activeKey={activeKey} onTabClick={(activeKey) => {
|
||||
setActiveKey(activeKey);
|
||||
}} tabBarExtraContent={activeKey === "1" && <>
|
||||
{legalActions.includes('update') && <Button style={{ marginRight: 4 }} size="small" onClick={() => onUpdate()}>
|
||||
{t('common::action.update')}
|
||||
</Button>}
|
||||
{legalActions.includes('remove') && <Button danger size="small" onClick={() => onRemove()}>
|
||||
{t('common::action.remove')}
|
||||
</Button>}
|
||||
</>} style={{ width: 380, height: 520 }} items={[
|
||||
{
|
||||
key: '1',
|
||||
label: t('common::action.detail'),
|
||||
children: (<Descriptions column={1} bordered size="small">
|
||||
<Descriptions.Item label={t('wpAccount:attr.mchId')}>{mchId}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('wpAccount:attr.price')}>{price}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('wpAccount:attr.refundGapDays')}>{refundGapDays}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('wpAccount:attr.enabled')}>{t(`common::${enabled}`)}</Descriptions.Item>
|
||||
</Descriptions>)
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: t('wpProduct:name'),
|
||||
children: (<WpProductConfig oakPath={`$$wpProduct-${account.id}`} systemId={systemId} wpAccountId={account.id}/>)
|
||||
}
|
||||
]}/>);
|
||||
}
|
||||
export default function render(props) {
|
||||
const { accounts, oakFullpath, oakExecutable, canCreate, systemId } = props.data;
|
||||
const { t, addItem, execute, clean } = props.methods;
|
||||
const getNotNullMessage = (entity, attr) => {
|
||||
return t('notnull', { value: t(`${entity}:attr.${attr}`) });
|
||||
};
|
||||
const errMsg = oakExecutable instanceof OakException && (oakExecutable instanceof OakAttrNotNullException ? getNotNullMessage(oakExecutable.getEntity(), oakExecutable.getAttributes()[0]) : t(oakExecutable.message));
|
||||
const [upsertId, setUpsertId] = useState('');
|
||||
const U = (<Modal width={920} destroyOnClose title={`${t('wpAccount: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>);
|
||||
if (accounts && accounts?.length) {
|
||||
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}>
|
||||
<WpAccount oakFullpath={oakFullpath} systemId={systemId} account={ele} t={t} onRemove={() => {
|
||||
Modal.confirm({
|
||||
title: t('confirmDelete'),
|
||||
content: t('areYouSure'),
|
||||
onOk: async () => execute(undefined, undefined, undefined, [
|
||||
{
|
||||
entity: 'wpAccount',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: ele.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
]),
|
||||
});
|
||||
}} onUpdate={() => setUpsertId(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>
|
||||
</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>);
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wpAccount", false, {
|
||||
systemId: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
export default OakComponent({
|
||||
entity: 'wpAccount',
|
||||
isList: false,
|
||||
projection: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
mchId: 1,
|
||||
refundGapDays: 1,
|
||||
enabled: 1,
|
||||
wechatPay: {
|
||||
id: 1,
|
||||
payNotifyUrl: 1,
|
||||
refundNotifyUrl: 1,
|
||||
},
|
||||
taxlossRatio: 1,
|
||||
publicKeyFilePath: 1,
|
||||
privateKeyFilePath: 1,
|
||||
refundLossFloor: 1,
|
||||
refundLossRatio: 1,
|
||||
apiV3Key: 1,
|
||||
systemId: 1,
|
||||
},
|
||||
formData({ data, features }) {
|
||||
const { systemId } = this.props;
|
||||
const [wechatPay] = features.cache.get('wechatPay', {
|
||||
data: {
|
||||
id: 1,
|
||||
refundNotifyUrl: 1,
|
||||
payNotifyUrl: 1,
|
||||
},
|
||||
filter: {
|
||||
systemId,
|
||||
}
|
||||
});
|
||||
return {
|
||||
wpAccount: data,
|
||||
wechatPay,
|
||||
};
|
||||
},
|
||||
properties: {
|
||||
systemId: '',
|
||||
},
|
||||
lifetimes: {
|
||||
async ready() {
|
||||
if (this.isCreation()) {
|
||||
this.update({
|
||||
price: 0,
|
||||
enabled: true,
|
||||
taxlossRatio: 0.6,
|
||||
});
|
||||
const { systemId } = this.props;
|
||||
const { data: [wechatPay] } = await this.features.cache.refresh('wechatPay', {
|
||||
data: {
|
||||
id: 1,
|
||||
refundNotifyUrl: 1,
|
||||
payNotifyUrl: 1,
|
||||
},
|
||||
filter: {
|
||||
systemId,
|
||||
}
|
||||
});
|
||||
if (wechatPay) {
|
||||
this.update({
|
||||
wechatPayId: wechatPay.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"placeholder": {
|
||||
"privateKeyFilePath": "服务器上存放apiclient_key.pem的路径,注意访问权限",
|
||||
"publicKeyFilePath": "服务器上存放apiclient_cert.pem的路径,注意访问权限",
|
||||
"taxlossRatio": "微信支付收取的手续费,一般为0.6(代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint",
|
||||
"apiV3Key": "需要登录商户后台获取",
|
||||
"refundGapDays": "超过这个天数后无法退款",
|
||||
"refundLossRatio": "退款时将按这个百分比扣除损耗(0.6就代表千分之六)",
|
||||
"refundLossFloor": "退款时按位向下取整(如按元取整,则忽略角位和分位)"
|
||||
},
|
||||
"wechatPayIsShared": "以上配置是全局的,请谨慎修改"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'wpAccount', false, {
|
||||
wpAccount?: (RowWithActions<EntityDict, 'wpAccount'> & {});
|
||||
wechatPay?: EntityDict['wechatPay']['OpSchema'];
|
||||
systemId: string;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import React from 'react';
|
||||
import { Form, Switch, InputNumber, Input, Radio, Divider } from 'antd';
|
||||
import Styles from './web.pc.module.less';
|
||||
import WechatPayUpsert from '../../wechatPay/upsert';
|
||||
export default function render(props) {
|
||||
const { wpAccount, wechatPay, oakFullpath, systemId } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
if (wpAccount) {
|
||||
return (<Form labelCol={{ span: 8 }} wrapperCol={{ span: 12 }} layout="horizontal" style={{ minWidth: 860 }}>
|
||||
{(!wechatPay || wechatPay.$$createAt$$ === 1) && <WechatPayUpsert oakPath={`${oakFullpath}.wechatPay`} systemId={systemId} key="wpCreate"/>}
|
||||
{wpAccount.wechatPayId && <WechatPayUpsert oakPath={`${oakFullpath}.wechatPay`} systemId={systemId} key="wpUpdate" oakId={wpAccount.wechatPayId}/>}
|
||||
<Form.Item label="说明">
|
||||
<div className={Styles.tips}>
|
||||
{t('wechatPayIsShared')}
|
||||
</div>
|
||||
</Form.Item>
|
||||
<Divider />
|
||||
<Form.Item label={t('wpAccount:attr.mchId')}>
|
||||
<Input maxLength={32} value={wpAccount.mchId} onChange={({ currentTarget }) => {
|
||||
const mchId = currentTarget.value;
|
||||
update({ mchId });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.privateKeyFilePath')}>
|
||||
<Input value={wpAccount.privateKeyFilePath} placeholder={t('placeholder.privateKeyFilePath')} onChange={({ currentTarget }) => {
|
||||
const privateKeyFilePath = currentTarget.value;
|
||||
update({ privateKeyFilePath });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.publicKeyFilePath')}>
|
||||
<Input value={wpAccount.publicKeyFilePath} placeholder={t('placeholder.publicKeyFilePath')} onChange={({ currentTarget }) => {
|
||||
const publicKeyFilePath = currentTarget.value;
|
||||
update({ publicKeyFilePath });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.apiV3Key')}>
|
||||
<Input value={wpAccount.apiV3Key} placeholder={t('placeholder.apiV3Key')} onChange={({ currentTarget }) => {
|
||||
const apiV3Key = currentTarget.value;
|
||||
update({ apiV3Key });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wechatPay:attr.taxlossRatio')} help={t('placeholder.taxlossRatio')}>
|
||||
<InputNumber value={wpAccount.taxlossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxlossRatio = value;
|
||||
update({ taxlossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundGapDays')} help={t('placeholder.refundGapDays')}>
|
||||
<InputNumber value={wpAccount.refundGapDays} max={365} min={7} addonAfter={"天"} step={1} onChange={(value) => {
|
||||
const refundGapDays = value;
|
||||
update({ refundGapDays });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundLossRatio')} help={t('placeholder.refundLossRatio')}>
|
||||
<InputNumber value={wpAccount.refundLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const refundLossRatio = value;
|
||||
update({ refundLossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundLossFloor')} help={t('placeholder.refundLossFloor')}>
|
||||
<Radio.Group onChange={({ target }) => {
|
||||
const { value } = target;
|
||||
const refundLossFloor = value;
|
||||
update({ refundLossFloor });
|
||||
}} value={wpAccount.refundLossFloor}>
|
||||
<Radio value={"jiao"}>角</Radio>
|
||||
<Radio value={"yuan"}>元</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.enabled')} required>
|
||||
<Switch value={wpAccount.enabled} onChange={(enabled) => {
|
||||
update({ enabled });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</Form>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wpProduct", true, {
|
||||
systemId: string;
|
||||
wpAccountId: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
export default OakComponent({
|
||||
entity: 'wpProduct',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
wpAccountId: 1,
|
||||
applicationId: 1,
|
||||
application: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
name: 1,
|
||||
},
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const { wpAccountId } = this.props;
|
||||
return {
|
||||
wpAccountId,
|
||||
};
|
||||
}
|
||||
}
|
||||
],
|
||||
properties: {
|
||||
systemId: '',
|
||||
wpAccountId: '',
|
||||
},
|
||||
formData({ data, legalActions }) {
|
||||
return {
|
||||
wpProducts: data,
|
||||
canCreate: legalActions?.includes('create'),
|
||||
};
|
||||
},
|
||||
actions: ['create', 'update', 'remove'],
|
||||
lifetimes: {
|
||||
ready() {
|
||||
const { systemId } = this.props;
|
||||
this.features.cache.refresh('application', {
|
||||
data: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
type: 1,
|
||||
},
|
||||
filter: {
|
||||
systemId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import React from 'react';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'wpProduct', true, {
|
||||
wpProducts?: (RowWithActions<EntityDict, 'wpProduct'> & {})[];
|
||||
systemId: string;
|
||||
canCreate?: boolean;
|
||||
wpAccountId: string;
|
||||
}>): React.JSX.Element;
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button, Modal, Alert } 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';
|
||||
function WpProduct(props) {
|
||||
return null;
|
||||
}
|
||||
export default function render(props) {
|
||||
const { wpAccountId, wpProducts, oakFullpath, oakExecutable, canCreate, systemId } = props.data;
|
||||
const { t, addItem, execute, clean } = props.methods;
|
||||
const getNotNullMessage = (entity, attr) => {
|
||||
return t('notnull', { value: t(`${entity}:attr.${attr}`) });
|
||||
};
|
||||
const errMsg = oakExecutable instanceof OakException && (oakExecutable instanceof OakAttrNotNullException ? getNotNullMessage(oakExecutable.getEntity(), oakExecutable.getAttributes()[0]) : t(oakExecutable.message));
|
||||
const [upsertId, setUpsertId] = useState('');
|
||||
const U = (<Modal width={420} destroyOnClose title={`${t('wpProduct:name')}${t('common::action.update')}`} 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} wpAccountId={wpAccountId}/>
|
||||
</div>
|
||||
</Modal>);
|
||||
if (wpProducts && wpProducts.length) {
|
||||
return (<div className={Styles.container}>
|
||||
<Alert type='info' message={t('tips')}/>
|
||||
{U}
|
||||
<div className={Styles.list}>
|
||||
{wpProducts.filter(ele => ele.$$createAt$$ > 1).map((ele, idx) => <div className={Styles.item} key={idx}>
|
||||
<WpProduct wpProduct={ele} t={t} onRemove={() => {
|
||||
Modal.confirm({
|
||||
title: t('confirmDelete'),
|
||||
content: t('areYouSure'),
|
||||
onOk: async () => execute(undefined, undefined, undefined, [
|
||||
{
|
||||
entity: 'wpProduct',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: ele.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
]),
|
||||
});
|
||||
}} onUpdate={() => setUpsertId(ele.id)}/>
|
||||
</div>)}
|
||||
</div>
|
||||
<div className={Styles.btnBar}>
|
||||
{canCreate && <Button type="primary" onClick={() => {
|
||||
const id = addItem({});
|
||||
setUpsertId(id);
|
||||
}}>
|
||||
{t('common::action.add')}
|
||||
</Button>}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
return (<div className={Styles.container2}>
|
||||
{U}
|
||||
<div className={Styles.body}>
|
||||
{canCreate ? <PlusCircleOutlined className={Styles.add} shape="circle" style={{ fontSize: 50 }} onClick={() => {
|
||||
const id = addItem({});
|
||||
setUpsertId(id);
|
||||
}}/> : t('noData')}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "wpProduct", false, {
|
||||
systemId: string;
|
||||
wpAccountId: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import { getAppTypeFromProductType } from "../../../utils/wpProduct";
|
||||
export default OakComponent({
|
||||
entity: 'wpProduct',
|
||||
isList: false,
|
||||
projection: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
wpAccountId: 1,
|
||||
applicationId: 1,
|
||||
application: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
name: 1,
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
systemId: '',
|
||||
wpAccountId: '',
|
||||
},
|
||||
formData({ data, features }) {
|
||||
const { systemId } = this.props;
|
||||
const applications = data?.type && features.cache.get('application', {
|
||||
data: {
|
||||
id: 1,
|
||||
name: 1,
|
||||
type: 1,
|
||||
},
|
||||
filter: {
|
||||
systemId,
|
||||
wpProduct$application: {
|
||||
"#sqp": 'not in',
|
||||
},
|
||||
type: {
|
||||
$in: getAppTypeFromProductType(data.type),
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
applications,
|
||||
wpProduct: data,
|
||||
};
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
if (this.isCreation()) {
|
||||
const { wpAccountId } = this.props;
|
||||
this.update({
|
||||
wpAccountId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import React from 'react';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
export default function render(props: WebComponentProps<EntityDict, 'wpProduct', false, {
|
||||
wpProduct?: (RowWithActions<EntityDict, 'wpProduct'> & {});
|
||||
applications?: EntityDict['application']['OpSchema'][];
|
||||
systemId: string;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { Form, Select } from 'antd';
|
||||
export default function render(props) {
|
||||
const { wpProduct, applications, oakFullpath, systemId } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
if (wpProduct) {
|
||||
return (<Form labelCol={{ span: 4 }} wrapperCol={{ span: 12 }} layout="horizontal" style={{ minWidth: 460 }}>
|
||||
<Form.Item label={t('wpProduct:attr.type')}>
|
||||
<Select value={wpProduct.type} options={['native', 'mp', 'jsapi', 'h5', 'app'].map(ele => ({
|
||||
label: t(`wpProduct:v.type.${ele}`),
|
||||
value: ele,
|
||||
}))} onSelect={(value) => update({ type: value })}/>
|
||||
</Form.Item>
|
||||
{wpProduct.type && applications && (<Form.Item label={t('wpProduct:attr.application')}>
|
||||
<Select value={wpProduct.applicationId} options={applications.map(ele => ({
|
||||
label: ele.name,
|
||||
value: ele.id,
|
||||
}))} onSelect={(value) => update({ applicationId: value })}/>
|
||||
</Form.Item>)}
|
||||
</Form>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { AttrUpdateMatrix } from 'oak-domain/lib/types/EntityDesc';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
declare const attrUpdateMatrix: AttrUpdateMatrix<EntityDict>;
|
||||
export default attrUpdateMatrix;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,70 @@ const attrUpdateMatrix = {
|
|||
meta: {
|
||||
actions: ['succeed', 'fail', 'succeedPartially'],
|
||||
},
|
||||
}
|
||||
},
|
||||
offlineAccount: {
|
||||
name: {
|
||||
actions: ['update'],
|
||||
filter: {
|
||||
// 只有从来没用过的才能改
|
||||
sysAccountOper$entity: {
|
||||
"#sqp": 'not in',
|
||||
}
|
||||
}
|
||||
},
|
||||
channel: {
|
||||
actions: ['update'],
|
||||
filter: {
|
||||
// 只有从来没用过的才能改
|
||||
sysAccountOper$entity: {
|
||||
"#sqp": 'not in',
|
||||
}
|
||||
}
|
||||
},
|
||||
qrCode: {
|
||||
actions: ['update'],
|
||||
},
|
||||
enabled: {
|
||||
actions: ['update'],
|
||||
},
|
||||
price: {
|
||||
actions: ['pay', 'refund', 'deposit', 'withdraw', 'tax'],
|
||||
}
|
||||
},
|
||||
wpAccount: {
|
||||
wechatPay: {
|
||||
actions: ['update'],
|
||||
},
|
||||
taxlossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
depositLossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
refundGapDays: {
|
||||
actions: ['update'],
|
||||
},
|
||||
refundLossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
refundLossFloor: {
|
||||
actions: ['update'],
|
||||
},
|
||||
publicKeyFilePath: {
|
||||
actions: ['update'],
|
||||
},
|
||||
privateKeyFilePath: {
|
||||
actions: ['update'],
|
||||
},
|
||||
apiV3Key: {
|
||||
actions: ['update'],
|
||||
},
|
||||
enabled: {
|
||||
actions: ['update'],
|
||||
},
|
||||
price: {
|
||||
actions: ['pay', 'refund', 'deposit', 'withdraw', 'tax'],
|
||||
}
|
||||
},
|
||||
};
|
||||
export default attrUpdateMatrix;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
declare const cacheSavedEntities: (keyof EntityDict)[];
|
||||
export default cacheSavedEntities;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { CommonConfiguration } from 'oak-domain/lib/types/Configuration';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
declare const _default: CommonConfiguration<EntityDict>;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* index中汇总了前端启动需要的引用配置
|
||||
*/
|
||||
import attrUpdateMatrix from './attrUpdateMatrix';
|
||||
import { actionDefDict } from '@project/oak-app-domain/ActionDefDict';
|
||||
import { actionDefDict } from '../oak-app-domain/ActionDefDict';
|
||||
import { selectFreeEntities, authDeduceRelationMap, updateFreeDict } from './relation';
|
||||
import cacheSavedEntities from './cache';
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { AuthDeduceRelationMap, UpdateFreeDict } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
export declare const authDeduceRelationMap: AuthDeduceRelationMap<EntityDict>;
|
||||
export declare const selectFreeEntities: string[];
|
||||
export declare const updateFreeDict: UpdateFreeDict<EntityDict>;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
// 此对象所标识的entity的权限由其外键指向的父对象判定
|
||||
export const authDeduceRelationMap = {};
|
||||
export const selectFreeEntities = [
|
||||
'payChannel',
|
||||
'offlineAccount',
|
||||
'wpProduct',
|
||||
];
|
||||
export const updateFreeDict = {};
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { RenderConfiguration } from 'oak-domain/lib/types/Configuration';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
declare const _default: RenderConfiguration<EntityDict>;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { RuntimeContext } from './RuntimeContext';
|
||||
import { BackendRuntimeContext as DependentBackendRuntimeContext } from './DependentContext';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { BackendRuntimeContext as DependentBackendRuntimeContext } from './DependentContext';
|
||||
import { mergedProjection } from '@project/utils/application';
|
||||
import { mergedProjection } from '../utils/application';
|
||||
export class BackendRuntimeContext extends DependentBackendRuntimeContext {
|
||||
applicationProjection = mergedProjection;
|
||||
async toString() {
|
||||
|
|
@ -21,6 +21,4 @@ export class BackendRuntimeContext extends DependentBackendRuntimeContext {
|
|||
}
|
||||
}
|
||||
;
|
||||
|
||||
console.log('aaaa');
|
||||
export default BackendRuntimeContext;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { FrontendRuntimeContext as DependentFrontendRuntimeContext, SerializedData } from './DependentContext';
|
||||
import { RuntimeContext } from './RuntimeContext';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
import { CreateOperationData as ActionAuth } from '@project/oak-app-domain/ActionAuth/Schema';
|
||||
import { CreateOperationData as ActionAuth } from '../oak-app-domain/ActionAuth/Schema';
|
||||
declare const actionAuths: ActionAuth[];
|
||||
export default actionAuths;
|
||||
|
|
|
|||
135
es/data/i18n.js
135
es/data/i18n.js
|
|
@ -53,6 +53,20 @@ const i18ns = [
|
|||
position: "src/components/accountOper/list",
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
id: "50388a328d027544c140578a7a614845",
|
||||
namespace: "oak-pay-business-c-offlineAccount-config",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/offlineAccount/config",
|
||||
data: {
|
||||
"tips": "线下账户是需要system的相关工作人员手动同步收款和打款结果的账户",
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "17cdc7adc4c7b439ae2298a7f9920855",
|
||||
namespace: "oak-pay-business-c-offlineAccount-upsert",
|
||||
|
|
@ -60,16 +74,29 @@ const i18ns = [
|
|||
module: "oak-pay-business",
|
||||
position: "src/components/offlineAccount/upsert",
|
||||
data: {
|
||||
"tips": "线下交易账户是需要人工同步收款和打款行为的账户",
|
||||
"label": {
|
||||
"channel": {
|
||||
"bank": "银行及所属支行"
|
||||
}
|
||||
},
|
||||
"placeholder": {
|
||||
"channel": {
|
||||
"bank": "银行-所属支行"
|
||||
"bank": "银行/支行",
|
||||
"others": "请输入途径名称"
|
||||
},
|
||||
"name": {
|
||||
"bank": "输入户主姓名",
|
||||
"alipay": "输入支付宝帐号",
|
||||
"wechat": "输入微信号",
|
||||
"shouqianba": "输入收钱吧商户号",
|
||||
"others": "输入该收款途径的唯一账号"
|
||||
},
|
||||
"qrCode": {
|
||||
"bank": "请输入银行账号",
|
||||
"alipay": "请将二维码解析后的字符串填入",
|
||||
"wechat": "请将二维码解析后的字符串填入",
|
||||
"shouqianba": "请将二维码解析后的字符串填入",
|
||||
"others": "请将二维码解析后的字符串填入"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"allowDeposit": "是否允许用户在系统中主动向此账号发起充值",
|
||||
"allowPay": "是否允许用户在系统中主动向此账号发起支付"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -264,6 +291,20 @@ const i18ns = [
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "79255be8c093dfef9765b3f367cab553",
|
||||
namespace: "oak-pay-business-c-wechatPay-upsert",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/wechatPay/upsert",
|
||||
data: {
|
||||
"placeholder": {
|
||||
"lossRatio": "填百分比(0.6就代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "6a1df36d072d367121b49dfc665b4100",
|
||||
namespace: "oak-pay-business-c-withdraw-create",
|
||||
|
|
@ -399,6 +440,54 @@ const i18ns = [
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "7273f5a9fdb45407416554325a1abb1e",
|
||||
namespace: "oak-pay-business-c-wpAccount-config",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/wpAccount/config",
|
||||
data: {
|
||||
"tips": "微信支付账户是用来配置微信支付的账户相关信息",
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "33691d391e052cccf005d0f0da84e20e",
|
||||
namespace: "oak-pay-business-c-wpAccount-upsert",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/wpAccount/upsert",
|
||||
data: {
|
||||
"placeholder": {
|
||||
"privateKeyFilePath": "服务器上存放apiclient_key.pem的路径,注意访问权限",
|
||||
"publicKeyFilePath": "服务器上存放apiclient_cert.pem的路径,注意访问权限",
|
||||
"taxlossRatio": "微信支付收取的手续费,一般为0.6(代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint",
|
||||
"apiV3Key": "需要登录商户后台获取",
|
||||
"refundGapDays": "超过这个天数后无法退款",
|
||||
"refundLossRatio": "退款时将按这个百分比扣除损耗(0.6就代表千分之六)",
|
||||
"refundLossFloor": "退款时按位向下取整(如按元取整,则忽略角位和分位)"
|
||||
},
|
||||
"wechatPayIsShared": "以上配置是全局的,请谨慎修改"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "634284beff0e0bdf84fb23cdeea9107d",
|
||||
namespace: "oak-pay-business-c-wpProduct-config",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/wpProduct/config",
|
||||
data: {
|
||||
"notnull": "属性\"%{value}\"不能为空",
|
||||
"noData": "没有数据",
|
||||
"confirmDelete": "确定删除",
|
||||
"areYouSure": "确认删除本数据吗?"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "2127948cb52e116e3ceccd93db8f319c",
|
||||
namespace: "oak-pay-business-l-common",
|
||||
|
|
@ -470,6 +559,38 @@ const i18ns = [
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "8ff2d28d93f47ceaa08aab6211449db8",
|
||||
namespace: "oak-pay-business-l-offlineAccount",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "locales/offlineAccount",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": {
|
||||
"bank": "银行及所属支行",
|
||||
"others": "途径名"
|
||||
},
|
||||
"name": {
|
||||
"bank": "户主姓名",
|
||||
"alipay": "支付宝账号",
|
||||
"wechat": "微信号",
|
||||
"shouqianba": "收钱吧商户号",
|
||||
"others": "相应帐号"
|
||||
},
|
||||
"qrCode": {
|
||||
"bank": "银行账号",
|
||||
"alipay": "收款二维码",
|
||||
"wechat": "收款二维码",
|
||||
"shouqianba": "收款二维码",
|
||||
"others": "收款二维码"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "e8c0a965783373d9117f9447ebbbad8d",
|
||||
namespace: "oak-pay-business-l-payChannel",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
import { CreateOperationData as Path } from '@project/oak-app-domain/Path/Schema';
|
||||
import { CreateOperationData as Path } from '../oak-app-domain/Path/Schema';
|
||||
declare const paths: Path[];
|
||||
export default paths;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { String, Text, Boolean } from 'oak-domain/lib/types/DataType';
|
||||
import { String, Text, Price, Boolean } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as System } from 'oak-general-business/lib/entities/System';
|
||||
import { Schema as Pay } from './Pay';
|
||||
import { Schema as SysAccountOper } from './SysAccountOper';
|
||||
export interface Schema extends EntityShape {
|
||||
type: 'bank' | 'alipay' | 'wechat' | 'shouqianba' | 'others';
|
||||
channel?: String<32>;
|
||||
|
|
@ -11,8 +12,12 @@ export interface Schema extends EntityShape {
|
|||
allowDeposit: Boolean;
|
||||
allowPay: Boolean;
|
||||
system: System;
|
||||
price: Price;
|
||||
pays: Pay[];
|
||||
opers: SysAccountOper[];
|
||||
enabled: Boolean;
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema, '', '', {
|
||||
export type Action = 'pay' | 'refund' | 'deposit' | 'withdraw' | 'tax';
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
type: Schema['type'];
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
export const entityDesc = {
|
||||
locales: {
|
||||
zh_CN: {
|
||||
name: '离线账号管理',
|
||||
name: '线下账户',
|
||||
attr: {
|
||||
type: '类型',
|
||||
channel: '通道',
|
||||
|
|
@ -11,7 +11,10 @@ export const entityDesc = {
|
|||
allowDeposit: '允许主动充值',
|
||||
allowPay: '允许主动支付',
|
||||
system: '所属系统',
|
||||
price: '余额',
|
||||
pays: '支付',
|
||||
opers: '操作记录',
|
||||
enabled: '是否启用',
|
||||
},
|
||||
v: {
|
||||
type: {
|
||||
|
|
@ -22,17 +25,31 @@ export const entityDesc = {
|
|||
others: '其它',
|
||||
},
|
||||
},
|
||||
action: {
|
||||
pay: '支付',
|
||||
refund: '退款',
|
||||
deposit: '充值',
|
||||
withdraw: '提现',
|
||||
tax: '渠道费',
|
||||
}
|
||||
},
|
||||
},
|
||||
style: {
|
||||
color: {
|
||||
type: {
|
||||
bank: '#E74C3C',
|
||||
alipay: '#3498DB',
|
||||
wechat: '#27AE60',
|
||||
shouqianba: '#F1C40F',
|
||||
alipay: '#1678ff',
|
||||
wechat: '#04BE02',
|
||||
shouqianba: '#ffc106',
|
||||
others: '#34495E',
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
deposit: '',
|
||||
withdraw: '',
|
||||
tax: '',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import { String, Price } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
export interface Schema extends EntityShape {
|
||||
delta: Price;
|
||||
type: 'pay' | 'refund' | 'deposit' | 'withdraw' | 'tax';
|
||||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema, '', '', {
|
||||
type: Schema['type'];
|
||||
}>;
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
;
|
||||
export const entityDesc = {
|
||||
locales: {
|
||||
zh_CN: {
|
||||
name: '系统账户操作',
|
||||
attr: {
|
||||
type: '类型',
|
||||
delta: '余额变化',
|
||||
entity: '关联对象',
|
||||
entityId: '关联对象Id',
|
||||
},
|
||||
v: {
|
||||
type: {
|
||||
deposit: '充值',
|
||||
withdraw: '提现',
|
||||
pay: '支付',
|
||||
refund: '退款',
|
||||
tax: '渠道手续费'
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
style: {
|
||||
color: {
|
||||
type: {
|
||||
deposit: '#3498DB',
|
||||
withdraw: '#F7DC6F',
|
||||
pay: '#82E0AA',
|
||||
tax: '#2E4053',
|
||||
refund: '#2E4053',
|
||||
}
|
||||
}
|
||||
},
|
||||
configuration: {
|
||||
actionType: 'appendOnly',
|
||||
}
|
||||
};
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { String, Decimal } from 'oak-domain/lib/types/DataType';
|
||||
import { String } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as System } from 'oak-general-business/lib/entities/System';
|
||||
export interface Schema extends EntityShape {
|
||||
payNotifyUrl: String<128>;
|
||||
refundNotifyUrl: String<128>;
|
||||
lossRatio: Decimal<4, 2>;
|
||||
system: System;
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema>;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export const entityDesc = {
|
|||
attr: {
|
||||
payNotifyUrl: '支付通知回调',
|
||||
refundNotifyUrl: '退款通知回调',
|
||||
lossRatio: '支付损耗比例'
|
||||
system: '关联系统'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { String, Text, Price, Int, Decimal } from 'oak-domain/lib/types/DataType';
|
||||
import { String, Text, Price, Boolean, Int, Decimal } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as WechatPay } from './WechatPay';
|
||||
import { Schema as System } from 'oak-general-business/lib/entities/System';
|
||||
import { Schema as SysAccountOper } from './SysAccountOper';
|
||||
export interface Schema extends EntityShape {
|
||||
wechatPay: WechatPay;
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4>;
|
||||
refundLossRatio?: Decimal<4, 2>;
|
||||
|
|
@ -15,7 +17,10 @@ export interface Schema extends EntityShape {
|
|||
apiV3Key: String<32>;
|
||||
price: Price;
|
||||
system: System;
|
||||
opers: SysAccountOper[];
|
||||
enabled: Boolean;
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema, '', '', {
|
||||
export type Action = 'pay' | 'refund' | 'deposit' | 'withdraw' | 'tax';
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
refundLossFloor: NonNullable<Schema['refundLossFloor']>;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ export const entityDesc = {
|
|||
name: '微信支付帐号',
|
||||
attr: {
|
||||
wechatPay: '微信支付',
|
||||
taxlossRatio: '商户号手续费(百分比)',
|
||||
depositLossRatio: '充值损耗百分比',
|
||||
refundGapDays: '(支付后)允许退款的天数',
|
||||
refundLossRatio: '退款损耗百分比',
|
||||
|
|
@ -14,13 +15,22 @@ export const entityDesc = {
|
|||
privateKeyFilePath: '私钥文件路径',
|
||||
apiV3Key: 'apiV3Key',
|
||||
price: '余额',
|
||||
system: '关联系统'
|
||||
system: '关联系统',
|
||||
opers: '操作记录',
|
||||
enabled: '是否启用',
|
||||
},
|
||||
v: {
|
||||
refundLossFloor: {
|
||||
yuan: '元',
|
||||
jiao: '角'
|
||||
},
|
||||
},
|
||||
action: {
|
||||
pay: '支付',
|
||||
refund: '退款',
|
||||
deposit: '充值',
|
||||
withdraw: '提现',
|
||||
tax: '渠道费',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -30,6 +40,13 @@ export const entityDesc = {
|
|||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
deposit: '',
|
||||
withdraw: '',
|
||||
tax: '',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { Boolean } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as WpAccount } from './WpAccount';
|
||||
|
|
@ -7,6 +8,7 @@ export interface Schema extends EntityShape {
|
|||
wpAccount: WpAccount;
|
||||
type: 'native' | 'mp' | 'jsapi' | 'h5' | 'app';
|
||||
application: Application;
|
||||
enabled: Boolean;
|
||||
pays: Pay[];
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema, '', '', {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const entityDesc = {
|
|||
wpAccount: '微信支付帐号',
|
||||
type: '类型',
|
||||
application: '关联应用',
|
||||
enabled: '有效中',
|
||||
pays: '支付',
|
||||
},
|
||||
v: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Feature } from "oak-frontend-base";
|
||||
import { FeatureDict as GeneralFeatures } from 'oak-general-business';
|
||||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
export default class Pay extends Feature {
|
||||
private application;
|
||||
constructor(application: GeneralFeatures<EntityDict>['application']);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Feature } from "oak-frontend-base";
|
||||
// import { getDepositRatio } from "@project/utils/pay";
|
||||
// import { getDepositRatio } from "../utils/pay";
|
||||
export default class Pay extends Feature {
|
||||
application;
|
||||
constructor(application) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EntityDict } from '@project/oak-app-domain';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { AccessConfiguration } from 'oak-domain/lib/types/Configuration';
|
||||
import { BasicFeatures } from 'oak-frontend-base';
|
||||
import { FeatureDict as Ogb0FeatureDict } from "oak-general-business";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { merge } from 'oak-domain/lib/utils/lodash';
|
||||
import { initialize as initializeGeneral } from 'oak-general-business/es/features';
|
||||
import Pay from './Pay';
|
||||
import { applicationProjection } from '@project/utils/application';
|
||||
import { applicationProjection } from '../utils/application';
|
||||
export function create(features) {
|
||||
const pay = new Pay(features.application);
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
import { AFD } from '@project/types/RuntimeCxt';
|
||||
import { AFD } from '../types/RuntimeCxt';
|
||||
export default function useFeatures(): AFD;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"label": {
|
||||
"channel": {
|
||||
"bank": "银行及所属支行",
|
||||
"others": "途径名"
|
||||
},
|
||||
"name": {
|
||||
"bank": "户主姓名",
|
||||
"alipay": "支付宝账号",
|
||||
"wechat": "微信号",
|
||||
"shouqianba": "收钱吧商户号",
|
||||
"others": "相应帐号"
|
||||
},
|
||||
"qrCode": {
|
||||
"bank": "银行账号",
|
||||
"alipay": "收款二维码",
|
||||
"wechat": "收款二维码",
|
||||
"shouqianba": "收款二维码",
|
||||
"others": "收款二维码"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空"
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ export declare const actionDefDict: {
|
|||
deposit: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
offlineAccount: {};
|
||||
order: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
|
|
@ -58,4 +59,5 @@ export declare const actionDefDict: {
|
|||
withdraw: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
wpAccount: {};
|
||||
};
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue