增加了pay的attrUpdateMatrix
This commit is contained in:
parent
a9161e7210
commit
7082a521cb
|
|
@ -0,0 +1 @@
|
|||
<view>account detail</view>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'accountOper', false, {
|
||||
accountOpers: RowWithActions<EntityDict, 'accountOper'>[];
|
||||
}>): string;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export default function Render(props) {
|
||||
const { accountOpers } = props.data;
|
||||
const { t } = props.methods;
|
||||
return '还没有实现,todo';
|
||||
}
|
||||
|
|
@ -50,7 +50,14 @@ export default OakComponent({
|
|||
},
|
||||
methods: {
|
||||
setUseAccount(v) {
|
||||
this.setState({ useAccount: v }, () => this.tryCreatePay());
|
||||
const { accountAvailMax } = this.props;
|
||||
const { order } = this.state;
|
||||
const accountMaxPrice = Math.min(accountAvailMax, order.price);
|
||||
this.setState({
|
||||
useAccount: v,
|
||||
accountPrice: accountMaxPrice,
|
||||
rest: order.price - accountMaxPrice,
|
||||
}, () => this.tryCreatePay());
|
||||
},
|
||||
setAccountPrice(price) {
|
||||
const { order } = this.state;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
export default function Info(props: {
|
||||
price: number;
|
||||
t: (k: string) => string;
|
||||
}): import("react").JSX.Element;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import Styles from './info.module.less';
|
||||
export default function Info(props) {
|
||||
const { price, t } = props;
|
||||
return (<div className={Styles.info}>
|
||||
<div className={Styles.should}>{t('price')}</div>
|
||||
<div className={Styles.price}>
|
||||
<div>{t('common::pay.symbol')}</div>
|
||||
<div>{price}</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
.info {
|
||||
margin: 8px;
|
||||
height: 140px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--oak-color-info);
|
||||
|
||||
.should {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.price {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 3px;
|
||||
font-size: xx-large;
|
||||
font-weight: bolder;
|
||||
color: var(--oak-color-primary);
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'order', false, {
|
||||
accountId?: string;
|
||||
accountAvailMax: number;
|
||||
order: EntityDict['order']['OpSchema'];
|
||||
activePay?: EntityDict['pay']['OpSchema'];
|
||||
accountConfig?: AccountPayConfig;
|
||||
payConfig?: PayConfig;
|
||||
accountPrice: number;
|
||||
channel?: string;
|
||||
meta?: object;
|
||||
useAccount: boolean;
|
||||
rest: number;
|
||||
legal: false;
|
||||
}, {
|
||||
setAccountPrice: (price: number) => void;
|
||||
onPickChannel: (channel: string) => void;
|
||||
onSetChannelMeta: (meta?: object) => void;
|
||||
setUseAccount: (v: boolean) => void;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import React from 'react';
|
||||
import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
|
||||
import Styles from './web.mobile.module.less';
|
||||
import PayChannelPicker from '../../pay/channelPicker';
|
||||
import { InputNumber } from 'antd';
|
||||
import { Checkbox, Divider, ErrorBlock } from 'antd-mobile';
|
||||
import Info from './info';
|
||||
function RenderPayChannel(props) {
|
||||
const { price, payConfig, t, channel, meta, onPick, onSetMeta } = props;
|
||||
return (<div className={Styles.pc1}>
|
||||
<div className={Styles.content}>
|
||||
<div>
|
||||
{t('choose', { price: ToYuan(price) })}
|
||||
</div>
|
||||
<Divider />
|
||||
<PayChannelPicker payConfig={payConfig} channel={channel} meta={meta} onPick={onPick} onSetMeta={onSetMeta}/>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
function RenderAccountPay(props) {
|
||||
const { max, t, accountPrice, setAccountPrice, useAccount, setUseAccount, accountAvail } = props;
|
||||
return (<div className={Styles.pc1}>
|
||||
<div className={Styles.content}>
|
||||
<Checkbox checked={useAccount} onChange={() => {
|
||||
setUseAccount(!useAccount);
|
||||
if (useAccount) {
|
||||
setAccountPrice(0);
|
||||
}
|
||||
}}>
|
||||
{t('useAccount')}
|
||||
</Checkbox>
|
||||
{useAccount && (<>
|
||||
<Divider />
|
||||
<div>
|
||||
<InputNumber max={ToYuan(max)} addonAfter="¥" value={typeof accountPrice === 'number' ? ToYuan(accountPrice) : null} onChange={(v) => {
|
||||
if (typeof v === 'number') {
|
||||
setAccountPrice(Math.floor(ToCent(v)));
|
||||
}
|
||||
}}/>
|
||||
<div className={Styles.tips}>{t('accountMax', { max: ToYuan(accountAvail) })}</div>
|
||||
</div>
|
||||
</>)}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
export default function Render(props) {
|
||||
const { accountId, accountAvailMax, legal, accountPrice, useAccount, order, activePay, payConfig, channel, meta, rest } = props.data;
|
||||
const { t, setAccountPrice, onPickChannel, onSetChannelMeta, setUseAccount } = props.methods;
|
||||
if (order) {
|
||||
if (activePay) {
|
||||
return (<ErrorBlock status="default" title={t('paying')}/>);
|
||||
}
|
||||
if (!legal) {
|
||||
return (<ErrorBlock status="default" title={t('illegalState', { state: t(`order:v.iState.${order.iState}`) })}/>);
|
||||
}
|
||||
return (<div className={Styles.container}>
|
||||
<Info t={t} price={ToYuan(order.price)}/>
|
||||
{accountId && accountAvailMax && <div className={Styles.ctrl}>
|
||||
<RenderAccountPay max={Math.min(accountAvailMax, rest + accountPrice)} t={t} setAccountPrice={setAccountPrice} useAccount={useAccount} setUseAccount={setUseAccount} accountPrice={accountPrice} accountAvail={accountAvailMax}/>
|
||||
</div>}
|
||||
{!!(rest && rest > 0) && <div className={Styles.ctrl}>
|
||||
<RenderPayChannel payConfig={payConfig} price={rest} t={t} channel={channel} meta={meta} onPick={onPickChannel} onSetMeta={onSetChannelMeta}/>
|
||||
</div>}
|
||||
</div>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
background-color: var(--oak-bg-color-page);
|
||||
// min-height: 500px;
|
||||
|
||||
.ctrl {
|
||||
margin: 8px;
|
||||
margin-top: 10px;
|
||||
flex: 1;
|
||||
|
||||
.pc1 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 4px;
|
||||
|
||||
.content {
|
||||
background-color: var(--oak-bg-color-container);
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
padding: 16px;
|
||||
|
||||
.tips {
|
||||
color: var(--oak-color-warning);
|
||||
font-size: small;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
|
|||
import Styles from './web.pc.module.less';
|
||||
import PayChannelPicker from '../../pay/channelPicker';
|
||||
import { Divider, Checkbox, InputNumber, Flex, Result } from 'antd';
|
||||
import Info from './info';
|
||||
function RenderPayChannel(props) {
|
||||
const { price, payConfig, t, channel, meta, onPick, onSetMeta } = props;
|
||||
return (<div className={Styles.pc1}>
|
||||
|
|
@ -52,13 +53,7 @@ export default function Render(props) {
|
|||
return (<Result status="warning" title={t('illegalState', { state: t(`order:v.iState.${order.iState}`) })}/>);
|
||||
}
|
||||
return (<div className={Styles.container}>
|
||||
<div className={Styles.info}>
|
||||
<div className={Styles.should}>{t('price')}</div>
|
||||
<div className={Styles.price}>
|
||||
<div>{t('common::pay.symbol')}</div>
|
||||
<div>{ToYuan(order.price)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<Info t={t} price={ToYuan(order.price)}/>
|
||||
{accountId && accountAvailMax && <div className={Styles.ctrl}>
|
||||
<RenderAccountPay max={Math.min(accountAvailMax, rest + accountPrice)} t={t} setAccountPrice={setAccountPrice} useAccount={useAccount} setUseAccount={setUseAccount} accountPrice={accountPrice} accountAvail={accountAvailMax}/>
|
||||
</div>}
|
||||
|
|
|
|||
|
|
@ -7,30 +7,6 @@
|
|||
background-color: var(--oak-bg-color-page);
|
||||
// min-height: 500px;
|
||||
|
||||
.info {
|
||||
margin: 8px;
|
||||
height: 140px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--oak-color-info);
|
||||
|
||||
.should {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.price {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 3px;
|
||||
font-size: xx-large;
|
||||
font-weight: bolder;
|
||||
color: var(--oak-color-primary)
|
||||
}
|
||||
}
|
||||
|
||||
.ctrl {
|
||||
margin: 8px;
|
||||
margin-top: 10px;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default function Render(props) {
|
|||
}
|
||||
}} value={channel}>
|
||||
<Space direction="vertical">
|
||||
{payConfig.map((v) => (<Radio value={v.channel} key={v.channel}>
|
||||
{payConfig.map((v) => (<Radio className={Styles.radio} value={v.channel} key={v.channel}>
|
||||
<Space direction="horizontal" align='center'>
|
||||
<span className={Styles.span}>
|
||||
{t(`payChannel::${v.channel}`)}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
.span {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.radio {
|
||||
height: 40px;
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ export default OakComponent({
|
|||
application,
|
||||
iStateColor,
|
||||
payConfig,
|
||||
closable: !!(data?.["#oakLegalActions"]?.includes('close')),
|
||||
};
|
||||
},
|
||||
features: ['application'],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,19 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
export declare function RenderOffline(props: {
|
||||
pay: RowWithActions<EntityDict, 'pay'>;
|
||||
t: (key: string) => string;
|
||||
offline: OfflinePayConfig;
|
||||
updateMeta: (meta: any) => void;
|
||||
metaUpdatable: boolean;
|
||||
}): React.JSX.Element;
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
pay: RowWithActions<EntityDict, 'pay'>;
|
||||
}>): null;
|
||||
application?: EntityDict['application']['Schema'];
|
||||
iStateColor?: string;
|
||||
payConfig?: PayConfig;
|
||||
onClose: () => undefined;
|
||||
closable: boolean;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,156 @@
|
|||
export default function Render(props) {
|
||||
const { pay } = props.data;
|
||||
const { t } = props.methods;
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Card, Tag, List, Button, Modal, Form, Selector, TextArea } from 'antd-mobile';
|
||||
import { QRCode, Alert } from 'antd';
|
||||
import Styles from './web.mobile.module.less';
|
||||
import * as dayJs from 'dayjs';
|
||||
import { CentToString } from 'oak-domain/lib/utils/money';
|
||||
import { PAY_CHANNEL_OFFLINE_NAME, PAY_CHANNEL_WECHAT_APP_NAME, PAY_CHANNEL_WECHAT_H5_NAME, PAY_CHANNEL_WECHAT_JS_NAME, PAY_CHANNEL_WECHAT_MP_NAME, PAY_CHANNEL_WECHAT_NATIVE_NAME } from '../../../types/PayConfig';
|
||||
import { PayCircleOutline, GlobalOutline } from 'antd-mobile-icons';
|
||||
export function RenderOffline(props) {
|
||||
const { pay, t, offline, updateMeta, metaUpdatable } = props;
|
||||
const { meta, iState } = pay;
|
||||
return (<>
|
||||
<Form layout="horizontal" style={{ width: '100%', marginTop: 12 }}>
|
||||
<Form.Item label={t("offline.label.tips")}>
|
||||
<span style={{ wordBreak: 'break-all', textDecoration: 'underline' }}>{offline.tips}</span>
|
||||
</Form.Item>
|
||||
{!!(offline.options?.length) && <Form.Item label={t("offline.label.option")}>
|
||||
<Selector value={meta?.option ? [meta?.option] : undefined} options={offline.options.map(ele => ({
|
||||
label: ele,
|
||||
value: ele,
|
||||
}))} disabled={!metaUpdatable} onChange={(v) => updateMeta({
|
||||
...meta,
|
||||
option: v[0],
|
||||
})}/>
|
||||
</Form.Item>}
|
||||
<Form.Item label={t("offline.label.serial")}>
|
||||
<TextArea autoSize={{ minRows: 3 }} value={meta?.serial} disabled={!metaUpdatable} placeholder={metaUpdatable ? t('offline.placeholder.serial') : t('offline.placeholder.none')} onChange={(value) => updateMeta({
|
||||
...meta,
|
||||
serial: value,
|
||||
})}/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</>);
|
||||
}
|
||||
function Counter(props) {
|
||||
const { deadline } = props;
|
||||
const [counter, setCounter] = useState('');
|
||||
const timerFn = () => {
|
||||
const now = Date.now();
|
||||
if (now < deadline) {
|
||||
const duration = dayJs.duration(deadline - now);
|
||||
setCounter(duration.format('HH:mm:ss'));
|
||||
setTimeout(timerFn, 1000);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
timerFn();
|
||||
}, []);
|
||||
return (<div className={Styles.counter}>{counter}</div>);
|
||||
}
|
||||
function RenderWechatPay(props) {
|
||||
const { pay, t } = props;
|
||||
const { externalId, channel, timeoutAt, iState } = pay;
|
||||
switch (channel) {
|
||||
case PAY_CHANNEL_WECHAT_NATIVE_NAME: {
|
||||
if (iState === 'paying') {
|
||||
return (<>
|
||||
<Counter deadline={timeoutAt}/>
|
||||
<QRCode value={externalId} size={280}/>
|
||||
<div className={Styles.qrCodeTips}>
|
||||
{process.env.NODE_ENV === 'production' ?
|
||||
<Alert type="info" message={t('wechat.native.tips')}/> :
|
||||
<Alert type="warning" message={t('wechat.native.tips2')}/>}
|
||||
</div>
|
||||
</>);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function RenderPayMeta(props) {
|
||||
const { pay, application, t, payConfig, updateMeta } = props;
|
||||
const { iState, channel } = pay;
|
||||
if (['unpaid', 'paying'].includes(iState) && pay.applicationId !== application.id && channel !== PAY_CHANNEL_OFFLINE_NAME) {
|
||||
return <Alert type='warning' message={t('notSameApp')}/>;
|
||||
}
|
||||
switch (channel) {
|
||||
case PAY_CHANNEL_OFFLINE_NAME: {
|
||||
const { '#oakLegalActions': legalActions } = pay;
|
||||
const metaUpdatable = !!legalActions?.find(ele => typeof ele === 'object'
|
||||
&& ele.action === 'update'
|
||||
&& ele.attrs?.includes('meta'));
|
||||
return (<>
|
||||
{iState === 'paying' && <Alert type='info' message={t('offline.tips')}/>}
|
||||
{RenderOffline({
|
||||
pay,
|
||||
t,
|
||||
offline: payConfig.find(ele => ele.channel === PAY_CHANNEL_OFFLINE_NAME),
|
||||
updateMeta,
|
||||
metaUpdatable
|
||||
})}
|
||||
</>);
|
||||
}
|
||||
case PAY_CHANNEL_WECHAT_APP_NAME:
|
||||
case PAY_CHANNEL_WECHAT_H5_NAME:
|
||||
case PAY_CHANNEL_WECHAT_JS_NAME:
|
||||
case PAY_CHANNEL_WECHAT_MP_NAME:
|
||||
case PAY_CHANNEL_WECHAT_NATIVE_NAME: {
|
||||
return <RenderWechatPay pay={pay} t={t}/>;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export default function Render(props) {
|
||||
const { pay, application, iStateColor, payConfig, oakExecutable, onClose, closable } = props.data;
|
||||
const { t, update, execute, clean } = props.methods;
|
||||
if (pay && application) {
|
||||
const { iState, channel, price, '#oakLegalActions': legalActions } = pay;
|
||||
return (<div className={Styles.container}>
|
||||
<Card title={t('title')} extra={<Tag color={iStateColor}>{t(`pay:v.iState.${iState}`)}</Tag>}>
|
||||
<div>
|
||||
<List>
|
||||
<List.Item prefix={<PayCircleOutline />} extra={CentToString(price, 2)}>
|
||||
{t('pay:attr.price')}
|
||||
</List.Item>
|
||||
<List.Item prefix={<GlobalOutline />} extra={t(`payChannel::${channel}`)}>
|
||||
{t('pay:attr.channel')}
|
||||
</List.Item>
|
||||
</List>
|
||||
</div>
|
||||
</Card>
|
||||
<div className={Styles.meta}>
|
||||
<RenderPayMeta pay={pay} t={t} application={application} payConfig={payConfig} updateMeta={(meta) => update({ meta })}/>
|
||||
</div>
|
||||
<div className={Styles.padding}/>
|
||||
<div className={Styles.btn}>
|
||||
{oakExecutable === true && (<>
|
||||
<div className={Styles.btnItem}>
|
||||
<Button block color='primary' onClick={() => execute()}>
|
||||
{t('common::action.update')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className={Styles.btnItem}>
|
||||
<Button block onClick={() => clean()}>
|
||||
{t('common::reset')}
|
||||
</Button>
|
||||
</div>
|
||||
</>)}
|
||||
{closable && !(oakExecutable === true) && (<Button block color="primary" onClick={() => {
|
||||
Modal.confirm({
|
||||
title: t('cc.title'),
|
||||
content: t('cc.content'),
|
||||
onConfirm: async () => {
|
||||
await execute('close');
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
}}>
|
||||
{t('pay:action.close')}
|
||||
</Button>)}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
.container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.meta {
|
||||
margin-top: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.qrCodeTips {
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.counter {
|
||||
font-size: var(--oak-font-size-headline-medium);
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
|
||||
.padding {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.btnItem {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,4 +15,5 @@ export default function Render(props: WebComponentProps<EntityDict, 'pay', false
|
|||
iStateColor?: string;
|
||||
payConfig?: PayConfig;
|
||||
onClose: () => undefined;
|
||||
closable: boolean;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export function RenderOffline(props) {
|
|||
return (<>
|
||||
<Form labelCol={{ span: 4 }} wrapperCol={{ span: 14 }} layout="horizontal" style={{ width: '100%', marginTop: 12 }}>
|
||||
<Form.Item label={t("offline.label.tips")}>
|
||||
<span style={{ wordBreak: 'break-all' }}>{offline.tips}</span>
|
||||
<span style={{ wordBreak: 'break-all', textDecoration: 'underline' }}>{offline.tips}</span>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("offline.label.option")}>
|
||||
<Select value={meta?.option} options={offline.options?.map(ele => ({
|
||||
|
|
@ -58,7 +58,7 @@ function RenderWechatPay(props) {
|
|||
<Counter deadline={timeoutAt}/>
|
||||
<QRCode value={externalId} size={280}/>
|
||||
<div className={Styles.qrCodeTips}>
|
||||
{process.env.NODE_ENV === 'production' ?
|
||||
{process.env.NODE_ENV === 'production' ?
|
||||
<Alert type="info" message={t('wechat.native.tips')}/> :
|
||||
<Alert type="warning" message={t('wechat.native.tips2')}/>}
|
||||
</div>
|
||||
|
|
@ -103,11 +103,10 @@ function RenderPayMeta(props) {
|
|||
return null;
|
||||
}
|
||||
export default function Render(props) {
|
||||
const { pay, application, iStateColor, payConfig, oakExecutable, onClose } = props.data;
|
||||
const { t, update, execute } = props.methods;
|
||||
const { pay, application, iStateColor, payConfig, oakExecutable, onClose, closable } = props.data;
|
||||
const { t, update, execute, clean } = props.methods;
|
||||
if (pay && application) {
|
||||
const { iState, channel, price, '#oakLegalActions': legalActions } = pay;
|
||||
const closable = !!legalActions?.find(ele => ele === 'close');
|
||||
return (<Card title={t('title')} extra={<Tag color={iStateColor}>{t(`pay:v.iState.${iState}`)}</Tag>}>
|
||||
<div className={Styles.container}>
|
||||
<div className={Styles.detail}>
|
||||
|
|
@ -128,9 +127,14 @@ export default function Render(props) {
|
|||
<RenderPayMeta pay={pay} t={t} application={application} payConfig={payConfig} updateMeta={(meta) => update({ meta })}/>
|
||||
</div>
|
||||
<div className={Styles.btn}>
|
||||
{oakExecutable === true && (<Button onClick={() => execute()}>
|
||||
{t('common::action.update')}
|
||||
</Button>)}
|
||||
{oakExecutable === true && (<>
|
||||
<Button type="primary" onClick={() => execute()}>
|
||||
{t('common::action.update')}
|
||||
</Button>
|
||||
<Button onClick={() => clean()}>
|
||||
{t('common::reset')}
|
||||
</Button>
|
||||
</>)}
|
||||
{closable && !(oakExecutable === true) && (<Button type="primary" onClick={() => {
|
||||
Modal.confirm({
|
||||
title: t('cc.title'),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ const attrUpdateMatrix = {
|
|||
},
|
||||
channel: PAY_CHANNEL_ACCOUNT_NAME,
|
||||
}
|
||||
},
|
||||
paid: {
|
||||
actions: ['succeedPaying'],
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const entityDesc = {
|
|||
zh_CN: {
|
||||
name: '订单',
|
||||
attr: {
|
||||
price: '订单金额',
|
||||
price: '应支付金额',
|
||||
paid: '已支付金额',
|
||||
refunded: '已退款金额',
|
||||
iState: '支付状态',
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ const watchers = [
|
|||
results.push(result);
|
||||
}
|
||||
}
|
||||
if (results.length === 0) {
|
||||
return {};
|
||||
}
|
||||
return results.reduce((prev, cur) => mergeOperationResult(prev, cur));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ const attrUpdateMatrix = {
|
|||
},
|
||||
channel: PayConfig_1.PAY_CHANNEL_ACCOUNT_NAME,
|
||||
}
|
||||
},
|
||||
paid: {
|
||||
actions: ['succeedPaying'],
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ exports.entityDesc = {
|
|||
zh_CN: {
|
||||
name: '订单',
|
||||
attr: {
|
||||
price: '订单金额',
|
||||
price: '应支付金额',
|
||||
paid: '已支付金额',
|
||||
refunded: '已退款金额',
|
||||
iState: '支付状态',
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ const watchers = [
|
|||
results.push(result);
|
||||
}
|
||||
}
|
||||
if (results.length === 0) {
|
||||
return {};
|
||||
}
|
||||
return results.reduce((prev, cur) => (0, operationResult_1.mergeOperationResult)(prev, cur));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<view>account detail</view>
|
||||
|
|
@ -26,6 +26,9 @@ const attrUpdateMatrix: AttrUpdateMatrix<EntityDict> = {
|
|||
},
|
||||
channel: PAY_CHANNEL_ACCOUNT_NAME,
|
||||
}
|
||||
},
|
||||
paid: {
|
||||
actions: ['succeedPaying'],
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ const watchers: Watcher<EntityDict, 'pay', BRC>[] = [
|
|||
}
|
||||
}
|
||||
|
||||
if (results.length === 0) {
|
||||
return {};
|
||||
}
|
||||
return results.reduce(
|
||||
(prev, cur) => mergeOperationResult(prev, cur)
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue