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