From 305ad8fa5bfa91353f45ea1915ef73cc0646590d Mon Sep 17 00:00:00 2001 From: nili Date: Sun, 19 May 2024 21:31:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.ts | 9 +- src/pages/{ => App}/AppManagement.tsx | 64 +++++- src/pages/App/CashConfigForm.tsx | 201 ++++++++++++++++++ src/pages/App/NormalAppManagement.tsx | 117 ++++++++++ src/services/matrix/admin.ts | 2 +- src/services/matrix/citrusAppController.ts | 18 ++ src/services/matrix/index.ts | 10 +- src/services/matrix/matrixAppController.ts | 38 ++++ ...egisterController.ts => openController.ts} | 36 ++++ src/services/matrix/typings.d.ts | 105 ++++++++- src/services/matrix/userController.ts | 46 ++++ 11 files changed, 628 insertions(+), 18 deletions(-) rename src/pages/{ => App}/AppManagement.tsx (77%) create mode 100644 src/pages/App/CashConfigForm.tsx create mode 100644 src/pages/App/NormalAppManagement.tsx create mode 100644 src/services/matrix/citrusAppController.ts create mode 100644 src/services/matrix/matrixAppController.ts rename src/services/matrix/{registerController.ts => openController.ts} (54%) create mode 100644 src/services/matrix/userController.ts diff --git a/config/routes.ts b/config/routes.ts index 1fc77d1..e39cec1 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -1,5 +1,4 @@ - -/** +/** * @name umi 的路由配置 * @description 只支持 path,component,routes,redirect,wrappers,name,icon 的配置 * @param path path 只支持两种占位符配置,第一种是动态参数 :id 的形式,第二种是 * 通配符,通配符只能出现路由字符串的最后。 @@ -54,19 +53,19 @@ export default [ path: '/adminList', name: '人员管理', access: 'canAdmin', - component: './AdminManagement' + component: './AdminManagement', }, { path: '/bind', name: '绑定设备', access: 'canDeviceOwner', - component: './Bind' + component: './Bind', }, { path: '/appList', name: '应用管理', access: 'canAdmin', - component: './AppManagement' + component: './App/AppManagement', }, { path: '/', diff --git a/src/pages/AppManagement.tsx b/src/pages/App/AppManagement.tsx similarity index 77% rename from src/pages/AppManagement.tsx rename to src/pages/App/AppManagement.tsx index b1f71e5..1036fd7 100644 --- a/src/pages/AppManagement.tsx +++ b/src/pages/App/AppManagement.tsx @@ -4,6 +4,7 @@ import { Button, Form, Input, Modal, Popover, QRCode, Select, Tag } from 'antd'; import { useEffect, useState } from 'react'; import { appList, saveApp } from '@/services/matrix/admin'; +import NormalAppManagement from './NormalAppManagement'; const AppManagement = () => { const [visible, setVisible] = useState(false); @@ -13,15 +14,15 @@ const AppManagement = () => { const [filteredAppArr, setFilteredAppArr] = useState([]); const { initialState } = useModel('@@initialState'); const currentUser = initialState?.currentUser; - const canUpdate = currentUser && currentUser.role && currentUser.role < 2; + const superAdmin = currentUser && currentUser.role && currentUser.role < 2; - const handleEdit = (record: API.MatrixApp) => { + const handleEdit = (record: API.MatrixAppBo) => { form.setFieldsValue(record); setVisible(true); setEditing(true); }; - const columns: ProColumns[] = [ + const columns: ProColumns[] = [ { title: '应用名', dataIndex: 'name', @@ -56,8 +57,53 @@ const AppManagement = () => { }, ]; - const columnsWithOperation: ProColumns[] = [ - ...columns, + const superAdminColumns: ProColumns[] = [ + { + title: '应用名', + dataIndex: 'name', + copyable: true, + hideInSearch: true, + }, + { + title: '应用图片', + dataIndex: 'img', + hideInSearch: true, + renderText: (img: string) => , + }, + { + title: 'code', + dataIndex: 'code', + copyable: true, + hideInSearch: true, + }, + { + title: '下载地址', + dataIndex: 'url', + width: 200, + hideInSearch: true, + renderText: (url: string) => ( + } + > + {url} + + ), + }, + { + title: '操作', + width: 80, + hideInSearch: true, + renderText: (r: API.MatrixAppBo) => { + if (r.enableCash) { + return ( + handleEdit(r)}> + 编辑 + + ); + } + }, + }, { title: 'secret', dataIndex: 'secret', @@ -95,7 +141,7 @@ const AppManagement = () => { title: '操作', width: 80, hideInSearch: true, - renderText: (record: API.MatrixApp) => ( + renderText: (record: API.MatrixAppBo) => ( handleEdit(record)}> 编辑 @@ -143,6 +189,10 @@ const AppManagement = () => { setFilteredAppArr(filtered); }; + if (!superAdmin) { + return ; + } + return ( {currentUser && currentUser.role && currentUser.role < 2 && ( @@ -165,7 +215,7 @@ const AppManagement = () => { onReset={() => { setFilteredAppArr(appArr); }} - columns={canUpdate ? columnsWithOperation : columns} + columns={superAdmin ? superAdminColumns : columns} dataSource={filteredAppArr} /> diff --git a/src/pages/App/CashConfigForm.tsx b/src/pages/App/CashConfigForm.tsx new file mode 100644 index 0000000..f3bb84b --- /dev/null +++ b/src/pages/App/CashConfigForm.tsx @@ -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 = (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 ( + +
+ + {(fields, { add, remove }) => ( + <> + {fields.map((field, index) => ( + + + + + {fields.length > 1 ? ( + remove(field.name)} + /> + ) : null} + + ))} + + + + + )} + + + 自动到账门槛(分) + + + + + + + } + > + + + + + + + 每日提现次数 + + + + + + + } + > + + + + 单条收益上限 + + + + + + + } + > + + + 默认分成比例}> + + + + {(fields, { add, remove }) => ( + <> + {fields.map(({ key, name }, index) => ( + <> + + + + + + + + + + + + + + remove(name)} /> + + + + + ))} + + + + + )} + +
+
+ ); +}; + +export default CashConfigForm; diff --git a/src/pages/App/NormalAppManagement.tsx b/src/pages/App/NormalAppManagement.tsx new file mode 100644 index 0000000..7e47c10 --- /dev/null +++ b/src/pages/App/NormalAppManagement.tsx @@ -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([]); + const [filteredAppArr, setFilteredAppArr] = useState([]); + + const [appCode, setAppCode] = useState(); + + const columns: ProColumns[] = [ + { + title: '应用名', + dataIndex: 'name', + copyable: true, + hideInSearch: true, + }, + { + title: '应用图片', + dataIndex: 'img', + hideInSearch: true, + renderText: (img: string) => , + }, + { + title: 'code', + dataIndex: 'code', + copyable: true, + hideInSearch: true, + }, + { + title: '下载地址', + dataIndex: 'url', + width: 200, + hideInSearch: true, + renderText: (url: string) => ( + } + > + {url} + + ), + }, + { + title: '操作', + width: 80, + hideInSearch: true, + renderText: (r: API.MatrixAppBo) => { + if (r.enableCash) { + return ( + { + setAppCode(r.code); + setVisible(true); + }} + > + 编辑 + + ); + } + }, + }, + ]; + + const fetchApp = async () => { + const res = await appList(); + if (res.data) { + setAppArr(res.data); + setFilteredAppArr(res.data); + } + }; + + useEffect(() => { + fetchApp(); + }, []); + + return ( + + [ + // 自定义搜索框 + handleSearch(e.target.value)} + />, + ], + }} + onReset={() => { + setFilteredAppArr(appArr); + }} + columns={columns} + dataSource={filteredAppArr} + /> + {appCode && ( + setVisible(false)} + onSubmit={() => { + setVisible(false); + }} + /> + )} + + ); +}; + +export default NormalAppManagement; diff --git a/src/services/matrix/admin.ts b/src/services/matrix/admin.ts index 490afbf..4b034bb 100644 --- a/src/services/matrix/admin.ts +++ b/src/services/matrix/admin.ts @@ -51,7 +51,7 @@ export async function advList(body: API.AdvRecordQuery, options?: { [key: string /** 此处后端没有提供注释 GET /api/admin/appList */ export async function appList(options?: { [key: string]: any }) { - return request('/api/admin/appList', { + return request('/api/admin/appList', { method: 'GET', ...(options || {}), }); diff --git a/src/services/matrix/citrusAppController.ts b/src/services/matrix/citrusAppController.ts new file mode 100644 index 0000000..03afb5c --- /dev/null +++ b/src/services/matrix/citrusAppController.ts @@ -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/citrus/app/getDetail', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }); +} diff --git a/src/services/matrix/index.ts b/src/services/matrix/index.ts index f15629e..c68093f 100644 --- a/src/services/matrix/index.ts +++ b/src/services/matrix/index.ts @@ -4,15 +4,21 @@ // API 唯一标识: import * as admin from './admin'; import * as appController from './appController'; +import * as citrusAppController from './citrusAppController'; import * as device from './device'; import * as loginController from './loginController'; +import * as matrixAppController from './matrixAppController'; import * as matrixController from './matrixController'; -import * as registerController from './registerController'; +import * as openController from './openController'; +import * as userController from './userController'; export default { + matrixAppController, matrixController, loginController, - registerController, + userController, + openController, admin, device, appController, + citrusAppController, }; diff --git a/src/services/matrix/matrixAppController.ts b/src/services/matrix/matrixAppController.ts new file mode 100644 index 0000000..1041578 --- /dev/null +++ b/src/services/matrix/matrixAppController.ts @@ -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/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/matrix/app/normalConfig', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + params: { + ...params, + }, + data: body, + ...(options || {}), + }); +} diff --git a/src/services/matrix/registerController.ts b/src/services/matrix/openController.ts similarity index 54% rename from src/services/matrix/registerController.ts rename to src/services/matrix/openController.ts index abb9254..2a6ca33 100644 --- a/src/services/matrix/registerController.ts +++ b/src/services/matrix/openController.ts @@ -2,6 +2,42 @@ /* eslint-disable */ import { request } from '@umijs/max'; +/** 此处后端没有提供注释 POST /api/citrus/loginByCode */ +export async function loginByCode(body: API.LoginReq, options?: { [key: string]: any }) { + return request('/api/citrus/loginByCode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /api/citrus/loginByPwd */ +export async function loginByPwd(body: API.LoginReq, options?: { [key: string]: any }) { + return request('/api/citrus/loginByPwd', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 POST /api/citrus/loginByToken */ +export async function loginByToken(body: API.LoginReq, options?: { [key: string]: any }) { + return request('/api/citrus/loginByToken', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }); +} + /** 此处后端没有提供注释 GET /api/citrus/register/getApp */ export async function getApp( // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) diff --git a/src/services/matrix/typings.d.ts b/src/services/matrix/typings.d.ts index ec44b21..992ebc6 100644 --- a/src/services/matrix/typings.d.ts +++ b/src/services/matrix/typings.d.ts @@ -31,6 +31,13 @@ declare namespace API { adminId?: number; }; + type AppCashConfig = { + moneyLadder?: number[]; + noAuditMoney?: number; + qqUrl?: string; + dayLimit?: number; + }; + type AppInfo = { name?: string; icon?: string; @@ -39,6 +46,20 @@ declare namespace API { recommend?: AppInfo[]; }; + type applyCashParams = { + money: number; + }; + + type AppNormalConfig = { + moneyLadder?: number[]; + noAuditMoney?: number; + qqUrl?: string; + dayLimit?: number; + maxIncomeEachVideo?: number; + dayRates?: DayRate[]; + defaultRate?: number; + }; + type bindDeviceParams = { deviceId: string; appCode: string; @@ -49,6 +70,12 @@ declare namespace API { date: number; }; + type CashRecord = { + cent?: number; + createTime?: number; + status?: number; + }; + type CurrentUser = { avatarUrl?: string; nickName?: string; @@ -61,6 +88,11 @@ declare namespace API { income?: number; }; + type DayRate = { + day?: number; + rate?: number; + }; + type deleteWhiteListParams = { deviceId: string; }; @@ -74,12 +106,21 @@ declare namespace API { deviceId: string; }; + type getAppDetailParams = { + appCode: string; + }; + type getAppInfoParams = { appId?: string; }; + type getAppNormalConfigParams = { + appCode: string; + }; + type getAppParams = { - inviteCode: string; + inviteCode?: string; + appCode?: string; }; type grantAppParams = { @@ -209,6 +250,16 @@ declare namespace API { channel?: string; hide?: number; secret?: string; + umeng?: string; + aliPay?: string; + wx?: string; + moneyLadder?: string; + noAuditMoney?: number; + qqUrl?: string; + dayLimit?: number; + maxIncomeEachVideo?: number; + dayRates?: string; + defaultRate?: number; }; type MatrixAppBo = { @@ -216,6 +267,11 @@ declare namespace API { code?: string; img?: string; url?: string; + channel?: string; + hide?: number; + secret?: string; + enableCash?: boolean; + config?: AppCashConfig; }; type MatrixMockSchedule = { @@ -271,12 +327,24 @@ declare namespace API { size: number; }; + type RAppCashConfig = { + code?: number; + message?: string; + data?: AppCashConfig; + }; + type RAppInfo = { code?: number; message?: string; data?: AppInfo; }; + type RAppNormalConfig = { + code?: number; + message?: string; + data?: AppNormalConfig; + }; + type RBoolean = { code?: number; message?: string; @@ -302,6 +370,12 @@ declare namespace API { data?: InviteInfo; }; + type RListCashRecord = { + code?: number; + message?: string; + data?: CashRecord[]; + }; + type RListDateIncome = { code?: number; message?: string; @@ -326,10 +400,10 @@ declare namespace API { data?: MatrixAdvRecordSimple[]; }; - type RListMatrixApp = { + type RListMatrixAppBo = { code?: number; message?: string; - data?: MatrixApp[]; + data?: MatrixAppBo[]; }; type RListMatrixMockSchedule = { @@ -392,14 +466,25 @@ declare namespace API { data?: STSInfo; }; + type RUserBo = { + code?: number; + message?: string; + data?: UserBo; + }; + type RVoid = { code?: number; message?: string; data?: Record; }; + type saveNormalConfigParams = { + appCode: string; + }; + type sendCodeParams = { mobile: string; + scene: string; }; type STSInfo = { @@ -421,6 +506,20 @@ declare namespace API { signature: string; }; + type UserBo = { + id?: number; + mobile?: string; + name?: string; + nickname?: string; + avatar?: string; + money?: number; + aliPayAccount?: string; + income?: number; + goldCoin?: number; + inviteCode?: string; + inviteUrl?: string; + }; + type UserInfo = { avatarUrl?: string; nickName?: string; diff --git a/src/services/matrix/userController.ts b/src/services/matrix/userController.ts new file mode 100644 index 0000000..354a2ca --- /dev/null +++ b/src/services/matrix/userController.ts @@ -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/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/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/citrus/user/cashRecords', { + method: 'GET', + ...(options || {}), + }); +} + +/** 此处后端没有提供注释 GET /api/citrus/user/current */ +export async function currentUser1(options?: { [key: string]: any }) { + return request('/api/citrus/user/current', { + method: 'GET', + ...(options || {}), + }); +}