nili
7 months ago
11 changed files with 628 additions and 18 deletions
@ -0,0 +1,201 @@ |
|||
import { getAppNormalConfig, saveNormalConfig } from '@/services/matrix/matrixAppController'; |
|||
import { InfoCircleOutlined, MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; |
|||
import { Button, Col, Form, Input, InputNumber, Modal, Row, Tooltip } from 'antd'; |
|||
import React, { useEffect } from 'react'; |
|||
|
|||
export type CashConfigFormProps = { |
|||
onCancel: () => void; |
|||
onSubmit: () => void; |
|||
updateModalOpen: boolean; |
|||
appCode: string; |
|||
}; |
|||
|
|||
const CashConfigForm: React.FC<CashConfigFormProps> = (props) => { |
|||
const [form] = Form.useForm(); |
|||
|
|||
const handleOk = () => { |
|||
form.submit(); |
|||
}; |
|||
|
|||
const handleCancel = () => { |
|||
props.onCancel(); |
|||
}; |
|||
|
|||
const fetchConfig = async (appCode: string) => { |
|||
const data = await getAppNormalConfig({ appCode }); |
|||
|
|||
form.setFieldsValue(data.data); |
|||
}; |
|||
|
|||
useEffect(() => { |
|||
fetchConfig(props.appCode); |
|||
}, [props.appCode]); |
|||
|
|||
const handleSaveApp = async (values: API.AppNormalConfig) => { |
|||
try { |
|||
await saveNormalConfig({ appCode: props.appCode }, values); |
|||
} catch (e) { |
|||
return; |
|||
} |
|||
props.onSubmit(); |
|||
}; |
|||
|
|||
const formItemLayout = { |
|||
labelCol: { |
|||
xs: { span: 24 }, |
|||
sm: { span: 6 }, |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 24 }, |
|||
sm: { span: 20 }, |
|||
}, |
|||
}; |
|||
const formItemLayoutWithOutLabel = { |
|||
wrapperCol: { |
|||
xs: { span: 24, offset: 0 }, |
|||
sm: { span: 20, offset: 6 }, |
|||
}, |
|||
}; |
|||
|
|||
return ( |
|||
<Modal title="编辑" visible={props.updateModalOpen} onOk={handleOk} onCancel={handleCancel}> |
|||
<Form form={form} onFinish={handleSaveApp}> |
|||
<Form.List name="moneyLadder"> |
|||
{(fields, { add, remove }) => ( |
|||
<> |
|||
{fields.map((field, index) => ( |
|||
<Form.Item |
|||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)} |
|||
label={index === 0 ? '提现梯度' : ''} |
|||
required={false} |
|||
key={field.key} |
|||
> |
|||
<Form.Item |
|||
{...field} |
|||
validateTrigger={['onChange', 'onBlur']} |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
whitespace: true, |
|||
message: '请输入金额或者删除本行', |
|||
}, |
|||
]} |
|||
noStyle |
|||
> |
|||
<InputNumber placeholder="金额,单位分" style={{ width: '60%' }} /> |
|||
</Form.Item> |
|||
{fields.length > 1 ? ( |
|||
<MinusCircleOutlined |
|||
className="dynamic-delete-button" |
|||
onClick={() => remove(field.name)} |
|||
/> |
|||
) : null} |
|||
</Form.Item> |
|||
))} |
|||
<Form.Item {...formItemLayoutWithOutLabel}> |
|||
<Button |
|||
type="dashed" |
|||
onClick={() => add()} |
|||
style={{ width: '60%' }} |
|||
icon={<PlusOutlined />} |
|||
> |
|||
添加 |
|||
</Button> |
|||
</Form.Item> |
|||
</> |
|||
)} |
|||
</Form.List> |
|||
<Form.Item |
|||
name="noAuditMoney" |
|||
label={ |
|||
<> |
|||
自动到账门槛(分) |
|||
<span style={{ marginLeft: 4 }}> |
|||
<Tooltip title="低于此金额的提现申请将会自动审核通过"> |
|||
<InfoCircleOutlined /> |
|||
</Tooltip> |
|||
</span> |
|||
</> |
|||
} |
|||
> |
|||
<InputNumber placeholder="单位分" style={{ width: '60%' }} /> |
|||
</Form.Item> |
|||
<Form.Item name="qqUrl" label="QQ群链接"> |
|||
<Input /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
name="dayLimit" |
|||
label={ |
|||
<> |
|||
每日提现次数 |
|||
<span style={{ marginLeft: 4 }}> |
|||
<Tooltip title="同个账号或同个支付宝每日最多提现的次数"> |
|||
<InfoCircleOutlined /> |
|||
</Tooltip> |
|||
</span> |
|||
</> |
|||
} |
|||
> |
|||
<InputNumber style={{ width: '60%' }} /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
name="maxIncomeEachVideo" |
|||
label={ |
|||
<> |
|||
单条收益上限 |
|||
<span style={{ marginLeft: 4 }}> |
|||
<Tooltip title="看一条视频最多能获得的钱,单位分"> |
|||
<InfoCircleOutlined /> |
|||
</Tooltip> |
|||
</span> |
|||
</> |
|||
} |
|||
> |
|||
<InputNumber style={{ width: '60%' }} /> |
|||
</Form.Item> |
|||
<Form.Item name="defaultRate" label={<>默认分成比例</>}> |
|||
<InputNumber style={{ width: '60%' }} /> |
|||
</Form.Item> |
|||
<Form.List name="dayRates"> |
|||
{(fields, { add, remove }) => ( |
|||
<> |
|||
{fields.map(({ key, name }, index) => ( |
|||
<> |
|||
<Form.Item |
|||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)} |
|||
label={index === 0 ? '特殊日分成比例' : ''} |
|||
required={false} |
|||
key={key} |
|||
> |
|||
<Row key={key} align="stretch" gutter={16}> |
|||
<Col span={8}> |
|||
<Form.Item name={[name, 'day']} rules={[{ required: true }]}> |
|||
<Input placeholder="Day" /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col span={8}> |
|||
<Form.Item name={[name, 'rate']} rules={[{ required: true }]}> |
|||
<Input placeholder="Rate" /> |
|||
</Form.Item> |
|||
</Col> |
|||
<Col> |
|||
<MinusCircleOutlined onClick={() => remove(name)} /> |
|||
</Col> |
|||
</Row> |
|||
</Form.Item> |
|||
</> |
|||
))} |
|||
<Form.Item> |
|||
<Button type="dashed" onClick={() => add()} block> |
|||
Add Field |
|||
</Button> |
|||
</Form.Item> |
|||
</> |
|||
)} |
|||
</Form.List> |
|||
</Form> |
|||
</Modal> |
|||
); |
|||
}; |
|||
|
|||
export default CashConfigForm; |
@ -0,0 +1,117 @@ |
|||
import { appList } from '@/services/matrix/admin'; |
|||
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components'; |
|||
import { Input, Popover, QRCode } from 'antd'; |
|||
import { useEffect, useState } from 'react'; |
|||
|
|||
import CashConfigForm from './CashConfigForm'; |
|||
|
|||
const NormalAppManagement = () => { |
|||
const [visible, setVisible] = useState(false); |
|||
|
|||
const [appArr, setAppArr] = useState<API.MatrixApp[]>([]); |
|||
const [filteredAppArr, setFilteredAppArr] = useState<API.MatrixApp[]>([]); |
|||
|
|||
const [appCode, setAppCode] = useState<string>(); |
|||
|
|||
const columns: ProColumns<API.MatrixAppBo>[] = [ |
|||
{ |
|||
title: '应用名', |
|||
dataIndex: 'name', |
|||
copyable: true, |
|||
hideInSearch: true, |
|||
}, |
|||
{ |
|||
title: '应用图片', |
|||
dataIndex: 'img', |
|||
hideInSearch: true, |
|||
renderText: (img: string) => <img style={{ width: '40px' }} src={img} />, |
|||
}, |
|||
{ |
|||
title: 'code', |
|||
dataIndex: 'code', |
|||
copyable: true, |
|||
hideInSearch: true, |
|||
}, |
|||
{ |
|||
title: '下载地址', |
|||
dataIndex: 'url', |
|||
width: 200, |
|||
hideInSearch: true, |
|||
renderText: (url: string) => ( |
|||
<Popover |
|||
overlayInnerStyle={{ padding: 0 }} |
|||
content={<QRCode value={url || ''} bordered={false} />} |
|||
> |
|||
<a style={{ wordBreak: 'break-word' }}>{url}</a> |
|||
</Popover> |
|||
), |
|||
}, |
|||
{ |
|||
title: '操作', |
|||
width: 80, |
|||
hideInSearch: true, |
|||
renderText: (r: API.MatrixAppBo) => { |
|||
if (r.enableCash) { |
|||
return ( |
|||
<a |
|||
key="edit" |
|||
onClick={() => { |
|||
setAppCode(r.code); |
|||
setVisible(true); |
|||
}} |
|||
> |
|||
编辑 |
|||
</a> |
|||
); |
|||
} |
|||
}, |
|||
}, |
|||
]; |
|||
|
|||
const fetchApp = async () => { |
|||
const res = await appList(); |
|||
if (res.data) { |
|||
setAppArr(res.data); |
|||
setFilteredAppArr(res.data); |
|||
} |
|||
}; |
|||
|
|||
useEffect(() => { |
|||
fetchApp(); |
|||
}, []); |
|||
|
|||
return ( |
|||
<PageContainer> |
|||
<ProTable |
|||
search={{ |
|||
defaultCollapsed: false, // 默认展开搜索框
|
|||
optionRender: () => [ |
|||
// 自定义搜索框
|
|||
<Input |
|||
key="name" |
|||
placeholder="请输入应用名" |
|||
onChange={(e) => handleSearch(e.target.value)} |
|||
/>, |
|||
], |
|||
}} |
|||
onReset={() => { |
|||
setFilteredAppArr(appArr); |
|||
}} |
|||
columns={columns} |
|||
dataSource={filteredAppArr} |
|||
/> |
|||
{appCode && ( |
|||
<CashConfigForm |
|||
updateModalOpen={visible} |
|||
appCode={appCode || ''} |
|||
onCancel={() => setVisible(false)} |
|||
onSubmit={() => { |
|||
setVisible(false); |
|||
}} |
|||
/> |
|||
)} |
|||
</PageContainer> |
|||
); |
|||
}; |
|||
|
|||
export default NormalAppManagement; |
@ -0,0 +1,18 @@ |
|||
// @ts-ignore
|
|||
/* eslint-disable */ |
|||
import { request } from '@umijs/max'; |
|||
|
|||
/** 此处后端没有提供注释 GET /api/citrus/app/getDetail */ |
|||
export async function getAppDetail( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.getAppDetailParams, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RAppCashConfig>('/api/citrus/app/getDetail', { |
|||
method: 'GET', |
|||
params: { |
|||
...params, |
|||
}, |
|||
...(options || {}), |
|||
}); |
|||
} |
@ -0,0 +1,38 @@ |
|||
// @ts-ignore
|
|||
/* eslint-disable */ |
|||
import { request } from '@umijs/max'; |
|||
|
|||
/** 此处后端没有提供注释 GET /api/matrix/app/normalConfig */ |
|||
export async function getAppNormalConfig( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.getAppNormalConfigParams, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RAppNormalConfig>('/api/matrix/app/normalConfig', { |
|||
method: 'GET', |
|||
params: { |
|||
...params, |
|||
}, |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 POST /api/matrix/app/normalConfig */ |
|||
export async function saveNormalConfig( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.saveNormalConfigParams, |
|||
body: API.AppNormalConfig, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RVoid>('/api/matrix/app/normalConfig', { |
|||
method: 'POST', |
|||
headers: { |
|||
'Content-Type': 'application/json', |
|||
}, |
|||
params: { |
|||
...params, |
|||
}, |
|||
data: body, |
|||
...(options || {}), |
|||
}); |
|||
} |
@ -0,0 +1,46 @@ |
|||
// @ts-ignore
|
|||
/* eslint-disable */ |
|||
import { request } from '@umijs/max'; |
|||
|
|||
/** 此处后端没有提供注释 POST /api/citrus/user/applyCash */ |
|||
export async function applyCash( |
|||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
|||
params: API.applyCashParams, |
|||
options?: { [key: string]: any }, |
|||
) { |
|||
return request<API.RVoid>('/api/citrus/user/applyCash', { |
|||
method: 'POST', |
|||
params: { |
|||
...params, |
|||
}, |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 POST /api/citrus/user/bindAliPay */ |
|||
export async function bindAliPay(body: API.UserBo, options?: { [key: string]: any }) { |
|||
return request<API.RVoid>('/api/citrus/user/bindAliPay', { |
|||
method: 'POST', |
|||
headers: { |
|||
'Content-Type': 'application/json', |
|||
}, |
|||
data: body, |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 GET /api/citrus/user/cashRecords */ |
|||
export async function getCashRecord(options?: { [key: string]: any }) { |
|||
return request<API.RListCashRecord>('/api/citrus/user/cashRecords', { |
|||
method: 'GET', |
|||
...(options || {}), |
|||
}); |
|||
} |
|||
|
|||
/** 此处后端没有提供注释 GET /api/citrus/user/current */ |
|||
export async function currentUser1(options?: { [key: string]: any }) { |
|||
return request<API.RUserBo>('/api/citrus/user/current', { |
|||
method: 'GET', |
|||
...(options || {}), |
|||
}); |
|||
} |
Loading…
Reference in new issue