feat: reset web
parent
6e0d9cca5d
commit
12da5f60bd
|
@ -25,7 +25,7 @@
|
||||||
"unocss": "^0.60.4"
|
"unocss": "^0.60.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash": "^4.17.4",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/qs": "^6.9.15",
|
"@types/qs": "^6.9.15",
|
||||||
"@types/react": "^18.0.33",
|
"@types/react": "^18.0.33",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
|
|
|
@ -45,9 +45,9 @@ importers:
|
||||||
specifier: ^0.60.4
|
specifier: ^0.60.4
|
||||||
version: 0.60.4(postcss@8.4.38)(rollup@3.29.4)(vite@4.5.2(@types/node@20.14.1)(less@4.1.3)(lightningcss@1.22.1)(terser@5.31.0))
|
version: 0.60.4(postcss@8.4.38)(rollup@3.29.4)(vite@4.5.2(@types/node@20.14.1)(less@4.1.3)(lightningcss@1.22.1)(terser@5.31.0))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/lodash':
|
'@types/lodash-es':
|
||||||
specifier: ^4.17.4
|
specifier: ^4.17.12
|
||||||
version: 4.17.4
|
version: 4.17.12
|
||||||
'@types/qs':
|
'@types/qs':
|
||||||
specifier: ^6.9.15
|
specifier: ^6.9.15
|
||||||
version: 6.9.15
|
version: 6.9.15
|
||||||
|
@ -1319,6 +1319,9 @@ packages:
|
||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
|
||||||
|
'@types/lodash-es@4.17.12':
|
||||||
|
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||||
|
|
||||||
'@types/lodash@4.17.4':
|
'@types/lodash@4.17.4':
|
||||||
resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==}
|
resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==}
|
||||||
|
|
||||||
|
@ -8068,6 +8071,10 @@ snapshots:
|
||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
|
'@types/lodash-es@4.17.12':
|
||||||
|
dependencies:
|
||||||
|
'@types/lodash': 4.17.4
|
||||||
|
|
||||||
'@types/lodash@4.17.4': {}
|
'@types/lodash@4.17.4': {}
|
||||||
|
|
||||||
'@types/minimist@1.2.5': {}
|
'@types/minimist@1.2.5': {}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { getSupderInfoApi } from '@/services/system/supderLogin';
|
import { getSupderInfoApi } from '@/services/system/supderLogin';
|
||||||
import { history } from '@umijs/max';
|
import { history } from '@umijs/max';
|
||||||
|
import './styles/global.less';
|
||||||
|
import './styles/tailwind.css';
|
||||||
import { routes as appRouters, loopMenuItem, type MenuItem } from './utils/router';
|
import { routes as appRouters, loopMenuItem, type MenuItem } from './utils/router';
|
||||||
|
|
||||||
export function patchClientRoutes({ routes }: any) {
|
export function patchClientRoutes({ routes }: any) {
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
import { addPackageAPI, editPackageAPI } from '@/services/system/package';
|
||||||
|
import { ActionType, ProFormMoney, ProFormRadio, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { App, Form, Modal, Spin } from 'antd';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type PropTypes = {
|
||||||
|
visible: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
tableRef: React.RefObject<EditRow<ActionType>>;
|
||||||
|
editRow: Package.PackageItem | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CreateModel = (props: PropTypes) => {
|
||||||
|
const { message } = App.useApp();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const { visible, editRow, tableRef, onCancel } = props;
|
||||||
|
const [title, setTitle] = useState<string>();
|
||||||
|
|
||||||
|
const handleOnCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddNewPackage = async () => {
|
||||||
|
const values = await form.validateFields();
|
||||||
|
const _values = cloneDeep(values);
|
||||||
|
_values['day'] = parseInt(_values['day']);
|
||||||
|
_values['materialSpace'] = parseInt(_values['materialSpace']);
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const result = !editRow?.id ? await addPackageAPI(_values) : await editPackageAPI(_values);
|
||||||
|
if (result.code === 200) {
|
||||||
|
message.success(`套餐${editRow?.id ? '修改' : '添加'}成功`);
|
||||||
|
handleOnCancel();
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTitle(editRow?.id ? '修改套餐' : '添加套餐');
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.resetFields();
|
||||||
|
if (visible) {
|
||||||
|
if (editRow?.id) {
|
||||||
|
form.setFieldsValue(editRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
destroyOnClose
|
||||||
|
forceRender
|
||||||
|
title={title}
|
||||||
|
width={800}
|
||||||
|
open={visible}
|
||||||
|
afterClose={handleOnCancel}
|
||||||
|
onCancel={handleOnCancel}
|
||||||
|
onOk={handleAddNewPackage}
|
||||||
|
>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
<Form form={form} labelCol={{ span: 5 }}>
|
||||||
|
<ProFormText name="id" hidden></ProFormText>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={''}
|
||||||
|
width="md"
|
||||||
|
name="name"
|
||||||
|
required
|
||||||
|
label="套餐名称"
|
||||||
|
placeholder="请输入套餐名称"
|
||||||
|
rules={[{ required: true, message: '请输入套餐名称' }]}
|
||||||
|
/>
|
||||||
|
<ProFormMoney
|
||||||
|
label="套餐展示金额(元)"
|
||||||
|
name="showMoney"
|
||||||
|
locale="en-US"
|
||||||
|
initialValue={0}
|
||||||
|
min={0}
|
||||||
|
placeholder="请输入套餐展示金额"
|
||||||
|
rules={[{ required: true, message: '请输入套餐展示金额' }]}
|
||||||
|
/>
|
||||||
|
<ProFormMoney
|
||||||
|
label="套餐支付金额(元)"
|
||||||
|
name="payMoney"
|
||||||
|
locale="en-US"
|
||||||
|
initialValue={0}
|
||||||
|
min={0}
|
||||||
|
placeholder="请输入套餐支付金额"
|
||||||
|
rules={[{ required: true, message: '请输入套餐支付金额' }]}
|
||||||
|
/>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={0}
|
||||||
|
width="md"
|
||||||
|
name="day"
|
||||||
|
required
|
||||||
|
label="套餐天数(天)"
|
||||||
|
placeholder="请输入套餐天数"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (rule, value) => {
|
||||||
|
if (!/^[0-9]+$/.test(value)) {
|
||||||
|
return Promise.reject(new Error('请输入套餐天数'));
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<ProFormRadio.Group
|
||||||
|
initialValue={'GB'}
|
||||||
|
name="type"
|
||||||
|
label="存储类型"
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: 'GB',
|
||||||
|
value: 'GB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'MB',
|
||||||
|
value: 'MB',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></ProFormRadio.Group>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={0}
|
||||||
|
width="md"
|
||||||
|
name="materialSpace"
|
||||||
|
required
|
||||||
|
label="套餐存储空间"
|
||||||
|
placeholder="请输入套餐存储空间"
|
||||||
|
/>
|
||||||
|
</Form>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateModel;
|
|
@ -0,0 +1,134 @@
|
||||||
|
import { delPackageAPI, getPackageAPI } from '@/services/system/package';
|
||||||
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
|
import { App, Button, message } from 'antd';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
import CreateModel from './createModule';
|
||||||
|
|
||||||
|
const Page = () => {
|
||||||
|
const { modal } = App.useApp();
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||||
|
const [editRow, setEditRow] = useState<EditRow<EditRow<Package.PackageItem>>>();
|
||||||
|
|
||||||
|
const columns: ProColumns[] = [
|
||||||
|
{
|
||||||
|
title: '套餐名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户展示金额',
|
||||||
|
dataIndex: 'showMoney',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: Package.PackageItem) => record.showMoney + '元',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '实际支付金额',
|
||||||
|
dataIndex: 'payMoney',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: Package.PackageItem) => record.payMoney + '元',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐天数',
|
||||||
|
dataIndex: 'day',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: Package.PackageItem) => record.day + '天',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐容量',
|
||||||
|
dataIndex: 'materialSpace',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: Package.PackageItem) => record.materialSpace + '' + record?.type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'option',
|
||||||
|
valueType: 'option',
|
||||||
|
align: 'center',
|
||||||
|
render: (_: React.ReactNode, record: Package.PackageItem) => (
|
||||||
|
<div className="space-x-4">
|
||||||
|
<Button
|
||||||
|
key={'edit'}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setEditRow(record);
|
||||||
|
setCreateModalVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
修改套餐
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
key={'del'}
|
||||||
|
onClick={() => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该套餐?',
|
||||||
|
async onOk() {
|
||||||
|
const flag = await delPackageAPI(record.id);
|
||||||
|
if (flag) {
|
||||||
|
message.success('删除成功');
|
||||||
|
tableRef.current?.reload();
|
||||||
|
} else {
|
||||||
|
message.error('删除失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
删除套餐
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ProTable
|
||||||
|
actionRef={tableRef}
|
||||||
|
columns={columns}
|
||||||
|
rowKey={'id'}
|
||||||
|
search={false}
|
||||||
|
toolBarRender={() => [
|
||||||
|
<Button
|
||||||
|
key="addSuperAdmin"
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setCreateModalVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
新建套餐
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
request={async () => {
|
||||||
|
const { meta, code, data } = await getPackageAPI();
|
||||||
|
return {
|
||||||
|
data: data ?? [],
|
||||||
|
total: meta.total,
|
||||||
|
success: code === 200,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
></ProTable>
|
||||||
|
|
||||||
|
<CreateModel
|
||||||
|
visible={createModalVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditRow(undefined);
|
||||||
|
setCreateModalVisible(false);
|
||||||
|
}}
|
||||||
|
tableRef={tableRef}
|
||||||
|
editRow={editRow}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Page;
|
|
@ -82,7 +82,6 @@ const Page = () => {
|
||||||
render: (_: React.ReactNode, record: SuperAdmin.SuperAdminItem) => (
|
render: (_: React.ReactNode, record: SuperAdmin.SuperAdminItem) => (
|
||||||
<div className="space-x-4">
|
<div className="space-x-4">
|
||||||
<Button
|
<Button
|
||||||
className="app-btn warning"
|
|
||||||
key={'edit'}
|
key={'edit'}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
import { addUxUserAPI } from '@/services/system/user';
|
||||||
|
import { Reg } from '@/utils/reg';
|
||||||
|
import { ActionType, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { App, Form, Modal, Spin } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type PropTypes = {
|
||||||
|
visible: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
onShowPwd: (email: string, password: string) => void;
|
||||||
|
tableRef: React.RefObject<EditRow<ActionType>>;
|
||||||
|
editRow: EditRow<User.UserItem>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CreateModel = (props: PropTypes) => {
|
||||||
|
const { message } = App.useApp();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const { visible, editRow, tableRef, onCancel, onShowPwd } = props;
|
||||||
|
const [title, setTitle] = useState<string>();
|
||||||
|
|
||||||
|
const handleOnCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddNewUser = async () => {
|
||||||
|
const values = await form.validateFields();
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const dict = 'ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
|
||||||
|
const password = Array.from({ length: 8 }, () => dict[Math.round(dict.length * Math.random())]).join('');
|
||||||
|
const submitData = values;
|
||||||
|
submitData['password'] = password;
|
||||||
|
const result = await addUxUserAPI(submitData);
|
||||||
|
if (result.code === 200) {
|
||||||
|
message.success(`用户添加成功`);
|
||||||
|
handleOnCancel();
|
||||||
|
onShowPwd(values.email, password);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTitle(editRow?.id ? '修改用户' : '添加用户');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.resetFields();
|
||||||
|
if (visible) {
|
||||||
|
if (editRow?.id) {
|
||||||
|
form.setFieldsValue(editRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
destroyOnClose
|
||||||
|
forceRender
|
||||||
|
title={title}
|
||||||
|
width={600}
|
||||||
|
open={visible}
|
||||||
|
afterClose={handleOnCancel}
|
||||||
|
onCancel={handleOnCancel}
|
||||||
|
onOk={handleAddNewUser}
|
||||||
|
>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
<Form form={form} labelCol={{ span: 5 }}>
|
||||||
|
<ProFormText name="id" hidden></ProFormText>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={''}
|
||||||
|
width="md"
|
||||||
|
name="email"
|
||||||
|
required
|
||||||
|
label="邮箱"
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请输入邮箱' },
|
||||||
|
{ pattern: Reg.Email, message: '邮箱格式不正确' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={''}
|
||||||
|
width="md"
|
||||||
|
name="userName"
|
||||||
|
required
|
||||||
|
label="用户名称"
|
||||||
|
placeholder="请输入用户名称"
|
||||||
|
rules={[{ required: true, message: '请输入用户名称' }]}
|
||||||
|
/>
|
||||||
|
{/* <Form.Item label="开通套餐" required>
|
||||||
|
<Space size="middle">
|
||||||
|
{packageOptions.map((item) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={item.id}
|
||||||
|
title={item.name}
|
||||||
|
size="small"
|
||||||
|
className={`cursor-pointer ${choosePackage === item.id ? 'border-[#1677ff] border-2' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setChoosePackage(item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>显示金额:{item.showMoney}</div>
|
||||||
|
<div>付款金额:{item.payMoney}</div>
|
||||||
|
<div>
|
||||||
|
存储空间:{item.materialSpace}
|
||||||
|
{item.type}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
</Form.Item> */}
|
||||||
|
</Form>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateModel;
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { getPackageAPI } from '@/services/system/package';
|
||||||
|
import { openPackageAPI } from '@/services/system/user';
|
||||||
|
import { ActionType } from '@ant-design/pro-components';
|
||||||
|
import { App, Card, Form, Modal, Space, Spin } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type PropTypes = {
|
||||||
|
visible: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
tableRef: React.RefObject<EditRow<ActionType>>;
|
||||||
|
editRow: EditRow<User.UserItem>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OpenPackageModel = (props: PropTypes) => {
|
||||||
|
const { message } = App.useApp();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [packageOptions, setPackage] = useState<Package.PackageItem[]>([]);
|
||||||
|
const [choosePackage, setChoosePackage] = useState<string>();
|
||||||
|
|
||||||
|
const { visible, editRow, tableRef, onCancel } = props;
|
||||||
|
const [title, setTitle] = useState<string>();
|
||||||
|
|
||||||
|
const handleOnCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPackageList = () => {
|
||||||
|
getPackageAPI().then((result) => {
|
||||||
|
setPackage(result.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!choosePackage) {
|
||||||
|
message.warning('请选择一个套餐');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const result = await openPackageAPI({ id: editRow!.id, packageId: choosePackage });
|
||||||
|
if (result.code === 200) {
|
||||||
|
message.success(result.message);
|
||||||
|
handleOnCancel();
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getPackageList();
|
||||||
|
setTitle('开通用户套餐');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (visible) {
|
||||||
|
setChoosePackage(undefined);
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
destroyOnClose
|
||||||
|
forceRender
|
||||||
|
title={title}
|
||||||
|
width={700}
|
||||||
|
open={visible}
|
||||||
|
afterClose={handleOnCancel}
|
||||||
|
onCancel={handleOnCancel}
|
||||||
|
onOk={handleSubmit}
|
||||||
|
>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
<Form form={form} labelCol={{ span: 5 }}>
|
||||||
|
<Form.Item label="开通套餐" required>
|
||||||
|
<Space size="middle">
|
||||||
|
{packageOptions.map((item) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={item.id}
|
||||||
|
title={item.name}
|
||||||
|
size="small"
|
||||||
|
className={`cursor-pointer ${choosePackage === item.id ? 'border-[#1677ff] border-2' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setChoosePackage(item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>显示金额:{item.showMoney}</div>
|
||||||
|
<div>付款金额:{item.payMoney}</div>
|
||||||
|
<div>
|
||||||
|
存储空间:{item.materialSpace}
|
||||||
|
{item.type}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OpenPackageModel;
|
|
@ -0,0 +1,120 @@
|
||||||
|
import { getUserByIdAPI } from '@/services/system/user';
|
||||||
|
import { ActionType } from '@ant-design/pro-components';
|
||||||
|
import { Descriptions, Form, Modal, Spin, Tabs } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type PropTypes = {
|
||||||
|
visible: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
tableRef: React.RefObject<EditRow<ActionType>>;
|
||||||
|
editRow: EditRow<User.UserItem>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserDetailsModal = (props: PropTypes) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [tabType, setTabType] = useState('details');
|
||||||
|
const [userInfo, setUserInfo] = useState<User.UserItem>();
|
||||||
|
const [projectCount, setProjectCount] = useState<User.UserItemByInfo['projectCount']>(0);
|
||||||
|
const [materialsCount, setMaterialsCount] = useState<User.UserItemByInfo['materialsCount']>(0);
|
||||||
|
const [materialsGroup, setMaterialsGroup] = useState<User.UserItemByInfo['materialsGroup']>([]);
|
||||||
|
|
||||||
|
const { visible, editRow, onCancel } = props;
|
||||||
|
const [title, setTitle] = useState<string>();
|
||||||
|
|
||||||
|
const handleOnCancel = () => {
|
||||||
|
form.resetFields();
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGetUserInfo = () => {
|
||||||
|
setLoading(true);
|
||||||
|
getUserByIdAPI(editRow!.id)
|
||||||
|
.then((result) => {
|
||||||
|
if (result.code === 200) {
|
||||||
|
setUserInfo(result.data.userInfo);
|
||||||
|
setProjectCount(result.data.projectCount);
|
||||||
|
setMaterialsCount(result.data.materialsCount);
|
||||||
|
setMaterialsGroup(result.data.materialsGroup);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTitle('用户详情');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (visible) {
|
||||||
|
handleGetUserInfo();
|
||||||
|
}
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
|
const RenderUserDetails = () => {
|
||||||
|
if (!userInfo) return <></>;
|
||||||
|
return (
|
||||||
|
<Descriptions size="small" column={{ xs: 1, sm: 2, md: 3, lg: 3 }} bordered>
|
||||||
|
<Descriptions.Item label="邮箱">{userInfo.email}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="用户名称">{userInfo.userName}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="套餐信息">
|
||||||
|
{userInfo?.package?.name +
|
||||||
|
'/' +
|
||||||
|
userInfo?.package?.showMoney +
|
||||||
|
'元' +
|
||||||
|
'/' +
|
||||||
|
userInfo?.package?.materialSpace +
|
||||||
|
userInfo?.package?.type}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="总存储空间">
|
||||||
|
{userInfo?.increasedStorageInKb && (userInfo.increasedStorageInKb / 1024).toFixed(2) + 'MB'}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="已使用空间">
|
||||||
|
{userInfo?.UserProfile && (userInfo.UserProfile.storageUsedInKb / 1024).toFixed(2) + 'MB'}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="剩余存储空间">
|
||||||
|
{((userInfo.increasedStorageInKb! - userInfo!.UserProfile!.storageUsedInKb) / 1024).toFixed(2) + 'MB'}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="项目数量">{projectCount}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="素材数量">{materialsCount}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="素材分组">
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
{materialsGroup.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<span key={index} className="text-xs">
|
||||||
|
{item.materialType}({item._count})
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
destroyOnClose
|
||||||
|
forceRender
|
||||||
|
title={title}
|
||||||
|
width={1200}
|
||||||
|
open={visible}
|
||||||
|
afterClose={handleOnCancel}
|
||||||
|
onCancel={handleOnCancel}
|
||||||
|
>
|
||||||
|
<Spin spinning={loading}>
|
||||||
|
<Tabs activeKey={tabType} onChange={(activeKey) => setTabType(activeKey)}>
|
||||||
|
<Tabs.TabPane key={'details'} tab={'用户详情'}>
|
||||||
|
<RenderUserDetails />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane key={'handleLogs'} tab={'操作记录'}></Tabs.TabPane>
|
||||||
|
<Tabs.TabPane key={'orderInfo'} tab={'订单信息'}></Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserDetailsModal;
|
|
@ -1,5 +1,278 @@
|
||||||
const UserPage = () => {
|
import { changeStatusAPI, delUxUserAPI, getUserListAPI } from '@/services/system/user';
|
||||||
return <>1231</>;
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
|
import { App, Button, Space, TableProps, message } from 'antd';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
import CreateModel from './CreateModule';
|
||||||
|
import OpenPackageModel from './OpenPackage';
|
||||||
|
import UserDetailsModal from './UserDetails';
|
||||||
|
|
||||||
|
const Page = () => {
|
||||||
|
const { modal } = App.useApp();
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||||
|
const [openPackageVisible, setOpenPackageVisible] = useState<boolean>(false);
|
||||||
|
const [userDetailsVisible, setUserDetailsVisible] = useState<boolean>(false);
|
||||||
|
const [editRow, setEditRow] = useState<EditRow<User.UserItem>>();
|
||||||
|
const [tableParams, setTableParams] = useState<TableParams>({
|
||||||
|
pagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleTableChange: TableProps['onChange'] = (pagination, filters, sorter) => {
|
||||||
|
setTableParams({
|
||||||
|
pagination,
|
||||||
|
filters,
|
||||||
|
...sorter,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeUserStatus = (record: User.UserItem) => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: `确定要将用户【${record.email}】${record.enabled ? '禁用' : '启用'}`,
|
||||||
|
async onOk() {
|
||||||
|
const result = await changeStatusAPI({ id: record.id, enabled: !record.enabled });
|
||||||
|
if (result.code === 200) {
|
||||||
|
message.success(result.message);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProColumns[] = [
|
||||||
|
{
|
||||||
|
title: '邮箱',
|
||||||
|
dataIndex: 'email',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_, record: User.UserItem) => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => {
|
||||||
|
setEditRow(record);
|
||||||
|
setUserDetailsVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{record.email}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户名称',
|
||||||
|
dataIndex: 'userName',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '当前套餐',
|
||||||
|
dataIndex: 'packageId',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: User.UserItem) => {
|
||||||
|
if (!record.package) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
record?.package?.name +
|
||||||
|
'/' +
|
||||||
|
record.package.showMoney +
|
||||||
|
'元' +
|
||||||
|
'/' +
|
||||||
|
record?.package?.materialSpace +
|
||||||
|
record?.package?.type
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户来源',
|
||||||
|
dataIndex: 'userSource',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_, record: User.UserItem) => {
|
||||||
|
// 用户来源 1. ux 注册 2. 后台创建
|
||||||
|
if (record.userSource === 1) {
|
||||||
|
return 'ux 注册';
|
||||||
|
} else if (record.userSource === 2) {
|
||||||
|
return '管理员创建';
|
||||||
|
}
|
||||||
|
return record.userSource;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'enabled',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_, record: User.UserItem) => {
|
||||||
|
if (record.enabled === true) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center space-x-2 justify-center">
|
||||||
|
<span className="w-[10px] h-[10px] rounded-full bg-green"></span>
|
||||||
|
<span>启用</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="flex items-center space-x-2 justify-center">
|
||||||
|
<span className="w-[10px] h-[10px] rounded-full bg-gray"></span>
|
||||||
|
<span>禁用</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '账户创建时间',
|
||||||
|
dataIndex: 'createdDateTime',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '最后登录时间',
|
||||||
|
dataIndex: 'lastLoginTime',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'option',
|
||||||
|
valueType: 'option',
|
||||||
|
align: 'center',
|
||||||
|
render: (_: React.ReactNode, record: User.UserItem) => (
|
||||||
|
<div className="space-x-4">
|
||||||
|
{!record.packageId && (
|
||||||
|
<Button
|
||||||
|
key={'openPackage'}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setEditRow(record);
|
||||||
|
setOpenPackageVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
开通套餐
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
className="app-btn warning"
|
||||||
|
key={'changeStatus'}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
handleChangeUserStatus(record);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{record.enabled ? '禁用' : '启用'}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
key={'delUser'}
|
||||||
|
onClick={() => {
|
||||||
|
modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除该用户?',
|
||||||
|
async onOk() {
|
||||||
|
const flag = await delUxUserAPI(record.id);
|
||||||
|
if (flag.code === 200) {
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
删除用户
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ProTable
|
||||||
|
actionRef={tableRef}
|
||||||
|
columns={columns}
|
||||||
|
rowKey={'id'}
|
||||||
|
pagination={tableParams.pagination}
|
||||||
|
onChange={handleTableChange}
|
||||||
|
search={{
|
||||||
|
labelWidth: 140,
|
||||||
|
span: { xs: 24, sm: 24, md: 12, lg: 12, xl: 6, xxl: 6 },
|
||||||
|
}}
|
||||||
|
toolBarRender={() => [
|
||||||
|
<Button
|
||||||
|
key="addUxAdmin"
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setCreateModalVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
新建用户
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
request={async (params) => {
|
||||||
|
const { current, pageSize } = params;
|
||||||
|
const _params = { current, pageSize };
|
||||||
|
const { meta, code, data } = await getUserListAPI(_params);
|
||||||
|
return {
|
||||||
|
data: data ?? [],
|
||||||
|
total: meta.total,
|
||||||
|
success: code === 200,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
></ProTable>
|
||||||
|
|
||||||
|
<CreateModel
|
||||||
|
visible={createModalVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditRow(undefined);
|
||||||
|
setCreateModalVisible(false);
|
||||||
|
}}
|
||||||
|
onShowPwd={(email, password) => {
|
||||||
|
modal.info({
|
||||||
|
title: '账号创建成功',
|
||||||
|
cancelButtonProps: {
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Space direction="vertical" size="middle">
|
||||||
|
<div>登录账号:{email}</div>
|
||||||
|
<div>登录密码:{password}</div>
|
||||||
|
</Space>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
tableRef={tableRef}
|
||||||
|
editRow={editRow}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<OpenPackageModel
|
||||||
|
visible={openPackageVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditRow(undefined);
|
||||||
|
setOpenPackageVisible(false);
|
||||||
|
}}
|
||||||
|
tableRef={tableRef}
|
||||||
|
editRow={editRow}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UserDetailsModal
|
||||||
|
visible={userDetailsVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditRow(undefined);
|
||||||
|
setUserDetailsVisible(false);
|
||||||
|
}}
|
||||||
|
tableRef={tableRef}
|
||||||
|
editRow={editRow}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UserPage;
|
export default Page;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
export const getPackageAPI = (): Promise<API.ResponstList<Package.PackageItem[]>> => {
|
||||||
|
return request.get(`/system/package`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addPackageAPI = (data: Record<string, any>): Promise<API.ResponstBody> => {
|
||||||
|
return request.post(`/system/package`, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editPackageAPI = (data: Record<string, any>): Promise<API.ResponstBody> => {
|
||||||
|
return request.put(`/system/package`, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const delPackageAPI = (id: string): Promise<API.ResponstBody> => {
|
||||||
|
return request.delete(`/system/package/${id}`);
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
declare namespace Package {
|
||||||
|
type PackageItem = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
showMoney?: number;
|
||||||
|
payMoney?: string;
|
||||||
|
day?: number;
|
||||||
|
type?: string;
|
||||||
|
materialSpace?: number;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
import qs from 'qs';
|
||||||
|
|
||||||
|
export const getUserListAPI = (params: Record<string, any>): Promise<API.ResponstList<User.UserItem[]>> => {
|
||||||
|
return request.get(`/system/user?` + qs.stringify(params));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUserByIdAPI = (id: string): Promise<API.ResponstList<User.UserItemByInfo>> => {
|
||||||
|
return request.get(`/system/user/getUserById/` + id);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addUxUserAPI = (params: User.UserItem): Promise<API.ResponstBody> => {
|
||||||
|
return request.post('/system/user', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const changeStatusAPI = (params: User.UserItem): Promise<API.ResponstBody> => {
|
||||||
|
return request.put('/system/user/changeStatus', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const delUxUserAPI = (id: string): Promise<API.ResponstBody> => {
|
||||||
|
return request.delete('/system/user/' + id);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const openPackageAPI = (params: User.UserItem): Promise<API.ResponstBody> => {
|
||||||
|
return request.post('/system/user/openPackage', params);
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
declare namespace User {
|
||||||
|
type UserProfile = {
|
||||||
|
id: string;
|
||||||
|
storageUsedInKb: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserItem = {
|
||||||
|
id: string;
|
||||||
|
userName?: string;
|
||||||
|
email?: string;
|
||||||
|
password?: string;
|
||||||
|
passwordHash?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
|
||||||
|
packageId?: string;
|
||||||
|
|
||||||
|
expired?: string;
|
||||||
|
// 用户来源 1. ux 注册 2. 后台创建
|
||||||
|
userSource?: number;
|
||||||
|
// 用户总空间
|
||||||
|
increasedStorageInKb?: number;
|
||||||
|
|
||||||
|
createdDateTime?: string;
|
||||||
|
lastUpdateDateTime?: string;
|
||||||
|
lastLoginTime?: string;
|
||||||
|
packageId?: string;
|
||||||
|
package?: Package.PackageItem;
|
||||||
|
|
||||||
|
UserProfile?: UserProfile;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UserItemByInfo = {
|
||||||
|
userInfo: UserItem;
|
||||||
|
materialsCount: number;
|
||||||
|
projectCount: number;
|
||||||
|
projectCount: number;
|
||||||
|
materialsGroup: { _count: number; materialType: string }[];
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
@import url('var.less');
|
||||||
|
|
||||||
|
.app-btn {
|
||||||
|
&.warning {
|
||||||
|
background-color: @btn-warning;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: @btn-warning__hover !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
@import 'tailwindcss/base';
|
||||||
|
@import 'tailwindcss/components';
|
||||||
|
@import 'tailwindcss/utilities';
|
|
@ -0,0 +1,2 @@
|
||||||
|
@btn-warning: #f5b753;
|
||||||
|
@btn-warning__hover: #f5b753;
|
|
@ -21,6 +21,11 @@ export const routes: any[] = [
|
||||||
name: '系统管理',
|
name: '系统管理',
|
||||||
path: '/system',
|
path: '/system',
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
name: '套餐设置',
|
||||||
|
path: '/system/package',
|
||||||
|
component: '/System/Package',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '管理员设置',
|
name: '管理员设置',
|
||||||
path: '/system/superAdmin',
|
path: '/system/superAdmin',
|
||||||
|
|
|
@ -3,6 +3,13 @@ import '@umijs/max/typings';
|
||||||
declare global {
|
declare global {
|
||||||
declare type EditRow<T> = T | undefined;
|
declare type EditRow<T> = T | undefined;
|
||||||
|
|
||||||
|
interface TableParams {
|
||||||
|
pagination?: TablePaginationConfig;
|
||||||
|
sortField?: string;
|
||||||
|
sortOrder?: string;
|
||||||
|
filters?: Parameters<GetProp<TableProps, 'onChange'>>[1];
|
||||||
|
}
|
||||||
|
|
||||||
const API_URL: string;
|
const API_URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue