大量页面实现

This commit is contained in:
Xu Chang 2024-05-05 12:17:37 +08:00
parent ca2a7cbdfe
commit 68983bd5eb
13 changed files with 278 additions and 32 deletions

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
@ -5,4 +6,10 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
depositMax: number;
payConfig: PayConfig;
accountConfig?: AccountPayConfig;
}>): null;
onSetPrice: (price: null | number) => void;
onSetChannel: (channel: string) => void;
onSetMeta: (meta: any) => void;
price: number;
channel: string;
meta: any;
}>): React.JSX.Element | null;

View File

@ -1,9 +1,32 @@
import { useState } from 'react';
import React from 'react';
import ChannelPicker from '../../pay/channelPicker';
import { Form, Input } from 'antd-mobile';
import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
export default function Render(props) {
const { depositMax, payConfig } = props.data;
const { depositMax, payConfig, price, channel, meta, onSetChannel, onSetMeta, onSetPrice } = props.data;
const { t } = props.methods;
const [depPrice, setDepPrice] = useState(null);
const [depositChannel, setDepositChannel] = useState();
const [depositMeta, setDepositMeta] = useState();
if (payConfig) {
return (<Form layout="horizontal">
<Form.Item label={<span>{t("label.depPrice")}:</span>} extra={t('common::pay.symbol')}>
<Input type='number' placeholder={t('placeholder', { max: depositMax })} max={depositMax} min={1} value={typeof price == 'number' ? `${ToYuan(price)}` : undefined} onChange={(value) => {
if (value === '' || value === null) {
onSetPrice(null);
return;
}
const v = parseInt(value);
if (!isNaN(v)) {
onSetPrice(ToCent(v));
}
}}/>
</Form.Item>
{price > 0 && <Form.Item label={<span>
{t('label.channel')}:
</span>}>
<ChannelPicker payConfig={payConfig} onPick={(channel) => {
onSetChannel(channel);
}} channel={channel} meta={meta} onSetMeta={(meta) => onSetMeta(meta)}/>
</Form.Item>}
</Form>);
}
return null;
}

View File

@ -8,17 +8,17 @@ export default function Render(props) {
if (payConfig) {
return (<Form labelCol={{ span: 4 }} wrapperCol={{ span: 14 }} layout="horizontal" style={{ minWidth: 600 }} colon={false}>
<Form.Item label={<span>{t("label.depPrice")}:</span>}>
<InputNumber placeholder={t('placeholder', { max: depositMax })} max={depositMax} min={1} value={ToYuan(price)} addonAfter={t('common::pay.symbol')} onChange={(value) => {
<InputNumber placeholder={t('placeholder', { max: depositMax })} max={depositMax} min={1} value={typeof price == 'number' ? ToYuan(price) : null} addonAfter={t('common::pay.symbol')} onChange={(value) => {
onSetPrice(ToCent(value || 0));
}}/>
</Form.Item>
<Form.Item label={<span style={{ marginTop: 10 }}>
{price > 0 ? <Form.Item label={<span style={{ marginTop: 10 }}>
{t('label.channel')}:
</span>}>
<ChannelPicker payConfig={payConfig} onPick={(channel) => {
onSetChannel(channel);
}} channel={channel} meta={meta} onSetMeta={(meta) => onSetMeta(meta)}/>
</Form.Item>
onSetChannel(channel);
}} channel={channel} meta={meta} onSetMeta={(meta) => onSetMeta(meta)}/>
</Form.Item> : <div style={{ height: 120 }}/>}
</Form>);
}
return null;

View File

@ -1,7 +1,12 @@
import React from 'react';
import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '../../../oak-app-domain';
import { PayConfig } from '../../../types/PayConfig';
import { OfflinePayConfig, PayConfig } from '../../../types/PayConfig';
export default function Render(props: WebComponentProps<EntityDict, keyof EntityDict, false, {
channels: PayConfig[];
payConfig: PayConfig;
offlineConfig?: OfflinePayConfig;
channel: string;
meta?: any;
onPick: (channel: string, meta?: object) => void;
}>): null;
onSetMeta: (meta?: object) => void;
}>): React.JSX.Element;

View File

@ -1,3 +1,56 @@
import React, { useState } from 'react';
import { Radio, Space, Picker, Button } from 'antd-mobile';
import { PAY_CHANNEL_ACCOUNT_NAME, 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 { WechatOutlined, WalletOutlined } from '@ant-design/icons';
import Styles from './web.mobile.module.less';
const ChannelIconDict = {
[PAY_CHANNEL_ACCOUNT_NAME]: <WalletOutlined />,
[PAY_CHANNEL_OFFLINE_NAME]: <WalletOutlined />,
[PAY_CHANNEL_WECHAT_APP_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_JS_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_NATIVE_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_H5_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_MP_NAME]: <WechatOutlined />,
};
export default function Render(props) {
return null;
const { payConfig, offlineConfig, channel, onPick, meta, onSetMeta } = props.data;
const { t } = props.methods;
const [offlinePickerVisible, setOpVisible] = useState(false);
const Offline = offlineConfig && offlineConfig.options?.length && (<>
<Button onClick={() => setOpVisible(true)}>
{meta?.option || t('common::change')}
</Button>
<Picker value={meta?.option} columns={[offlineConfig.options.map(ele => ({
label: ele,
value: ele,
}))]} visible={offlinePickerVisible} onConfirm={(value) => {
onSetMeta({
...meta,
option: value[0],
});
setOpVisible(false);
}} onCancel={() => setOpVisible(false)}/>
</>);
return (<Radio.Group onChange={(value) => {
onPick(value);
if (value === PAY_CHANNEL_OFFLINE_NAME && offlineConfig?.options?.length) {
onSetMeta({
option: offlineConfig.options[0],
});
}
else {
onSetMeta({});
}
}} value={channel}>
<Space direction="vertical">
{payConfig.map((v) => (<Radio value={v.channel} key={v.channel}>
<Space direction="horizontal" align='center'>
<span className={Styles.span}>
{t(`payChannel::${v.channel}`)}
</span>
{v.channel === PAY_CHANNEL_OFFLINE_NAME && channel === PAY_CHANNEL_OFFLINE_NAME && Offline}
</Space>
</Radio>))}
</Space>
</Radio.Group>);
}

View File

@ -0,0 +1,3 @@
.span {
margin-right: 10px;
}

View File

@ -26,7 +26,17 @@ export default function Render(props) {
});
}}/>
</span>);
return (<Radio.Group onChange={({ target }) => onPick(target.value)} value={channel}>
return (<Radio.Group onChange={({ target }) => {
onPick(target.value);
if (target.value === PAY_CHANNEL_OFFLINE_NAME && offlineConfig?.options?.length) {
onSetMeta({
option: offlineConfig.options[0],
});
}
else {
onSetMeta({});
}
}} value={channel}>
<Space direction="vertical">
{payConfig.map((v) => (<Radio value={v.channel} key={v.channel}>
<Flex gap="middle" className={Styles.option} align='center'>

View File

@ -36,14 +36,14 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
placeholder={t('placeholder', { max: depositMax })}
max={depositMax}
min={1}
value={ToYuan(price)}
value={typeof price == 'number' ? ToYuan(price) : null}
addonAfter={t('common::pay.symbol')}
onChange={(value) => {
onSetPrice(ToCent(value || 0));
}}
/>
</Form.Item>
<Form.Item label={<span style={{ marginTop: 10 }}>
{price > 0 ? <Form.Item label={<span style={{ marginTop: 10 }}>
{t('label.channel')}:
</span>}>
<ChannelPicker
@ -55,7 +55,7 @@ export default function Render(props: WebComponentProps<EntityDict, 'account', f
meta={meta}
onSetMeta={(meta) => onSetMeta(meta)}
/>
</Form.Item>
</Form.Item> : <div style={{ height: 120 }} />}
</Form>
);
}

View File

@ -3,19 +3,69 @@ import { WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '@project/oak-app-domain';
import ChannelPicker from '../../pay/channelPicker';
import { AccountPayConfig, PayConfig } from '@project/types/PayConfig';
import { Form, Input } from 'antd-mobile';
import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
export default function Render(props: WebComponentProps<EntityDict, 'account', false, {
depositMax: number;
payConfig: PayConfig;
accountConfig?: AccountPayConfig;
onSetPrice: (price: null | number) => void;
onSetChannel: (channel: string) => void;
onSetMeta: (meta: any) => void;
price: number;
channel: string;
meta: any;
}>) {
const { depositMax, payConfig } = props.data;
const { depositMax, payConfig, price, channel, meta,
onSetChannel, onSetMeta, onSetPrice } = props.data;
const { t } = props.methods;
const [depPrice, setDepPrice] = useState<null | number>(null);
const [depositChannel, setDepositChannel] = useState<string | undefined>();
const [depositMeta, setDepositMeta] = useState<any>();
if (payConfig) {
return (
<Form
layout="horizontal"
>
<Form.Item
label={<span>{t("label.depPrice")}:</span>}
extra={t('common::pay.symbol')}
>
<Input
type='number'
placeholder={t('placeholder', { max: depositMax })}
max={depositMax}
min={1}
value={typeof price == 'number' ? `${ToYuan(price)}` : undefined}
onChange={(value) => {
if (value === '' || value === null) {
onSetPrice(null);
return;
}
const v = parseInt(value);
if (!isNaN(v)) {
onSetPrice(ToCent(v));
}
}}
/>
</Form.Item>
{price > 0 && <Form.Item label={
<span>
{t('label.channel')}:
</span>
}>
<ChannelPicker
payConfig={payConfig}
onPick={(channel) => {
onSetChannel(channel);
}}
channel={channel}
meta={meta}
onSetMeta={(meta) => onSetMeta(meta)}
/>
</Form.Item>}
</Form>
);
}
return null;
}

View File

@ -60,7 +60,7 @@ export default OakComponent({
},
actions: ['deposit', 'withdraw'],
methods: {
async createDepositPay(price: number, channel: string, meta: object, success: () => void) {
async createDepositPay(price: number, channel: string, meta: object) {
const payId = await generateNewIdAsync();
const { oakId } = this.props;
await this.execute(undefined, undefined, undefined, [

View File

@ -0,0 +1,3 @@
.span {
margin-right: 10px;
}

View File

@ -56,7 +56,17 @@ export default function Render(props: WebComponentProps<EntityDict, keyof Entity
</span>
);
return (
<Radio.Group onChange={({ target }) => onPick(target.value)} value={channel}>
<Radio.Group onChange={({ target }) => {
onPick(target.value as string);
if (target.value === PAY_CHANNEL_OFFLINE_NAME && offlineConfig?.options?.length) {
onSetMeta({
option: offlineConfig!.options![0],
});
}
else {
onSetMeta({});
}
}} value={channel} >
<Space direction="vertical">
{
payConfig.map(
@ -76,6 +86,6 @@ export default function Render(props: WebComponentProps<EntityDict, keyof Entity
)
}
</Space>
</Radio.Group>
</Radio.Group >
);
}

View File

@ -1,15 +1,97 @@
import React, { useState } from 'react';
import { Button, Modal, Card, Flex, Form, InputNumber } from 'antd';
import { Input, Radio, Space, Picker, Button } from 'antd-mobile';
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
import { EntityDict } from '@project/oak-app-domain';
import Styles from './web.pc.module.less';
import classNames from 'classnames';
import { PayConfig } from '@project/types/PayConfig';
import {
OfflinePayConfig,
PAY_CHANNEL_ACCOUNT_NAME, 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, PayConfig
} from '../../../types/PayConfig';
import { WechatOutlined, MoneyCollectOutlined, WalletOutlined } from '@ant-design/icons';
import Styles from './web.mobile.module.less';
const ChannelIconDict = {
[PAY_CHANNEL_ACCOUNT_NAME]: <WalletOutlined />,
[PAY_CHANNEL_OFFLINE_NAME]: <WalletOutlined />,
[PAY_CHANNEL_WECHAT_APP_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_JS_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_NATIVE_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_H5_NAME]: <WechatOutlined />,
[PAY_CHANNEL_WECHAT_MP_NAME]: <WechatOutlined />,
};
export default function Render(props: WebComponentProps<EntityDict, keyof EntityDict, false, {
channels: PayConfig[];
payConfig: PayConfig;
offlineConfig?: OfflinePayConfig;
channel: string;
meta?: any;
onPick: (channel: string, meta?: object) => void;
onSetMeta: (meta?: object) => void;
}>) {
return null;
const { payConfig, offlineConfig, channel, onPick, meta, onSetMeta } = props.data;
const { t } = props.methods;
const [offlinePickerVisible, setOpVisible] = useState(false);
const Offline = offlineConfig && offlineConfig.options?.length && (
<>
<Button
onClick={() => setOpVisible(true)}
>
{meta?.option || t('common::change')}
</Button>
<Picker
value={meta?.option}
columns={[offlineConfig.options!.map(
ele => ({
label: ele,
value: ele,
})
)]}
visible={offlinePickerVisible}
onConfirm={(value) => {
onSetMeta({
...meta,
option: value[0],
});
setOpVisible(false);
}}
onCancel={() => setOpVisible(false)}
/>
</>
);
return (
<Radio.Group onChange={(value) => {
onPick(value as string);
if (value === PAY_CHANNEL_OFFLINE_NAME && offlineConfig?.options?.length) {
onSetMeta({
option: offlineConfig!.options![0],
});
}
else {
onSetMeta({});
}
}} value={channel}>
<Space direction="vertical">
{
payConfig.map(
(v) => (
<Radio
value={v.channel}
key={v.channel}
>
<Space direction="horizontal" align='center' >
<span className={Styles.span}>
{t(`payChannel::${v.channel}`)}
</span>
{v.channel === PAY_CHANNEL_OFFLINE_NAME && channel === PAY_CHANNEL_OFFLINE_NAME && Offline}
</Space>
</Radio>
)
)
}
</Space>
</Radio.Group>
);
}