feat: success reset 60%
parent
12da5f60bd
commit
50237f3f75
|
@ -19,6 +19,7 @@
|
||||||
"antd": "^5.18.0",
|
"antd": "^5.18.0",
|
||||||
"antd-style": "^3.6.2",
|
"antd-style": "^3.6.2",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
|
"dayjs": "^1.11.11",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"qs": "^6.12.1",
|
"qs": "^6.12.1",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
|
|
|
@ -32,6 +32,9 @@ importers:
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.7.2
|
specifier: ^1.7.2
|
||||||
version: 1.7.2
|
version: 1.7.2
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.11
|
||||||
|
version: 1.11.11
|
||||||
lodash-es:
|
lodash-es:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { userLogoutAPI } from '@/services/system/supderAdmin';
|
||||||
|
import { history } from '@umijs/max';
|
||||||
|
import { Dropdown } from 'antd';
|
||||||
|
import { JSXElementConstructor, ReactElement, ReactNode, ReactPortal } from 'react';
|
||||||
|
|
||||||
|
enum DrowType {
|
||||||
|
LOGOUT = 'LOGOUT',
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
userLogoutAPI().then(({ code }) => {
|
||||||
|
if (code === 200) {
|
||||||
|
history.replace('/login');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserDropDownRender = (props: {
|
||||||
|
dom:
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| ReactElement<any, string | JSXElementConstructor<any>>
|
||||||
|
| Iterable<ReactNode>
|
||||||
|
| ReactPortal
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
|
}) => {
|
||||||
|
const handleType = {
|
||||||
|
[DrowType.LOGOUT]: handleLogout,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
key: DrowType.LOGOUT,
|
||||||
|
label: '退出登录',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onClick: ({ key }) => {
|
||||||
|
handleType[key as DrowType]();
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.dom}
|
||||||
|
</Dropdown>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { UserDropDownRender };
|
|
@ -1,12 +1,14 @@
|
||||||
import { PageContainer, ProLayout } from '@ant-design/pro-components';
|
import { PageContainer, ProLayout } from '@ant-design/pro-components';
|
||||||
import { Link, Outlet, useAppData, useRouteProps } from '@umijs/max';
|
import { Link, Outlet, useAppData, useModel, useRouteProps } from '@umijs/max';
|
||||||
import { App, ConfigProvider } from 'antd';
|
import { App, ConfigProvider } from 'antd';
|
||||||
import zh_CN from 'antd/locale/zh_CN';
|
import zh_CN from 'antd/locale/zh_CN';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { UserDropDownRender } from './UserDropdown';
|
||||||
|
|
||||||
export const BasicLayout: React.FC = () => {
|
export const BasicLayout: React.FC = () => {
|
||||||
const { clientRoutes } = useAppData();
|
const { clientRoutes } = useAppData();
|
||||||
const { useContainer } = useRouteProps();
|
const { useContainer } = useRouteProps();
|
||||||
|
const { initialState } = useModel('@@initialState');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigProvider locale={zh_CN}>
|
<ConfigProvider locale={zh_CN}>
|
||||||
|
@ -16,9 +18,9 @@ export const BasicLayout: React.FC = () => {
|
||||||
logo={null}
|
logo={null}
|
||||||
layout="mix"
|
layout="mix"
|
||||||
avatarProps={{
|
avatarProps={{
|
||||||
src: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
|
|
||||||
size: 'small',
|
size: 'small',
|
||||||
title: 'xxx',
|
title: initialState?.userName,
|
||||||
|
render: (props, dom) => <UserDropDownRender dom={dom}></UserDropDownRender>,
|
||||||
}}
|
}}
|
||||||
route={clientRoutes.find((e) => e.path === '/')}
|
route={clientRoutes.find((e) => e.path === '/')}
|
||||||
contentStyle={{
|
contentStyle={{
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { userDilatationAPI } from '@/services/system/user';
|
||||||
|
import { ActionType, ProFormDependency, ProFormRadio, ProFormText } from '@ant-design/pro-components';
|
||||||
|
import { App, Form, Modal, Spin } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type PropTypes = {
|
||||||
|
visible: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
tableRef: React.RefObject<EditRow<ActionType>>;
|
||||||
|
editRow: EditRow<User.UserItem>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DilatationModel = (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 handleSubmit = async () => {
|
||||||
|
const values = await form.validateFields();
|
||||||
|
if (!/^[0-9]+$/.test(values.size)) {
|
||||||
|
message.warning('请输入数字');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parseInt(values.size) <= 0) {
|
||||||
|
message.warning('扩容大小需大于0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const result = await userDilatationAPI({ userId: editRow!.id, type: values.type, addSize: values.size });
|
||||||
|
if (result.code === 200) {
|
||||||
|
message.success(result.message);
|
||||||
|
handleOnCancel();
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTitle('用户扩容');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
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 }}>
|
||||||
|
<ProFormRadio.Group
|
||||||
|
width="md"
|
||||||
|
required
|
||||||
|
initialValue={'MB'}
|
||||||
|
name="type"
|
||||||
|
label="类型"
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: 'MB',
|
||||||
|
value: 'MB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'GB',
|
||||||
|
value: 'GB',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></ProFormRadio.Group>
|
||||||
|
<ProFormText
|
||||||
|
initialValue={0}
|
||||||
|
width="md"
|
||||||
|
name="size"
|
||||||
|
required
|
||||||
|
label="容量"
|
||||||
|
placeholder="请输入扩容容量"
|
||||||
|
rules={[{ required: true, message: '请输入扩容容量' }]}
|
||||||
|
/>
|
||||||
|
<ProFormDependency name={['type', 'size']}>
|
||||||
|
{({ type, size }) => {
|
||||||
|
return (
|
||||||
|
<div className="text-red text-center text-xl">
|
||||||
|
给{editRow?.email}账号,扩容{size} {type}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</ProFormDependency>
|
||||||
|
</Form>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DilatationModel;
|
|
@ -1,6 +1,8 @@
|
||||||
import { getUserByIdAPI } from '@/services/system/user';
|
import { getUserByIdAPI } from '@/services/system/user';
|
||||||
|
import { UxOrderStatus, UxOrderStatusTag } from '@/utils/const';
|
||||||
|
import { formatDateTime } from '@/utils/format';
|
||||||
import { ActionType } from '@ant-design/pro-components';
|
import { ActionType } from '@ant-design/pro-components';
|
||||||
import { Descriptions, Form, Modal, Spin, Tabs } from 'antd';
|
import { Descriptions, Empty, Form, Modal, Spin, Table, Tabs } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
type PropTypes = {
|
type PropTypes = {
|
||||||
|
@ -17,6 +19,7 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
const [userInfo, setUserInfo] = useState<User.UserItem>();
|
const [userInfo, setUserInfo] = useState<User.UserItem>();
|
||||||
const [projectCount, setProjectCount] = useState<User.UserItemByInfo['projectCount']>(0);
|
const [projectCount, setProjectCount] = useState<User.UserItemByInfo['projectCount']>(0);
|
||||||
const [materialsCount, setMaterialsCount] = useState<User.UserItemByInfo['materialsCount']>(0);
|
const [materialsCount, setMaterialsCount] = useState<User.UserItemByInfo['materialsCount']>(0);
|
||||||
|
const [dilatationLogs, setDilatationLogs] = useState<User.UserItemByInfo['dilatationLogs']>([]);
|
||||||
const [materialsGroup, setMaterialsGroup] = useState<User.UserItemByInfo['materialsGroup']>([]);
|
const [materialsGroup, setMaterialsGroup] = useState<User.UserItemByInfo['materialsGroup']>([]);
|
||||||
|
|
||||||
const { visible, editRow, onCancel } = props;
|
const { visible, editRow, onCancel } = props;
|
||||||
|
@ -34,6 +37,7 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
if (result.code === 200) {
|
if (result.code === 200) {
|
||||||
setUserInfo(result.data.userInfo);
|
setUserInfo(result.data.userInfo);
|
||||||
setProjectCount(result.data.projectCount);
|
setProjectCount(result.data.projectCount);
|
||||||
|
setDilatationLogs(result.data.dilatationLogs);
|
||||||
setMaterialsCount(result.data.materialsCount);
|
setMaterialsCount(result.data.materialsCount);
|
||||||
setMaterialsGroup(result.data.materialsGroup);
|
setMaterialsGroup(result.data.materialsGroup);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,21 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
}
|
}
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
|
const RenderPackage = ({ userInfo }: { userInfo: User.UserItem }) => {
|
||||||
|
if (userInfo.package) {
|
||||||
|
return (
|
||||||
|
userInfo?.package?.name +
|
||||||
|
'/' +
|
||||||
|
userInfo?.package?.showMoney +
|
||||||
|
'元' +
|
||||||
|
'/' +
|
||||||
|
userInfo?.package?.materialSpace +
|
||||||
|
userInfo?.package?.type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return '-';
|
||||||
|
};
|
||||||
|
|
||||||
const RenderUserDetails = () => {
|
const RenderUserDetails = () => {
|
||||||
if (!userInfo) return <></>;
|
if (!userInfo) return <></>;
|
||||||
return (
|
return (
|
||||||
|
@ -60,22 +79,16 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
<Descriptions.Item label="邮箱">{userInfo.email}</Descriptions.Item>
|
<Descriptions.Item label="邮箱">{userInfo.email}</Descriptions.Item>
|
||||||
<Descriptions.Item label="用户名称">{userInfo.userName}</Descriptions.Item>
|
<Descriptions.Item label="用户名称">{userInfo.userName}</Descriptions.Item>
|
||||||
<Descriptions.Item label="套餐信息">
|
<Descriptions.Item label="套餐信息">
|
||||||
{userInfo?.package?.name +
|
<RenderPackage userInfo={userInfo} />
|
||||||
'/' +
|
|
||||||
userInfo?.package?.showMoney +
|
|
||||||
'元' +
|
|
||||||
'/' +
|
|
||||||
userInfo?.package?.materialSpace +
|
|
||||||
userInfo?.package?.type}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="总存储空间">
|
<Descriptions.Item label="总存储空间">
|
||||||
{userInfo?.increasedStorageInKb && (userInfo.increasedStorageInKb / 1024).toFixed(2) + 'MB'}
|
{userInfo?.increasedStorageInKb && (userInfo.increasedStorageInKb / 1024).toFixed(2)}MB
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="已使用空间">
|
<Descriptions.Item label="已使用空间">
|
||||||
{userInfo?.UserProfile && (userInfo.UserProfile.storageUsedInKb / 1024).toFixed(2) + 'MB'}
|
{userInfo?.UserProfile && ((userInfo?.UserProfile?.storageUsedInKb ?? 0) / 1024).toFixed(2)}MB
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="剩余存储空间">
|
<Descriptions.Item label="剩余存储空间">
|
||||||
{((userInfo.increasedStorageInKb! - userInfo!.UserProfile!.storageUsedInKb) / 1024).toFixed(2) + 'MB'}
|
{((userInfo.increasedStorageInKb! - (userInfo?.UserProfile?.storageUsedInKb ?? 0)) / 1024).toFixed(2)}MB
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label="项目数量">{projectCount}</Descriptions.Item>
|
<Descriptions.Item label="项目数量">{projectCount}</Descriptions.Item>
|
||||||
<Descriptions.Item label="素材数量">{materialsCount}</Descriptions.Item>
|
<Descriptions.Item label="素材数量">{materialsCount}</Descriptions.Item>
|
||||||
|
@ -94,6 +107,114 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const RenderUserOrders = () => {
|
||||||
|
if (userInfo && userInfo.Order!.length === 0) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Empty />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
dataSource={userInfo!.Order}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
title: '订单号',
|
||||||
|
dataIndex: 'orderNo',
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record: Order.OrderItem) => {
|
||||||
|
if (record.isApply === true) {
|
||||||
|
return record.orderNo + '(试用)';
|
||||||
|
}
|
||||||
|
return record.orderNo;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第三方订单号',
|
||||||
|
dataIndex: 'platformOrderStatus',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '支付类型',
|
||||||
|
dataIndex: 'payType',
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record: Order.OrderItem) => {
|
||||||
|
// 支付类型 1. 微信 2. 支付宝 3. paypal -1: 后台创建
|
||||||
|
if (record.payType === 1) {
|
||||||
|
return '微信';
|
||||||
|
} else if (record.payType === 2) {
|
||||||
|
return '支付宝';
|
||||||
|
} else if (record.payType === 3) {
|
||||||
|
return 'paypal';
|
||||||
|
}
|
||||||
|
return '后台创建';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '套餐',
|
||||||
|
dataIndex: 'goodsName',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单状态',
|
||||||
|
dataIndex: 'orderStatus',
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record: Order.OrderItem) => {
|
||||||
|
const color = Reflect.get(UxOrderStatusTag, record.orderStatus);
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-center">
|
||||||
|
<div className="w-[10px] h-[10px] mr-2" style={{ background: color }}></div>
|
||||||
|
{Reflect.get(UxOrderStatus, record.orderStatus)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '订单创建时间',
|
||||||
|
dataIndex: 'createdDateTime',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderDilatationLogs = () => {
|
||||||
|
if (dilatationLogs.length === 0) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Empty />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
dataSource={dilatationLogs}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
title: '扩容大小',
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record: User.UserItemByInfo['dilatationLogs'][0]) => {
|
||||||
|
return record.size + record.type;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '扩容时间',
|
||||||
|
dataIndex: 'createDate',
|
||||||
|
align: 'center',
|
||||||
|
render: (_, record: User.UserItemByInfo['dilatationLogs'][0]) => formatDateTime(record.createDate),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'desc',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></Table>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
|
@ -109,8 +230,12 @@ const UserDetailsModal = (props: PropTypes) => {
|
||||||
<Tabs.TabPane key={'details'} tab={'用户详情'}>
|
<Tabs.TabPane key={'details'} tab={'用户详情'}>
|
||||||
<RenderUserDetails />
|
<RenderUserDetails />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane key={'handleLogs'} tab={'操作记录'}></Tabs.TabPane>
|
<Tabs.TabPane key={'handleLogs'} tab={'扩容记录'}>
|
||||||
<Tabs.TabPane key={'orderInfo'} tab={'订单信息'}></Tabs.TabPane>
|
<RenderDilatationLogs />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane key={'orderInfo'} tab={'订单信息'}>
|
||||||
|
<RenderUserOrders />
|
||||||
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Spin>
|
</Spin>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { changeStatusAPI, delUxUserAPI, getUserListAPI } from '@/services/system/user';
|
import { changeStatusAPI, delUxUserAPI, getUserListAPI } from '@/services/system/user';
|
||||||
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
import { App, Button, Space, TableProps, message } from 'antd';
|
import { App, Button, Radio, Space, TableProps, message } from 'antd';
|
||||||
|
|
||||||
|
import { formatDateTime } from '@/utils/format';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import CreateModel from './CreateModule';
|
import CreateModel from './CreateModule';
|
||||||
|
import DilatationModel from './Dilatation';
|
||||||
import OpenPackageModel from './OpenPackage';
|
import OpenPackageModel from './OpenPackage';
|
||||||
import UserDetailsModal from './UserDetails';
|
import UserDetailsModal from './UserDetails';
|
||||||
|
|
||||||
|
@ -13,6 +16,9 @@ const Page = () => {
|
||||||
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
|
||||||
const [openPackageVisible, setOpenPackageVisible] = useState<boolean>(false);
|
const [openPackageVisible, setOpenPackageVisible] = useState<boolean>(false);
|
||||||
const [userDetailsVisible, setUserDetailsVisible] = useState<boolean>(false);
|
const [userDetailsVisible, setUserDetailsVisible] = useState<boolean>(false);
|
||||||
|
const [kuoRongVisible, setKuoRongVisible] = useState<boolean>(false);
|
||||||
|
const [showType, setShowType] = useState<string>('MB');
|
||||||
|
const [showTypeValue, setShowTypeValue] = useState<number>(1024);
|
||||||
const [editRow, setEditRow] = useState<EditRow<User.UserItem>>();
|
const [editRow, setEditRow] = useState<EditRow<User.UserItem>>();
|
||||||
const [tableParams, setTableParams] = useState<TableParams>({
|
const [tableParams, setTableParams] = useState<TableParams>({
|
||||||
pagination: {
|
pagination: {
|
||||||
|
@ -43,6 +49,11 @@ const Page = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handledDilatation = (record: User.UserItem) => {
|
||||||
|
setEditRow(record);
|
||||||
|
setKuoRongVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
const columns: ProColumns[] = [
|
const columns: ProColumns[] = [
|
||||||
{
|
{
|
||||||
title: '邮箱',
|
title: '邮箱',
|
||||||
|
@ -89,6 +100,45 @@ const Page = () => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '剩余容量',
|
||||||
|
dataIndex: 'packageId',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: User.UserItem) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{((record.increasedStorageInKb! - (record?.UserProfile?.storageUsedInKb ?? 0)) / showTypeValue).toFixed(2) +
|
||||||
|
showType}
|
||||||
|
<Button type="link" onClick={() => handledDilatation(record)}>
|
||||||
|
扩容
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
filterDropdown: () => {
|
||||||
|
return (
|
||||||
|
<div className="p-2">
|
||||||
|
显示类型:
|
||||||
|
<Radio.Group
|
||||||
|
onChange={(e) => {
|
||||||
|
const type = e.target.value;
|
||||||
|
setShowType(type);
|
||||||
|
if (type === 'GB') {
|
||||||
|
setShowTypeValue(Math.pow(1024, 2));
|
||||||
|
} else {
|
||||||
|
setShowTypeValue(1024);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={showType}
|
||||||
|
>
|
||||||
|
<Radio value={'MB'}>MB</Radio>
|
||||||
|
<Radio value={'GB'}>GB</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '用户来源',
|
title: '用户来源',
|
||||||
dataIndex: 'userSource',
|
dataIndex: 'userSource',
|
||||||
|
@ -126,17 +176,27 @@ const Page = () => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '套餐过期时间',
|
||||||
|
dataIndex: 'expired',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: User.UserItem) => (!record.expired ? '-' : formatDateTime(record.expired)),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '账户创建时间',
|
title: '账户创建时间',
|
||||||
dataIndex: 'createdDateTime',
|
dataIndex: 'createdDateTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: User.UserItem) =>
|
||||||
|
!record.createdDateTime ? '-' : formatDateTime(record.createdDateTime),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最后登录时间',
|
title: '最后登录时间',
|
||||||
dataIndex: 'lastLoginTime',
|
dataIndex: 'lastLoginTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
|
renderText: (_, record: User.UserItem) => (!record.lastLoginTime ? '-' : formatDateTime(record.lastLoginTime)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -271,6 +331,16 @@ const Page = () => {
|
||||||
tableRef={tableRef}
|
tableRef={tableRef}
|
||||||
editRow={editRow}
|
editRow={editRow}
|
||||||
/>
|
/>
|
||||||
|
{/* 扩容 */}
|
||||||
|
<DilatationModel
|
||||||
|
visible={kuoRongVisible}
|
||||||
|
onCancel={() => {
|
||||||
|
setEditRow(undefined);
|
||||||
|
setKuoRongVisible(false);
|
||||||
|
}}
|
||||||
|
tableRef={tableRef}
|
||||||
|
editRow={editRow}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
declare namespace Order {
|
||||||
|
type OrderItem = {
|
||||||
|
id?: string;
|
||||||
|
userEmail: string;
|
||||||
|
userId: string;
|
||||||
|
userName?: string;
|
||||||
|
user?: User.UserItem;
|
||||||
|
payType: number;
|
||||||
|
payTypeStr: string;
|
||||||
|
orderNo: string;
|
||||||
|
packageId: string;
|
||||||
|
package?: Package.PackageItem;
|
||||||
|
packageJson?: string;
|
||||||
|
orderStatus: number;
|
||||||
|
platformOrderStatus?: string;
|
||||||
|
platformNo?: string;
|
||||||
|
goodsName: string;
|
||||||
|
price: number;
|
||||||
|
quantity?: number;
|
||||||
|
payCode?: string;
|
||||||
|
payCodeExpired?: string;
|
||||||
|
platformNotifyTime?: string;
|
||||||
|
orderType: number;
|
||||||
|
createSource: number;
|
||||||
|
createSouceBy?: string;
|
||||||
|
createdDateTime: string;
|
||||||
|
lastUpdateDateTime?: string;
|
||||||
|
comment?: string;
|
||||||
|
isApply: boolean;
|
||||||
|
};
|
||||||
|
}
|
|
@ -19,3 +19,7 @@ export const editSupderAdminAPI = (data: SuperAdmin.SuperAdminItem): Promise<API
|
||||||
export const delSuperAdminAPI = (id: string): Promise<API.ResponstBody> => {
|
export const delSuperAdminAPI = (id: string): Promise<API.ResponstBody> => {
|
||||||
return request.delete(`/system/superAdmin/${id}`);
|
return request.delete(`/system/superAdmin/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const userLogoutAPI = (): Promise<API.ResponstBody> => {
|
||||||
|
return request.post(`/system/superAdmin/logout`);
|
||||||
|
};
|
||||||
|
|
|
@ -24,3 +24,11 @@ export const delUxUserAPI = (id: string): Promise<API.ResponstBody> => {
|
||||||
export const openPackageAPI = (params: User.UserItem): Promise<API.ResponstBody> => {
|
export const openPackageAPI = (params: User.UserItem): Promise<API.ResponstBody> => {
|
||||||
return request.post('/system/user/openPackage', params);
|
return request.post('/system/user/openPackage', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const userDilatationAPI = (params: {
|
||||||
|
userId: string;
|
||||||
|
addSize: number;
|
||||||
|
type: string;
|
||||||
|
}): Promise<API.ResponstBody> => {
|
||||||
|
return request.post('/system/user/dilatation', params);
|
||||||
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@ declare namespace User {
|
||||||
package?: Package.PackageItem;
|
package?: Package.PackageItem;
|
||||||
|
|
||||||
UserProfile?: UserProfile;
|
UserProfile?: UserProfile;
|
||||||
|
Order?: Order.OrderItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type UserItemByInfo = {
|
type UserItemByInfo = {
|
||||||
|
@ -35,5 +36,6 @@ declare namespace User {
|
||||||
projectCount: number;
|
projectCount: number;
|
||||||
projectCount: number;
|
projectCount: number;
|
||||||
materialsGroup: { _count: number; materialType: string }[];
|
materialsGroup: { _count: number; materialType: string }[];
|
||||||
|
dilatationLogs: { id: string; type: string; size: string; desc: string; createDate: string }[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 订单状态: 1: 待支付 2. 已支付 3. 订单取消 4. 支付失败 5. 订单超时支付(二维码过期)
|
||||||
|
export const UxOrderStatus: Record<number, string> = {
|
||||||
|
1: '待支付',
|
||||||
|
2: '已支付',
|
||||||
|
3: '订单取消',
|
||||||
|
4: '支付失败',
|
||||||
|
5: '订单超时支付(二维码过期)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UxOrderStatusTag: Record<number, string> = {
|
||||||
|
1: '#3498db', // 蓝色
|
||||||
|
2: '#27ae60', // 绿色
|
||||||
|
3: '#c8d6e5', // 灰色
|
||||||
|
4: '#e74c3c', // 红色
|
||||||
|
5: '订单超时支付(二维码过期)', //
|
||||||
|
};
|
|
@ -1,4 +1,11 @@
|
||||||
|
// @ts-ignore
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
// 示例方法,没有实际意义
|
// 示例方法,没有实际意义
|
||||||
export function trim(str: string) {
|
export function trim(str: string) {
|
||||||
return str.trim();
|
return str.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatDateTime = (time: string) => {
|
||||||
|
return dayjs(time).format('YYYY-MM-DD HH:ss:mm');
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue