在pay/detail支持用户修改externalId
This commit is contained in:
parent
09c3094f7c
commit
28c92f89e1
|
|
@ -19,6 +19,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
|
|||
textColor: string;
|
||||
priceColor: string;
|
||||
bgColor: string;
|
||||
onGoToHistory: () => void;
|
||||
}, {
|
||||
newDeposit: () => Promise<void>;
|
||||
setDepositOpen: (v: boolean) => void;
|
||||
|
|
@ -29,5 +30,4 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
|
|||
onDepositClick: () => void;
|
||||
onDepositModalClose: () => void;
|
||||
onUnfinishedDepositClick: () => void;
|
||||
onGoToHistory: () => void;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import classNames from 'classnames';
|
|||
import { CentToString } from 'oak-domain/lib/utils/money';
|
||||
import NewDeposit from '../../deposit/new';
|
||||
export default function Render(props) {
|
||||
const { account, depositMaxCent, newDepositPath, depositOpen, depositMinCent, ufOpen, depPrice, depositChannel, depositLoss, depositing, onWithdraw, textColor, priceColor, bgColor, } = props.data;
|
||||
const { t, newDeposit, setMessage, setDepositOpen, setUfOpen, setDepPrice, setDepositChannel, onUnfinishedDepositClick, setDepositing, onDepositClick, onDepositModalClose, onGoToHistory, } = props.methods;
|
||||
const { account, depositMaxCent, newDepositPath, depositOpen, depositMinCent, ufOpen, depPrice, depositChannel, depositLoss, depositing, onWithdraw, textColor, priceColor, bgColor, onGoToHistory } = props.data;
|
||||
const { t, newDeposit, setMessage, setDepositOpen, setUfOpen, setDepPrice, setDepositChannel, onUnfinishedDepositClick, setDepositing, onDepositClick, onDepositModalClose, } = props.methods;
|
||||
if (account) {
|
||||
const { total, avail, '#oakLegalActions': legalActions, accountOper$account: opers } = account;
|
||||
return (<div className={Styles.container}>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
|
|||
depositMeta: any;
|
||||
depositing: boolean;
|
||||
newDepositPath: string;
|
||||
onGoToHistory: () => void;
|
||||
}, {
|
||||
newDeposit: () => Promise<string>;
|
||||
setDepositOpen: (v: boolean) => void;
|
||||
|
|
@ -26,5 +27,4 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
|
|||
onDepositClick: () => void;
|
||||
onDepositModalClose: () => void;
|
||||
onUnfinishedDepositClick: () => void;
|
||||
onGoToHistory: () => void;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import NewDeposit from '../../deposit/new';
|
|||
import AccountOperList from '../../accountOper/pure/List.pc';
|
||||
import { AccountBookOutlined, ScheduleOutlined } from '@ant-design/icons';
|
||||
export default function Render(props) {
|
||||
const { account, depositMaxCent, newDepositPath, depositOpen, depositMinCent, ufOpen, depPrice, depositChannel, depositLoss, depositing, onWithdraw, } = props.data;
|
||||
const { t, newDeposit, setMessage, setDepositOpen, setUfOpen, setDepPrice, setDepositChannel, onUnfinishedDepositClick, setDepositing, onDepositClick, onDepositModalClose, onGoToHistory, } = props.methods;
|
||||
const { account, depositMaxCent, newDepositPath, depositOpen, depositMinCent, ufOpen, depPrice, depositChannel, depositLoss, depositing, onWithdraw, onGoToHistory, } = props.data;
|
||||
const { t, newDeposit, setMessage, setDepositOpen, setUfOpen, setDepPrice, setDepositChannel, onUnfinishedDepositClick, setDepositing, onDepositClick, onDepositModalClose, } = props.methods;
|
||||
if (account) {
|
||||
const { total, avail, '#oakLegalActions': legalActions, accountOper$account: opers } = account;
|
||||
return (<>
|
||||
|
|
|
|||
|
|
@ -6,22 +6,26 @@ export default OakComponent({
|
|||
projection: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
totalPlus: 1,
|
||||
avail: 1,
|
||||
availPlus: 1,
|
||||
$$createAt$$: 1,
|
||||
},
|
||||
properties: {
|
||||
accountId: '',
|
||||
},
|
||||
data: {
|
||||
month: new Date(),
|
||||
monthStr: '',
|
||||
type: 'both',
|
||||
chooseMonth: false,
|
||||
chooseType: false,
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const { accountId } = this.props;
|
||||
return {
|
||||
accountId,
|
||||
avail: {
|
||||
$ne: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -38,19 +42,103 @@ export default OakComponent({
|
|||
const sign = availPlus > 0 ? '+' : '-';
|
||||
const time = dayjs($$createAt$$).format('YYYY-MM-DD HH:mm');
|
||||
const symbol = this.t(`accountOper:v.type.${type}`)[0];
|
||||
const bgColor = this.features.style.getColor('accountOper', 'type', type);
|
||||
return {
|
||||
value: `${sign}${plus}`,
|
||||
time,
|
||||
type,
|
||||
type: this.t(`accountOper:v.type.${type}`),
|
||||
symbol,
|
||||
avail: ThousandCont(ToYuan(avail), 2)
|
||||
avail: ThousandCont(ToYuan(avail), 2),
|
||||
bgColor,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.setTypeFilter();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadMoreMp() {
|
||||
return this.loadMore();
|
||||
},
|
||||
setType(type) {
|
||||
this.setState({
|
||||
type,
|
||||
}, () => this.setTypeFilter());
|
||||
},
|
||||
setTypeFilter() {
|
||||
const { type } = this.state;
|
||||
switch (type) {
|
||||
case 'in': {
|
||||
this.addNamedFilter({
|
||||
'#name': 'type',
|
||||
filter: {
|
||||
availPlus: {
|
||||
$gt: 0,
|
||||
},
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
case 'out': {
|
||||
this.addNamedFilter({
|
||||
'#name': 'type',
|
||||
filter: {
|
||||
availPlus: {
|
||||
$lt: 0,
|
||||
},
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
case 'both':
|
||||
default: {
|
||||
this.addNamedFilter({
|
||||
'#name': 'type',
|
||||
filter: {
|
||||
availPlus: {
|
||||
$ne: 0,
|
||||
},
|
||||
}
|
||||
}, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
setMonth(month) {
|
||||
if (month) {
|
||||
const m = dayjs(month);
|
||||
const begin = m.startOf('month').valueOf();
|
||||
const end = m.endOf('month').valueOf();
|
||||
this.setState({
|
||||
monthStr: m.format('YYYY-MM'),
|
||||
month,
|
||||
}, () => this.addNamedFilter({
|
||||
'#name': 'month',
|
||||
filter: {
|
||||
$$createAt$$: {
|
||||
$between: [begin, end],
|
||||
}
|
||||
}
|
||||
}, true));
|
||||
}
|
||||
else {
|
||||
this.setState({
|
||||
monthStr: '',
|
||||
month: undefined,
|
||||
}, () => this.removeNamedFilter({
|
||||
'#name': 'month',
|
||||
filter: {}
|
||||
}, true));
|
||||
}
|
||||
},
|
||||
setChooseMonth(chooseMonth) {
|
||||
this.setState({ chooseMonth });
|
||||
},
|
||||
setChooseType(chooseType) {
|
||||
this.setState({ chooseType });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1 +1,9 @@
|
|||
{}
|
||||
{
|
||||
"history": "账户历史",
|
||||
"chooseMonth": "选择月份",
|
||||
"type": {
|
||||
"both": "全部",
|
||||
"in": "仅收入",
|
||||
"out": "仅支出"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,52 @@
|
|||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
.control {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding-bottom: 10px;
|
||||
|
||||
.symbol {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 25px;
|
||||
margin: 10px;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-top: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sub {
|
||||
width: 100%;
|
||||
|
||||
.type {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.types {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
background-color: white;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
@ -8,6 +8,17 @@ export default function Render(props: WebComponentProps<EntityDict, 'accountOper
|
|||
type: string;
|
||||
symbol: string;
|
||||
avail: string;
|
||||
bgColor: string;
|
||||
}>;
|
||||
hasMore: boolean;
|
||||
}>): React.JSX.Element | null;
|
||||
month?: Date;
|
||||
monthStr: string;
|
||||
type: 'in' | 'out' | 'both';
|
||||
chooseMonth: boolean;
|
||||
chooseType: boolean;
|
||||
}, {
|
||||
setMonth: (month?: number | Date) => void;
|
||||
setType: (type: 'in' | 'out' | 'both') => void;
|
||||
setChooseMonth: (cm: boolean) => void;
|
||||
setChooseType: (ct: boolean) => void;
|
||||
}>): React.JSX.Element;
|
||||
|
|
|
|||
|
|
@ -1,29 +1,63 @@
|
|||
import React from 'react';
|
||||
import { List, InfiniteScroll, Space } from 'antd-mobile';
|
||||
import { List, InfiniteScroll, Space, DatePicker, Button, Popup, Radio, Result } from 'antd-mobile';
|
||||
import { DownOutline, SearchOutline, UndoOutline } from 'antd-mobile-icons';
|
||||
import Styles from './mobile.module.less';
|
||||
export default function Render(props) {
|
||||
const { accountOpers, hasMore } = props.data;
|
||||
const { t, loadMore } = props.methods;
|
||||
if (accountOpers?.length) {
|
||||
return (<div className={Styles.container}>
|
||||
<List>
|
||||
{accountOpers.map((oper, idx) => {
|
||||
const { value, time, type, symbol, avail } = oper;
|
||||
return (<List.Item key={idx} prefix={<div className={Styles.symbol}>
|
||||
{symbol}
|
||||
</div>} description={<Space direction="horizontal" justify="between">
|
||||
<span>{time}</span>
|
||||
<span>{t('accountOper:attr.avail')}:{avail}</span>
|
||||
</Space>}>
|
||||
<Space direction="horizontal" justify="between">
|
||||
<span>{type}</span>
|
||||
<span>{value}</span>
|
||||
</Space>
|
||||
</List.Item>);
|
||||
const { accountOpers, hasMore, month, type, chooseMonth, chooseType, monthStr } = props.data;
|
||||
const { t, loadMore, setType, setMonth, setChooseMonth, setChooseType, navigateBack } = props.methods;
|
||||
return (<div className={Styles.container}>
|
||||
<Space justify="between" className={Styles.control}>
|
||||
<Button size="small" fill="none" onClick={() => setChooseMonth(true)}>
|
||||
{monthStr || t('chooseMonth')}
|
||||
<DownOutline />
|
||||
</Button>
|
||||
<Button size="small" fill="none" onClick={() => setChooseType(true)}>
|
||||
<SearchOutline />
|
||||
{t(`type.${type}`)}
|
||||
</Button>
|
||||
</Space>
|
||||
<DatePicker visible={chooseMonth} value={month || null} onClose={() => setChooseMonth(false)} max={new Date()} precision="month" onConfirm={(value) => {
|
||||
setMonth(value);
|
||||
setChooseMonth(false);
|
||||
}}/>
|
||||
<Popup visible={chooseType} onMaskClick={() => setChooseType(false)} onClose={() => setChooseType(false)}>
|
||||
<Radio.Group onChange={(type) => {
|
||||
setType(type);
|
||||
setChooseType(false);
|
||||
}} value={type}>
|
||||
<Space className={Styles.types} justify="around">
|
||||
<Radio value="both">{t('type.both')}</Radio>
|
||||
<Radio value="in">{t('type.in')}</Radio>
|
||||
<Radio value="out">{t('type.out')}</Radio>
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Popup>
|
||||
{accountOpers?.length ? <div style={{ flex: 1 }}>
|
||||
<List>
|
||||
{accountOpers.map((oper, idx) => {
|
||||
const { value, time, type, symbol, avail, bgColor } = oper;
|
||||
return (<List.Item className={Styles.item} key={idx} prefix={<div className={Styles.symbol} style={{
|
||||
backgroundColor: bgColor,
|
||||
}}>
|
||||
{symbol}
|
||||
</div>} description={<Space direction="horizontal" justify="between" className={Styles.main}>
|
||||
<span>{time}</span>
|
||||
<span>{t('account:attr.avail')}:{avail}</span>
|
||||
</Space>}>
|
||||
<Space direction="horizontal" justify="between" className={Styles.sub}>
|
||||
<span className={Styles.type}>{type}</span>
|
||||
<span style={{
|
||||
color: bgColor,
|
||||
}}>{value}</span>
|
||||
</Space>
|
||||
</List.Item>);
|
||||
})}
|
||||
</List>
|
||||
<InfiniteScroll hasMore={hasMore} loadMore={loadMore}/>
|
||||
</div>);
|
||||
}
|
||||
return null;
|
||||
</List>
|
||||
<InfiniteScroll hasMore={hasMore} loadMore={loadMore}/>
|
||||
</div> : (<div className={Styles.empty}>
|
||||
<Result icon={<UndoOutline />} status='success' title={t('common::noData')} description={<Button onClick={() => navigateBack()}>
|
||||
{t('common::back')}
|
||||
</Button>}/>
|
||||
</div>)}
|
||||
</div>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
.control {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: x-large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.list {
|
||||
min-height: 620px;
|
||||
}
|
||||
|
||||
.types {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
background-color: white;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
@ -1,12 +1,24 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'accountOper', false, {
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'accountOper', true, {
|
||||
accountOpers?: Array<{
|
||||
value: string;
|
||||
time: string;
|
||||
type: string;
|
||||
symbol: string;
|
||||
avail: string;
|
||||
bgColor: string;
|
||||
}>;
|
||||
}>): React.JSX.Element | undefined;
|
||||
hasMore: boolean;
|
||||
month?: Date;
|
||||
monthStr: string;
|
||||
type: 'in' | 'out' | 'both';
|
||||
chooseMonth: boolean;
|
||||
chooseType: boolean;
|
||||
}, {
|
||||
setMonth: (month?: Date) => void;
|
||||
setType: (type: 'in' | 'out' | 'both') => void;
|
||||
setChooseMonth: (cm: boolean) => void;
|
||||
setChooseType: (ct: boolean) => void;
|
||||
}>): React.JSX.Element;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,46 @@
|
|||
import React from 'react';
|
||||
import { List, Flex } from 'antd';
|
||||
import { Avatar, List, Select, Flex, Button, Card, Result, DatePicker } from 'antd';
|
||||
import Styles from './web.module.less';
|
||||
import dayJs from 'dayjs';
|
||||
export default function Render(props) {
|
||||
const { accountOpers } = props.data;
|
||||
const { t } = props.methods;
|
||||
if (accountOpers?.length) {
|
||||
return (<Flex vertical>
|
||||
<List dataSource={accountOpers}/>
|
||||
</Flex>);
|
||||
}
|
||||
const { accountOpers, hasMore, month, type, chooseMonth, chooseType, monthStr, oakLoading, oakLoadingMore } = props.data;
|
||||
const { t, loadMore, setType, setMonth, setChooseMonth, setChooseType, navigateBack } = props.methods;
|
||||
return (<>
|
||||
<Card title={t('history')} extra={<Flex gap="middle" className={Styles.control}>
|
||||
<DatePicker picker="month" onChange={(value) => {
|
||||
setMonth(value.toDate());
|
||||
}} maxDate={dayJs()}/>
|
||||
<Select style={{ width: 120 }} onChange={(value) => {
|
||||
setType(value);
|
||||
}} value={type} options={[
|
||||
{ value: 'both', label: t('type.both') },
|
||||
{ value: 'in', label: t('type.in') },
|
||||
{ value: 'out', label: t('type.out') },
|
||||
]}/>
|
||||
</Flex>}>
|
||||
{accountOpers?.length ?
|
||||
<List className={Styles.list} loading={oakLoading || oakLoadingMore} dataSource={accountOpers} renderItem={(item, idx) => (<List.Item key={idx}>
|
||||
<List.Item.Meta avatar={<Avatar style={{ backgroundColor: item.bgColor }}>{item.symbol}</Avatar>} title={<span className={Styles.type}>{item.type}</span>} description={<Flex justify="between" className={Styles.main} gap="large">
|
||||
<span>{item.time}</span>
|
||||
<span>{t('account:attr.avail')}:{item.avail}</span>
|
||||
</Flex>}/>
|
||||
<div className={Styles.value} style={{
|
||||
color: item.bgColor,
|
||||
}}>
|
||||
{item.value}
|
||||
</div>
|
||||
</List.Item>)} loadMore={!oakLoading && !oakLoadingMore && hasMore ? (<div style={{
|
||||
textAlign: 'center',
|
||||
marginTop: 12,
|
||||
height: 32,
|
||||
lineHeight: '32px',
|
||||
}}>
|
||||
<Button onClick={loadMore}>
|
||||
{t('common::loadMore')}
|
||||
</Button>
|
||||
</div>) : null}/> : (<Result status="404" title={t('common::noData')} extra={<Button onClick={() => navigateBack()}>
|
||||
{t('common::back')}
|
||||
</Button>}/>)}
|
||||
</Card>
|
||||
</>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,6 +264,17 @@ export default OakComponent({
|
|||
});
|
||||
}
|
||||
},
|
||||
updateExternalIdMp(input) {
|
||||
const { detail } = input;
|
||||
this.update({
|
||||
externalId: detail.value,
|
||||
});
|
||||
},
|
||||
clearExternalIdMp() {
|
||||
this.update({
|
||||
externalId: null,
|
||||
});
|
||||
}
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@
|
|||
<l-form-item label-width="240rpx" label="{{t('code.label')}}">
|
||||
<l-tag bg-color="#d9363e">{{pay.phantom3}}</l-tag>
|
||||
</l-form-item>
|
||||
<l-form-item label-width="240rpx" label="{{t('externalId.label')}}">
|
||||
<l-input
|
||||
hide-label="{{true}}"
|
||||
clear="{{true}}"
|
||||
disabled="{{pay.iState !== 'paying'}}"
|
||||
placeholder="{{t('externalId.help')}}"
|
||||
bind:lininput="updateExternalIdMp"
|
||||
bind:linclear="clearExternalIdMp"
|
||||
/>
|
||||
</l-form-item>
|
||||
<block wx:if="{{offline.type === 'bank'}}">
|
||||
<l-form-item label-width="240rpx" label="{{t('offlineAccount::label.channel.bank')}}">
|
||||
<view>{{offline.channel}}</view>
|
||||
|
|
|
|||
|
|
@ -25,10 +25,14 @@
|
|||
},
|
||||
"code": {
|
||||
"label": "转帐凭证号",
|
||||
"help": "请在转帐留言中附上转帐凭证号,便于人工核对"
|
||||
"help": "请在转帐时于留言中附上转帐凭证号,便于人工核对。若转账时忘记附上,则请准确填写转账流水号。"
|
||||
},
|
||||
"channel": {
|
||||
"change": "更换",
|
||||
"prefix": "渠道"
|
||||
},
|
||||
"externalId": {
|
||||
"label": "转账流水号",
|
||||
"help": "转账成功后有唯一流水号,将之正确填入可减少财务人员核对时的错误概率,给您带来更大便利"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export declare function RenderOffline(props: {
|
|||
offlines: ColoredOffline[];
|
||||
offline: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void;
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}): React.JSX.Element;
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
pay?: RowWithActions<EntityDict, 'pay'>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Card, Tag, List, Button, Modal, Form, Selector, Popup } from 'antd-mobile';
|
||||
import { Card, Tag, List, Button, Modal, Form, Selector, Input, Popup } from 'antd-mobile';
|
||||
import { QRCode, Alert } from 'antd';
|
||||
import Styles from './web.mobile.module.less';
|
||||
import * as dayJs from 'dayjs';
|
||||
|
|
@ -9,8 +9,8 @@ import { CentToString } from 'oak-domain/lib/utils/money';
|
|||
import { PayCircleOutline, GlobalOutline, InformationCircleOutline, CheckCircleOutline } from 'antd-mobile-icons';
|
||||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
export function RenderOffline(props) {
|
||||
const { pay, t, offline, offlines, updateOfflineId } = props;
|
||||
const { meta, iState, phantom3 } = pay;
|
||||
const { pay, t, offline, offlines, updateOfflineId, updateExternalId } = props;
|
||||
const { meta, iState, phantom3, externalId } = pay;
|
||||
const { type, channel, name, qrCode, color } = offline || {};
|
||||
const [show, setShow] = useState(false);
|
||||
const items2 = [
|
||||
|
|
@ -23,6 +23,11 @@ export function RenderOffline(props) {
|
|||
<Tag color="red">
|
||||
<span style={{ fontSize: 'large' }}>{phantom3}</span>
|
||||
</Tag>
|
||||
</Form.Item>,
|
||||
<Form.Item key="externalId" label={<span className={Styles.bold}>{t('externalId.label')}</span>}>
|
||||
<Input autoFocus value={externalId || ''} onChange={(value) => {
|
||||
updateExternalId(value);
|
||||
}} placeholder={t('externalId.help')} disabled={iState !== 'paying'}/>
|
||||
</Form.Item>
|
||||
];
|
||||
if (type === 'bank') {
|
||||
|
|
@ -121,7 +126,7 @@ function RenderWechatPay(props) {
|
|||
return null;
|
||||
}
|
||||
function RenderPayMeta(props) {
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId } = props;
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, entity } = pay;
|
||||
if (entity !== 'offlineAccount' && notSameApp) {
|
||||
return <Alert type='warning' message={t('notSameApp')}/>;
|
||||
|
|
@ -131,7 +136,7 @@ function RenderPayMeta(props) {
|
|||
if (offline && offlines) {
|
||||
return (<>
|
||||
{iState === 'paying' && <Alert type='info' message={t('code.help')} style={{ marginBottom: 10 }}/>}
|
||||
<RenderOffline t={t} pay={pay} offline={offline} offlines={offlines} updateOfflineId={updateOfflineId}/>
|
||||
<RenderOffline t={t} pay={pay} offline={offline} offlines={offlines} updateOfflineId={updateOfflineId} updateExternalId={updateExternalId}/>
|
||||
</>);
|
||||
}
|
||||
return null;
|
||||
|
|
@ -208,6 +213,8 @@ export default function Render(props) {
|
|||
}
|
||||
}
|
||||
]);
|
||||
}} updateExternalId={(externalId) => {
|
||||
update({ externalId });
|
||||
}}/>
|
||||
</div>
|
||||
<div className={Styles.padding}/>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export declare function RenderOffline(props: {
|
|||
offlines: ColoredOffline[];
|
||||
offline: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void;
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}): React.JSX.Element | null;
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
pay?: RowWithActions<EntityDict, 'pay'>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Tag, Card, QRCode, Form, Descriptions, Typography, Alert, Button, Modal, Radio } from 'antd';
|
||||
import { Input, Tag, Card, QRCode, Form, Descriptions, Typography, Alert, Button, Modal, Radio } from 'antd';
|
||||
import { CheckCircleOutlined } from '@ant-design/icons';
|
||||
import { CentToString } from 'oak-domain/lib/utils/money';
|
||||
import Styles from './web.pc.module.less';
|
||||
|
|
@ -8,8 +8,8 @@ import duration from 'dayjs/plugin/duration';
|
|||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
dayJs.extend(duration);
|
||||
export function RenderOffline(props) {
|
||||
const { pay, t, offline, offlines, updateOfflineId } = props;
|
||||
const { iState, phantom3 } = pay;
|
||||
const { pay, t, offline, offlines, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, phantom3, externalId } = pay;
|
||||
const { type, channel, name, qrCode, color } = offline;
|
||||
const [show, setShow] = useState(false);
|
||||
const [showQrCode, setShowQrCode] = useState(false);
|
||||
|
|
@ -23,6 +23,12 @@ export function RenderOffline(props) {
|
|||
<Tag color="red">
|
||||
<span style={{ fontSize: 'large' }}>{phantom3}</span>
|
||||
</Tag>
|
||||
</Form.Item>,
|
||||
<Form.Item key="externalId" label={<span className={Styles.bold}>{t('externalId.label')}</span>}>
|
||||
<Input value={externalId || ''} onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
updateExternalId(value);
|
||||
}} placeholder={t('externalId.help')} disabled={iState !== 'paying'}/>
|
||||
</Form.Item>
|
||||
];
|
||||
if (type === 'bank') {
|
||||
|
|
@ -123,7 +129,7 @@ function RenderWechatPay(props) {
|
|||
return null;
|
||||
}
|
||||
function RenderPayMeta(props) {
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId } = props;
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, entity } = pay;
|
||||
if (entity !== 'offlineAccount' && notSameApp) {
|
||||
return <Alert type='warning' message={t('notSameApp')}/>;
|
||||
|
|
@ -133,7 +139,7 @@ function RenderPayMeta(props) {
|
|||
if (offline && offlines) {
|
||||
return (<>
|
||||
{iState === 'paying' && <Alert type='info' message={t('code.help')} style={{ marginBottom: 10 }}/>}
|
||||
<RenderOffline t={t} pay={pay} offline={offline} offlines={offlines} updateOfflineId={updateOfflineId}/>
|
||||
<RenderOffline t={t} pay={pay} offline={offline} offlines={offlines} updateOfflineId={updateOfflineId} updateExternalId={updateExternalId}/>
|
||||
</>);
|
||||
}
|
||||
return null;
|
||||
|
|
@ -214,6 +220,10 @@ export default function Render(props) {
|
|||
}
|
||||
}
|
||||
]);
|
||||
}} updateExternalId={(externalId) => {
|
||||
update({
|
||||
externalId,
|
||||
});
|
||||
}}/>
|
||||
</div>
|
||||
<div className={Styles.btn}>
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ export default function Render(props) {
|
|||
{offlines && <RenderOffline pay={spRow} t={t} offlines={offlines} offline={offlines.find(ele => ele.id === spRow.entityId)} updateOfflineId={(entityId) => updateItem({
|
||||
entity: 'offlineAccount',
|
||||
entityId
|
||||
}, spId)} updateExternalId={(externalId) => updateItem({
|
||||
externalId,
|
||||
}, spId)}/>}
|
||||
<Divider style={{ width: '80%', alignSelf: 'flex-end' }}/>
|
||||
<Form labelCol={{ span: 8 }} wrapperCol={{ span: 12 }} layout="horizontal" style={{ width: '100%', marginTop: 12 }}>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,12 @@ const attrUpdateMatrix = {
|
|||
}
|
||||
},
|
||||
externalId: {
|
||||
actions: ['startPaying', 'succeedPaying'],
|
||||
actions: ['startPaying', 'succeedPaying', 'update'],
|
||||
filter: {
|
||||
iState: {
|
||||
$in: ['unpaid', 'paying'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
refund: {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,15 @@ const i18ns = [
|
|||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/accountOper/list",
|
||||
data: {}
|
||||
data: {
|
||||
"history": "账户历史",
|
||||
"chooseMonth": "选择月份",
|
||||
"type": {
|
||||
"both": "全部",
|
||||
"in": "仅收入",
|
||||
"out": "仅支出"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "65d19e4723a89c25e3c10a87013af430",
|
||||
|
|
@ -198,11 +206,15 @@ const i18ns = [
|
|||
},
|
||||
"code": {
|
||||
"label": "转帐凭证号",
|
||||
"help": "请在转帐留言中附上转帐凭证号,便于人工核对"
|
||||
"help": "请在转帐时于留言中附上转帐凭证号,便于人工核对。若转账时忘记附上,则请准确填写转账流水号。"
|
||||
},
|
||||
"channel": {
|
||||
"change": "更换",
|
||||
"prefix": "渠道"
|
||||
},
|
||||
"externalId": {
|
||||
"label": "转账流水号",
|
||||
"help": "转账成功后有唯一流水号,将之正确填入可减少财务人员核对时的错误概率,给您带来更大便利"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -696,6 +708,7 @@ const i18ns = [
|
|||
"enter": "请输入",
|
||||
"change": "修改",
|
||||
"finish": "完成",
|
||||
"loadMore": "加载更多",
|
||||
"pay": {
|
||||
"symbol": "¥",
|
||||
"scale": "元"
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
"enter": "请输入",
|
||||
"change": "修改",
|
||||
"finish": "完成",
|
||||
"loadMore": "加载更多",
|
||||
"pay": {
|
||||
"symbol": "¥",
|
||||
"scale": "元"
|
||||
|
|
|
|||
|
|
@ -269,6 +269,17 @@ exports.default = OakComponent({
|
|||
});
|
||||
}
|
||||
},
|
||||
updateExternalIdMp(input) {
|
||||
const { detail } = input;
|
||||
this.update({
|
||||
externalId: detail.value,
|
||||
});
|
||||
},
|
||||
clearExternalIdMp() {
|
||||
this.update({
|
||||
externalId: null,
|
||||
});
|
||||
}
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,12 @@ const attrUpdateMatrix = {
|
|||
}
|
||||
},
|
||||
externalId: {
|
||||
actions: ['startPaying', 'succeedPaying'],
|
||||
actions: ['startPaying', 'succeedPaying', 'update'],
|
||||
filter: {
|
||||
iState: {
|
||||
$in: ['unpaid', 'paying'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
refund: {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,15 @@ const i18ns = [
|
|||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/accountOper/list",
|
||||
data: {}
|
||||
data: {
|
||||
"history": "账户历史",
|
||||
"chooseMonth": "选择月份",
|
||||
"type": {
|
||||
"both": "全部",
|
||||
"in": "仅收入",
|
||||
"out": "仅支出"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "65d19e4723a89c25e3c10a87013af430",
|
||||
|
|
@ -200,11 +208,15 @@ const i18ns = [
|
|||
},
|
||||
"code": {
|
||||
"label": "转帐凭证号",
|
||||
"help": "请在转帐留言中附上转帐凭证号,便于人工核对"
|
||||
"help": "请在转帐时于留言中附上转帐凭证号,便于人工核对。若转账时忘记附上,则请准确填写转账流水号。"
|
||||
},
|
||||
"channel": {
|
||||
"change": "更换",
|
||||
"prefix": "渠道"
|
||||
},
|
||||
"externalId": {
|
||||
"label": "转账流水号",
|
||||
"help": "转账成功后有唯一流水号,将之正确填入可减少财务人员核对时的错误概率,给您带来更大便利"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -698,6 +710,7 @@ const i18ns = [
|
|||
"enter": "请输入",
|
||||
"change": "修改",
|
||||
"finish": "完成",
|
||||
"loadMore": "加载更多",
|
||||
"pay": {
|
||||
"symbol": "¥",
|
||||
"scale": "元"
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
"enter": "请输入",
|
||||
"change": "修改",
|
||||
"finish": "完成",
|
||||
"loadMore": "加载更多",
|
||||
"pay": {
|
||||
"symbol": "¥",
|
||||
"scale": "元"
|
||||
|
|
|
|||
|
|
@ -290,6 +290,17 @@ export default OakComponent({
|
|||
})
|
||||
}
|
||||
},
|
||||
updateExternalIdMp(input: WechatMiniprogram.Input) {
|
||||
const { detail } = input;
|
||||
this.update({
|
||||
externalId: detail.value,
|
||||
});
|
||||
},
|
||||
clearExternalIdMp() {
|
||||
this.update({
|
||||
externalId: null,
|
||||
});
|
||||
}
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@
|
|||
<l-form-item label-width="240rpx" label="{{t('code.label')}}">
|
||||
<l-tag bg-color="#d9363e">{{pay.phantom3}}</l-tag>
|
||||
</l-form-item>
|
||||
<l-form-item label-width="240rpx" label="{{t('externalId.label')}}">
|
||||
<l-input
|
||||
hide-label="{{true}}"
|
||||
clear="{{true}}"
|
||||
disabled="{{pay.iState !== 'paying'}}"
|
||||
placeholder="{{t('externalId.help')}}"
|
||||
bind:lininput="updateExternalIdMp"
|
||||
bind:linclear="clearExternalIdMp"
|
||||
/>
|
||||
</l-form-item>
|
||||
<block wx:if="{{offline.type === 'bank'}}">
|
||||
<l-form-item label-width="240rpx" label="{{t('offlineAccount::label.channel.bank')}}">
|
||||
<view>{{offline.channel}}</view>
|
||||
|
|
|
|||
|
|
@ -25,10 +25,14 @@
|
|||
},
|
||||
"code": {
|
||||
"label": "转帐凭证号",
|
||||
"help": "请在转帐留言中附上转帐凭证号,便于人工核对"
|
||||
"help": "请在转帐时于留言中附上转帐凭证号,便于人工核对。若转账时忘记附上,则请准确填写转账流水号。"
|
||||
},
|
||||
"channel": {
|
||||
"change": "更换",
|
||||
"prefix": "渠道"
|
||||
},
|
||||
"externalId": {
|
||||
"label": "转账流水号",
|
||||
"help": "转账成功后有唯一流水号,将之正确填入可减少财务人员核对时的错误概率,给您带来更大便利"
|
||||
}
|
||||
}
|
||||
|
|
@ -16,10 +16,11 @@ export function RenderOffline(props: {
|
|||
t: (key: string) => string,
|
||||
offlines: ColoredOffline[];
|
||||
offline: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void
|
||||
updateOfflineId: (entityId: string) => void;
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}) {
|
||||
const { pay, t, offline, offlines, updateOfflineId } = props;
|
||||
const { iState, phantom3 } = pay;
|
||||
const { pay, t, offline, offlines, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, phantom3, externalId } = pay;
|
||||
const { type, channel, name, qrCode, color } = offline;
|
||||
|
||||
const [show, setShow] = useState(false);
|
||||
|
|
@ -41,6 +42,20 @@ export function RenderOffline(props: {
|
|||
<Tag color="red">
|
||||
<span style={{ fontSize: 'large' }}>{phantom3}</span>
|
||||
</Tag>
|
||||
</Form.Item>,
|
||||
<Form.Item
|
||||
key="externalId"
|
||||
label={<span className={Styles.bold}>{t('externalId.label')}</span>}
|
||||
>
|
||||
<Input
|
||||
value={externalId || ''}
|
||||
onChange={({ currentTarget }) => {
|
||||
const { value } = currentTarget;
|
||||
updateExternalId(value);
|
||||
}}
|
||||
placeholder={t('externalId.help')}
|
||||
disabled={iState !== 'paying'}
|
||||
/>
|
||||
</Form.Item>
|
||||
];
|
||||
if (type === 'bank') {
|
||||
|
|
@ -228,8 +243,9 @@ function RenderPayMeta(props: {
|
|||
offlines?: ColoredOffline[];
|
||||
offline?: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}) {
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId } = props;
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, entity } = pay;
|
||||
if (entity !== 'offlineAccount' && notSameApp) {
|
||||
return <Alert type='warning' message={t('notSameApp')} />
|
||||
|
|
@ -246,6 +262,7 @@ function RenderPayMeta(props: {
|
|||
offline={offline}
|
||||
offlines={offlines}
|
||||
updateOfflineId={updateOfflineId}
|
||||
updateExternalId={updateExternalId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
@ -384,6 +401,11 @@ export default function Render(props: WebComponentProps<EntityDict, 'pay', false
|
|||
}
|
||||
])
|
||||
}}
|
||||
updateExternalId={(externalId) => {
|
||||
update({
|
||||
externalId,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={Styles.btn}>
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ export function RenderOffline(props: {
|
|||
t: (key: string) => string,
|
||||
offlines: ColoredOffline[];
|
||||
offline: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void
|
||||
updateOfflineId: (entityId: string) => void;
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}) {
|
||||
const { pay, t, offline, offlines, updateOfflineId } = props;
|
||||
const { meta, iState, phantom3 } = pay;
|
||||
const { pay, t, offline, offlines, updateOfflineId, updateExternalId } = props;
|
||||
const { meta, iState, phantom3, externalId } = pay;
|
||||
const { type, channel, name, qrCode, color } = offline || {};
|
||||
|
||||
const [show, setShow] = useState(false);
|
||||
|
|
@ -45,6 +46,20 @@ export function RenderOffline(props: {
|
|||
<Tag color="red">
|
||||
<span style={{ fontSize: 'large' }}>{phantom3}</span>
|
||||
</Tag>
|
||||
</Form.Item>,
|
||||
<Form.Item
|
||||
key="externalId"
|
||||
label={<span className={Styles.bold}>{t('externalId.label')}</span>}
|
||||
>
|
||||
<Input
|
||||
autoFocus
|
||||
value={externalId || ''}
|
||||
onChange={(value) => {
|
||||
updateExternalId(value);
|
||||
}}
|
||||
placeholder={t('externalId.help')}
|
||||
disabled={iState !== 'paying'}
|
||||
/>
|
||||
</Form.Item>
|
||||
];
|
||||
if (type === 'bank') {
|
||||
|
|
@ -221,9 +236,10 @@ function RenderPayMeta(props: {
|
|||
t: (key: string) => string,
|
||||
offlines?: ColoredOffline[];
|
||||
offline?: ColoredOffline;
|
||||
updateOfflineId: (entityId: string) => void
|
||||
updateOfflineId: (entityId: string) => void;
|
||||
updateExternalId: (externalId: string) => void;
|
||||
}) {
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId } = props;
|
||||
const { pay, notSameApp, t, offlines, offline, updateOfflineId, updateExternalId } = props;
|
||||
const { iState, entity } = pay;
|
||||
if (entity !== 'offlineAccount' && notSameApp) {
|
||||
return <Alert type='warning' message={t('notSameApp')} />
|
||||
|
|
@ -240,6 +256,7 @@ function RenderPayMeta(props: {
|
|||
offline={offline}
|
||||
offlines={offlines}
|
||||
updateOfflineId={updateOfflineId}
|
||||
updateExternalId={updateExternalId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
@ -383,6 +400,9 @@ export default function Render(props: WebComponentProps<EntityDict, 'pay', false
|
|||
}
|
||||
])
|
||||
}}
|
||||
updateExternalId={(externalId) => {
|
||||
update({ externalId });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={Styles.padding} />
|
||||
|
|
|
|||
|
|
@ -197,6 +197,9 @@ export default function Render(props: WebComponentProps<EntityDict, 'pay', false
|
|||
entity: 'offlineAccount',
|
||||
entityId
|
||||
}, spId)}
|
||||
updateExternalId={(externalId) => updateItem({
|
||||
externalId,
|
||||
}, spId)}
|
||||
/>}
|
||||
<Divider style={{ width: '80%', alignSelf: 'flex-end' }} />
|
||||
<Form
|
||||
|
|
|
|||
|
|
@ -72,7 +72,12 @@ const attrUpdateMatrix: AttrUpdateMatrix<EntityDict> = {
|
|||
}
|
||||
},
|
||||
externalId: {
|
||||
actions: ['startPaying', 'succeedPaying'],
|
||||
actions: ['startPaying', 'succeedPaying', 'update'],
|
||||
filter: {
|
||||
iState: {
|
||||
$in: ['unpaid', 'paying'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
refund: {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,15 @@ const i18ns: I18n[] = [
|
|||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/accountOper/list",
|
||||
data: {}
|
||||
data: {
|
||||
"history": "账户历史",
|
||||
"chooseMonth": "选择月份",
|
||||
"type": {
|
||||
"both": "全部",
|
||||
"in": "仅收入",
|
||||
"out": "仅支出"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "65d19e4723a89c25e3c10a87013af430",
|
||||
|
|
@ -200,11 +208,15 @@ const i18ns: I18n[] = [
|
|||
},
|
||||
"code": {
|
||||
"label": "转帐凭证号",
|
||||
"help": "请在转帐留言中附上转帐凭证号,便于人工核对"
|
||||
"help": "请在转帐时于留言中附上转帐凭证号,便于人工核对。若转账时忘记附上,则请准确填写转账流水号。"
|
||||
},
|
||||
"channel": {
|
||||
"change": "更换",
|
||||
"prefix": "渠道"
|
||||
},
|
||||
"externalId": {
|
||||
"label": "转账流水号",
|
||||
"help": "转账成功后有唯一流水号,将之正确填入可减少财务人员核对时的错误概率,给您带来更大便利"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -698,6 +710,7 @@ const i18ns: I18n[] = [
|
|||
"enter": "请输入",
|
||||
"change": "修改",
|
||||
"finish": "完成",
|
||||
"loadMore": "加载更多",
|
||||
"pay": {
|
||||
"symbol": "¥",
|
||||
"scale": "元"
|
||||
|
|
|
|||
Loading…
Reference in New Issue