From 7781c6c95cd2fba0967a1147bf7a7db078b45744 Mon Sep 17 00:00:00 2001 From: lq1405 <2769838458@qq.com> Date: Fri, 27 Dec 2024 21:49:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BD=AF=E4=BB=B6=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=9D=83=E9=99=90=EF=BC=8C=E5=8C=85=E6=8B=AC=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=EF=BC=8C=E7=AE=A1=E7=90=86=EF=BC=8C=E5=88=A0=E9=99=A4?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E4=BD=BF=E7=94=A8=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.ts | 11 +- src/access.ts | 11 +- src/app.tsx | 1 - .../RightContent/AvatarDropdown.tsx | 1 - src/global.tsx | 2 +- src/locales/zh-CN/menu.ts | 1 + src/pages/Machine/ModifyMachine/index.tsx | 3 - .../LaitoolOptions/BasicOptions/index.tsx | 1 - .../DubSetting/DubSettingTTsOptions/index.tsx | 2 - .../LaitoolOptions/DubSetting/index.tsx | 4 +- src/pages/Prompt/PromptManagement/index.tsx | 1 - .../ManagePromptType/index.tsx | 1 - .../Prompt/PromptTypeManagement/index.tsx | 1 - src/pages/Role/AddRoleForm/index.tsx | 1 - src/pages/Role/ManageRoleModal/index.tsx | 1 - src/pages/Role/RoleManagement/index.tsx | 2 - .../SofrwareControlManagement.tsx | 313 ++++++++++++++++++ src/pages/User/Login/index.tsx | 1 - src/pages/User/Register/index.tsx | 1 - .../UserCenter/{index.tsx => UserCenter.tsx} | 72 +++- .../UserCenterAgentMessage/index.tsx | 0 .../UserCenterUserInfo/index.tsx | 0 .../{ => UserCenter}/UserRenderList/index.tsx | 0 .../User/UserCenter/UserSoftwareInfo.tsx | 103 ++++++ .../{ => UserManage}/ModifyUser/index.tsx | 0 .../{ => UserManage}/UserManagement/index.tsx | 82 ++++- src/requestErrorConfig.ts | 9 - src/services/define/tokenStorage.ts | 6 - src/services/services/machine.ts | 3 - src/services/services/options/optionsTool.ts | 2 - src/services/services/prompt.ts | 4 - src/services/services/role.ts | 7 - src/services/services/software.ts | 94 ++++++ src/services/services/user.ts | 1 - src/services/typing/access.d.ts | 13 +- src/services/typing/software.d.ts | 47 +++ 36 files changed, 728 insertions(+), 74 deletions(-) create mode 100644 src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx rename src/pages/User/UserCenter/{index.tsx => UserCenter.tsx} (61%) rename src/pages/User/{ => UserCenter}/UserCenterAgentMessage/index.tsx (100%) rename src/pages/User/{ => UserCenter}/UserCenterUserInfo/index.tsx (100%) rename src/pages/User/{ => UserCenter}/UserRenderList/index.tsx (100%) create mode 100644 src/pages/User/UserCenter/UserSoftwareInfo.tsx rename src/pages/User/{ => UserManage}/ModifyUser/index.tsx (100%) rename src/pages/User/{ => UserManage}/UserManagement/index.tsx (77%) create mode 100644 src/services/services/software.ts create mode 100644 src/services/typing/software.d.ts diff --git a/config/routes.ts b/config/routes.ts index 28335a0..98b6d26 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -41,7 +41,7 @@ export default [ path: '/userCenter', name: 'userCenter', icon: 'User', - component: './User/UserCenter/index', + component: './User/UserCenter/UserCenter.tsx', }, { name: 'prompt', @@ -89,7 +89,7 @@ export default [ name: 'userManagement', icon: 'User', access: 'canUserManagement', - component: './User/UserManagement/index', + component: './User/UserManage/UserManagement/index', }, { path: '/machineManagement', @@ -98,6 +98,13 @@ export default [ access: 'canMachineManagement', component: './Machine/MachineManagement/index', }, + { + path: '/sofrwareControlManagement', + name: 'sofrwareControlManagement', + icon: 'Reconciliation', + access: 'canSofrwareControlManagement', + component: './Software/SofrwareControl/SofrwareControlManagement', + }, { path: '/', redirect: '/welcome', diff --git a/src/access.ts b/src/access.ts index e03f0c0..581abd9 100644 --- a/src/access.ts +++ b/src/access.ts @@ -3,8 +3,6 @@ * */ export default function access(initialState: { currentUser?: API.CurrentUser } | undefined): AccessType.AccessType { const { currentUser } = initialState ?? {}; - console.log("currentUser", currentUser); - console.log("userRole", currentUser?.roleNames); let access = { canPrompt: false, @@ -20,6 +18,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } | canOptions: false, canLaitoolOptions: false, + canApplySoftwareControl: false, + canSofrwareControlManagement: false, + canMachineManagement: false, canAddMachine: true, canEditMachine: false, @@ -72,6 +73,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } | canEditMachine: true, canDeleteMachine: true, canUpgradeMachine: true, + + canApplySoftwareControl: true, + canSofrwareControlManagement: true } } @@ -95,6 +99,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } | canEditMachine: true, canDeleteMachine: true, canUpgradeMachine: true, + + canApplySoftwareControl: true, + canSofrwareControlManagement: true }; } console.log("accsee", access); diff --git a/src/app.tsx b/src/app.tsx index 107c55f..03c5bdc 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -57,7 +57,6 @@ export async function getInitialState(): Promise<{ let currentUser = currentUserString ? JSON.parse(currentUserString) : null; let token = localStorage.getItem('token') ?? null; if (token == null || currentUser == null) { - console.log('没有登录,重定向到登录页面123') history.push('/user/login'); return { fetchUserInfo, diff --git a/src/components/RightContent/AvatarDropdown.tsx b/src/components/RightContent/AvatarDropdown.tsx index 5c177c3..0f28e3c 100644 --- a/src/components/RightContent/AvatarDropdown.tsx +++ b/src/components/RightContent/AvatarDropdown.tsx @@ -49,7 +49,6 @@ export const AvatarDropdown: React.FC = ({ menu, childre /** 此方法会跳转到 redirect 参数所在的位置 */ const redirect = urlParams.get('redirect'); // Note: There may be security issues, please note - console.log('没有登录,重定向到登录页面12333333333333333') if (window.location.pathname !== '/user/login' && !redirect) { history.replace({ pathname: '/user/login', diff --git a/src/global.tsx b/src/global.tsx index afa1fab..2e26173 100644 --- a/src/global.tsx +++ b/src/global.tsx @@ -15,7 +15,7 @@ const clearCache = () => { caches.delete(key); }); }) - .catch((e) => console.log(e)); + .catch((e) => console.error(e)); } }; diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts index 259cf71..52563db 100644 --- a/src/locales/zh-CN/menu.ts +++ b/src/locales/zh-CN/menu.ts @@ -15,6 +15,7 @@ export default { 'menu.userManagement': '用户管理', 'menu.machineManagement': '机器码管理', + 'menu.sofrwareControlManagement': '软件控制管理', 'menu.more-blocks': '更多区块', 'menu.home': '首页', diff --git a/src/pages/Machine/ModifyMachine/index.tsx b/src/pages/Machine/ModifyMachine/index.tsx index 9f261f2..a167537 100644 --- a/src/pages/Machine/ModifyMachine/index.tsx +++ b/src/pages/Machine/ModifyMachine/index.tsx @@ -66,7 +66,6 @@ const ModifyMachine: React.FC = ({ id, setFormRef, open }) = }; const onOk = (value: DatePickerProps['value'] | RangePickerProps['value']) => { - console.log('onOk: ', value); }; return ( @@ -145,8 +144,6 @@ const ModifyMachine: React.FC = ({ id, setFormRef, open }) = { - console.log('Selected Time: ', value); - console.log('Formatted Selected Time: ', dateString); }} onOk={onOk} /> diff --git a/src/pages/Options/LaitoolOptions/BasicOptions/index.tsx b/src/pages/Options/LaitoolOptions/BasicOptions/index.tsx index 4e8200b..84d41f5 100644 --- a/src/pages/Options/LaitoolOptions/BasicOptions/index.tsx +++ b/src/pages/Options/LaitoolOptions/BasicOptions/index.tsx @@ -7,7 +7,6 @@ import TrailOptions from './TrialOptions'; const DubSetting: React.FC = () => { const onChange = (key: string | string[]) => { - console.log(key); }; const items: CollapseProps['items'] = [ diff --git a/src/pages/Options/LaitoolOptions/DubSetting/DubSettingTTsOptions/index.tsx b/src/pages/Options/LaitoolOptions/DubSetting/DubSettingTTsOptions/index.tsx index 8dbbfdc..b523831 100644 --- a/src/pages/Options/LaitoolOptions/DubSetting/DubSettingTTsOptions/index.tsx +++ b/src/pages/Options/LaitoolOptions/DubSetting/DubSettingTTsOptions/index.tsx @@ -13,7 +13,6 @@ const DubSettingTTsOptions: React.FC = () => { const [messageApi, messageHolder] = message.useMessage(); async function onFinish(values: any): Promise { - console.log('Received values of form: ', values); setTopSpinning(true); setTopSpinTip("正在保存EdgeTTs配置"); try { @@ -32,7 +31,6 @@ const DubSettingTTsOptions: React.FC = () => { } } useEffect(() => { - console.log("DubSettingTTsOptions", ttsOptions) form.setFieldsValue({ edgeTTsRoles: getOptionsStringValue(ttsOptions, 'EdgeTTsRoles', "{}") }) }, [ttsOptions]) diff --git a/src/pages/Options/LaitoolOptions/DubSetting/index.tsx b/src/pages/Options/LaitoolOptions/DubSetting/index.tsx index f4131bf..2189d7b 100644 --- a/src/pages/Options/LaitoolOptions/DubSetting/index.tsx +++ b/src/pages/Options/LaitoolOptions/DubSetting/index.tsx @@ -11,7 +11,6 @@ const DubSetting: React.FC = () => { const { setTopSpinning, setTopSpinTip } = useSoftStore(); const onChange = (key: string | string[]) => { - console.log(key); }; useEffect(() => { @@ -22,9 +21,8 @@ const DubSetting: React.FC = () => { setTTsOptions(res); } ).catch((err) => { - console.log(err); + console.error(err); }).finally(() => { - console.log('finally'); setTopSpinning(false); }); diff --git a/src/pages/Prompt/PromptManagement/index.tsx b/src/pages/Prompt/PromptManagement/index.tsx index ac7d359..eee4729 100644 --- a/src/pages/Prompt/PromptManagement/index.tsx +++ b/src/pages/Prompt/PromptManagement/index.tsx @@ -123,7 +123,6 @@ const PromptManagement: React.FC = () => { okText: "确认", cancelText: "取消" }); - console.log(confirmed) if (confirmed) { setTopSpinning(true); setTopSpinTip("正在删除数据。。。") diff --git a/src/pages/Prompt/PromptTypeManagement/ManagePromptType/index.tsx b/src/pages/Prompt/PromptTypeManagement/ManagePromptType/index.tsx index c7a3bfb..f1db57a 100644 --- a/src/pages/Prompt/PromptTypeManagement/ManagePromptType/index.tsx +++ b/src/pages/Prompt/PromptTypeManagement/ManagePromptType/index.tsx @@ -82,7 +82,6 @@ const PromptManagement: React.FC = ({ type, setFormRef, i }; const onFinishFailed: FormProps['onFinishFailed'] = (errorInfo) => { - console.log('Failed:', errorInfo); }; return (<> diff --git a/src/pages/Prompt/PromptTypeManagement/index.tsx b/src/pages/Prompt/PromptTypeManagement/index.tsx index 947cc22..2966cc4 100644 --- a/src/pages/Prompt/PromptTypeManagement/index.tsx +++ b/src/pages/Prompt/PromptTypeManagement/index.tsx @@ -52,7 +52,6 @@ const PromptManagement: React.FC = () => { page: tableParams.pagination?.current ?? 1, } as Prompt.PromptTypeQueryCondition; - console.log("fetchData", params) let promptRes = await QueryPromptypeCollection(params) setData(promptRes.collection); setTableParams({ diff --git a/src/pages/Role/AddRoleForm/index.tsx b/src/pages/Role/AddRoleForm/index.tsx index ffa61b7..6ced46f 100644 --- a/src/pages/Role/AddRoleForm/index.tsx +++ b/src/pages/Role/AddRoleForm/index.tsx @@ -15,7 +15,6 @@ const AddRoleForm: React.FC = ({ setFormRef }) => { }, [form, setFormRef]); const onFinish = async (values: any) => { - console.log('Success:', values); setLoading(true); try { await AddRole(values.name, values.remark); diff --git a/src/pages/Role/ManageRoleModal/index.tsx b/src/pages/Role/ManageRoleModal/index.tsx index e155c55..8890ff2 100644 --- a/src/pages/Role/ManageRoleModal/index.tsx +++ b/src/pages/Role/ManageRoleModal/index.tsx @@ -41,7 +41,6 @@ const ManageRoleModal: React.FC = ({ roleId, setFormRef }) }, [roleId]); async function onFinish(values: RoleModel.Collection): Promise { - console.log("onFinish", values); setLoading(true); setSpinTip("更新中..."); try { diff --git a/src/pages/Role/RoleManagement/index.tsx b/src/pages/Role/RoleManagement/index.tsx index 6cd98e5..f6ec5fb 100644 --- a/src/pages/Role/RoleManagement/index.tsx +++ b/src/pages/Role/RoleManagement/index.tsx @@ -35,7 +35,6 @@ const RoleManagement: React.FC = () => { }, }); useEffect(() => { - console.log("RoleManagement useEffect"); // 初始化加载数据 QueryRoleList(tableParams, form.getFieldsValue()) .then((res) => { @@ -49,7 +48,6 @@ const RoleManagement: React.FC = () => { setLoading(false); }) .catch((error) => { - console.log(error); messageApi.error(error.message); }).finally(() => { setLoading(false); diff --git a/src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx b/src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx new file mode 100644 index 0000000..cf8bdb0 --- /dev/null +++ b/src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx @@ -0,0 +1,313 @@ +import React, { useEffect, useState } from 'react'; +import type { FC } from 'react'; +import TemplateContainer from '@/pages/TemplateContainer'; +import { useModel } from '@umijs/max'; +import { Button, Dropdown, Form, Input, message, Modal, Select, Table, TableProps, Tag } from 'antd'; +import { FilterValue, SorterResult, TableCurrentDataSource, TablePaginationConfig } from 'antd/es/table/interface'; +import { Software, SoftwareControl } from '@/services/services/software'; +import moment from 'moment'; +import { DeleteOutlined, EditOutlined, MenuOutlined, PlusSquareOutlined } from '@ant-design/icons'; + + +interface SoftwareControlManagementProps { + // Add your props here +} + +const SoftwareControlManagement: FC = () => { + const { initialState } = useModel('@@initialState'); + const [messageApi, messageHolder] = message.useMessage(); + const [loading, setLoading] = React.useState(false); + const [modalApi, modalHolder] = Modal.useModal(); + const [form] = Form.useForm(); + const [softwareBasicInfo, setSoftwareBasicInfo] = useState(); + const [softwareOptions, setSoftwareOptions] = useState([]); + const [data, setData] = React.useState([]); + const [tableParams, setTableParams] = useState({ + pagination: { + current: 1, + pageSize: 10, + showQuickJumper: true, + totalBoundaryShowSizeChanger: true, + }, + }); + + + + const columns: TableProps['columns'] = [ + { + title: '软件代码', + dataIndex: 'software', + width: 100, + key: 'softwareCode', + render: (software) => {software.softwareCode} + }, + { + title: '软件名称', + dataIndex: 'software', + key: 'softwareName', + render: (software) => {software.softwareName}, + }, + { + title: '所属用户ID', + dataIndex: 'user', + key: 'userId', + render: (user) => {user.id}, + }, + { + title: '所属用户名称', + dataIndex: 'user', + key: 'userName', + render: (user) => {user.nickName}, + }, + { + title: '创建者', + dataIndex: 'createdUser', + key: 'createdUserNickName', + render: (createdUser) => {createdUser.nickName}, + }, + { + title: '更新者', + dataIndex: 'updatedUser', + key: 'updatedUserNickName', + render: (updatedUser) => {updatedUser.nickName}, + }, + { + title: '更新时间', + dataIndex: 'updatedTime', + key: 'updatedTime', + width: 200, + render: (updatedTime) => updatedTime ? moment(updatedTime).format('YYYY-MM-DD HH:mm:ss') : 'null', + }, + { + title: '到期时间', + dataIndex: 'expirationTime', + key: 'expirationTime', + width: 200, + render: (expirationTime) => expirationTime ? moment(expirationTime).format('YYYY-MM-DD HH:mm:ss') : 'null', + }, + { + title: '是否永久', + dataIndex: 'isForever', + key: 'isForever', + width: 100, + render: (isForever) => isForever ? : , + }, + { + title: '操作', + key: 'action', + width: 100, + render: (_, record) => ( + , + onClick: () => { + // 编辑 + messageApi.warning("暂不支持编辑"); + } + }, + { + key: 'addMouth', + label: '添加月付', + style: { color: '#38a2fc' }, + icon: , + onClick: async () => { + // 延长到期时间 + await AddSoftwareControlExpirationTime(record.id, 30); + } + }, + { + key: 'addQuarterly', + label: '添加季付', + style: { color: '#38a2fc' }, + icon: , + onClick: async () => { + // 延长到期时间 + await AddSoftwareControlExpirationTime(record.id, 90); + } + }, + { + key: 'addHalfYear', + label: '添加半年', + style: { color: '#38a2fc' }, + icon: , + onClick: async () => { + // 延长到期时间 + await AddSoftwareControlExpirationTime(record.id, 180); + } + }, + { + key: 'addYear', + label: '添加年付', + style: { color: '#38a2fc' }, + icon: , + onClick: async () => { + // 延长到期时间 + await AddSoftwareControlExpirationTime(record.id, 365); + } + }, + { + key: 'addForever', + label: '永久', + style: { color: '#38a2fc' }, + icon: , + onClick: async () => { + // 延长到期时间 + await AddSoftwareControlExpirationTime(record.id, 0); + } + }, + { + key: 'delete', + label: '停用权限', + danger: true, + icon: , + onClick: async () => { + await DeleteSoftwareControl(record.id); + } + }, + ], + }} + > + + + +
+ columns={columns} dataSource={data} rowKey={(record) => record.id} pagination={tableParams.pagination} onChange={TableChangeHandle} loading={loading} /> +
+ {messageHolder} + {modalHolder} + + ); +}; + +export default SoftwareControlManagement; \ No newline at end of file diff --git a/src/pages/User/Login/index.tsx b/src/pages/User/Login/index.tsx index 6de5dcf..4fc1216 100644 --- a/src/pages/User/Login/index.tsx +++ b/src/pages/User/Login/index.tsx @@ -130,7 +130,6 @@ const Login: React.FC = () => { setUserLoginState({ status: 'error', }); - console.log(error); message.error(error.message); } }; diff --git a/src/pages/User/Register/index.tsx b/src/pages/User/Register/index.tsx index e252990..f5c6d78 100644 --- a/src/pages/User/Register/index.tsx +++ b/src/pages/User/Register/index.tsx @@ -19,7 +19,6 @@ const Register: React.FC = () => { }, []); const onFinish = async (values: UserModel.UserRegisterParams) => { - console.log('Received values of form: ', values); // 判断两次密码是否一致 if (values.password !== values.confirm) { messageApi.warning('两次密码不一致!'); diff --git a/src/pages/User/UserCenter/index.tsx b/src/pages/User/UserCenter/UserCenter.tsx similarity index 61% rename from src/pages/User/UserCenter/index.tsx rename to src/pages/User/UserCenter/UserCenter.tsx index 17b875d..cff43d0 100644 --- a/src/pages/User/UserCenter/index.tsx +++ b/src/pages/User/UserCenter/UserCenter.tsx @@ -2,16 +2,19 @@ import TemplateContainer from '@/pages/TemplateContainer'; import { GetUserAgentInfo, GetUserInfo } from '@/services/services/user'; import { RedoOutlined } from '@ant-design/icons'; import { useModel } from '@umijs/max'; -import { Avatar, Button, Card, Col, Input, message, Modal, Row, Spin, Tag } from 'antd'; +import { Avatar, Badge, Button, Card, Col, FloatButton, Input, message, Modal, Row, Spin, Tag } from 'antd'; import React, { useEffect, useState } from 'react'; -import UserCenterUserInfo from '../UserCenterUserInfo'; -import UserCenterAgentMessage from '../UserCenterAgentMessage'; +import UserCenterUserInfo from './UserCenterUserInfo'; +import UserCenterAgentMessage from './UserCenterAgentMessage'; import { useSoftStore } from '@/store/software'; +import { SoftwareControl } from '@/services/services/software'; +import UserSoftwareInfo from './UserSoftwareInfo'; const UserCenter: React.FC = () => { const { initialState, setInitialState } = useModel('@@initialState'); const [messageApi, messageHolder] = message.useMessage(); const [modalApi, modalHolder] = Modal.useModal(); + const [badgeCount, setBadgeCount] = useState(0); const { setTopSpinTip, setTopSpinning } = useSoftStore(); const [userAgentUserInfo, setUserAgentUserInfo] = useState(); @@ -26,13 +29,62 @@ const UserCenter: React.FC = () => { let agentInfo = await GetUserAgentInfo(); setUserAgentUserInfo(agentInfo); }).catch((error) => { - console.log(error) + messageApi.error(error.message); }).finally(() => { setTopSpinning(false); }) + // 加载当前用户可申请的的软件控制权限 + SoftwareControl.GetUserSoftwareControlCount(initialState?.currentUser?.id).then((res) => { + setBadgeCount(res); + }).catch((error) => { + messageApi.error(error.message); + }) } }, []) + /** + * 申请用户软件控制权限 + */ + async function ApplyUserSoftwareControlHandle() { + let userID = initialState?.currentUser?.id; + if (!userID) { + messageApi.error("用户信息不存在"); + return; + } + // 重新获取用户关联信息 + const userCanApplyCount = await SoftwareControl.GetUserSoftwareControlCount(userID); + if (userCanApplyCount <= 0) { + messageApi.warning("您已经没有可申请的软件控制权限了"); + return; + } + // 开始调用申请接口 + setTopSpinning(true); + setTopSpinTip("正在申请软件控制权限。。。"); + try { + await SoftwareControl.ApplyUserSoftwareControl(userID); + // 提示成功 + messageApi.success("申请成功"); + setBadgeCount(0); + } catch (error: any) { + messageApi.error(error.message); + } finally { + setTopSpinning(false); + } + } + + /** + * 显示软件控制权限 + */ + async function ShowSoftwareControlHandle() { + modalApi.info({ + title: "用户软件控制权限", + content: , + width: 800, + footer: null, + closable: true, + }); + } + function renderTitie() { return (
@@ -81,6 +133,18 @@ const UserCenter: React.FC = () => {
{initialState?.currentUser?.affiliateCode} + +
+ 软件控制权限 + +
+ { + badgeCount > 0 ? + + : + } + + diff --git a/src/pages/User/UserCenterAgentMessage/index.tsx b/src/pages/User/UserCenter/UserCenterAgentMessage/index.tsx similarity index 100% rename from src/pages/User/UserCenterAgentMessage/index.tsx rename to src/pages/User/UserCenter/UserCenterAgentMessage/index.tsx diff --git a/src/pages/User/UserCenterUserInfo/index.tsx b/src/pages/User/UserCenter/UserCenterUserInfo/index.tsx similarity index 100% rename from src/pages/User/UserCenterUserInfo/index.tsx rename to src/pages/User/UserCenter/UserCenterUserInfo/index.tsx diff --git a/src/pages/User/UserRenderList/index.tsx b/src/pages/User/UserCenter/UserRenderList/index.tsx similarity index 100% rename from src/pages/User/UserRenderList/index.tsx rename to src/pages/User/UserCenter/UserRenderList/index.tsx diff --git a/src/pages/User/UserCenter/UserSoftwareInfo.tsx b/src/pages/User/UserCenter/UserSoftwareInfo.tsx new file mode 100644 index 0000000..3d411ac --- /dev/null +++ b/src/pages/User/UserCenter/UserSoftwareInfo.tsx @@ -0,0 +1,103 @@ +import React, { useEffect, useState } from 'react'; +import { message, Space, Table, Tag } from 'antd'; +import type { TablePaginationConfig, TableProps } from 'antd'; +import { FilterValue, SorterResult, TableCurrentDataSource } from 'antd/es/table/interface'; +import { SoftwareControl } from '@/services/services/software'; +import { useModel } from '@umijs/max'; +import moment from 'moment'; + + +const columns: TableProps['columns'] = [ + { + title: '软件代码', + dataIndex: 'software', + width: 100, + key: 'softwareCode', + render: (software) => {software.softwareCode} + }, + { + title: '软件名称', + dataIndex: 'software', + key: 'softwareName', + render: (software) => {software.softwareName}, + }, + { + title: '到期时间', + dataIndex: 'expirationTime', + key: 'expirationTime', + width: 200, + render: (expirationTime) => expirationTime ? moment(expirationTime).format('YYYY-MM-DD HH:mm:ss') : 'null', + }, + { + title: '是否永久', + dataIndex: 'isForever', + key: 'isForever', + width: 100, + render: (isForever) => isForever ? : , + } +]; + +interface UserSoftwareInfoProps { + userId?: number; +} + +const UserSoftwareInfo: React.FC = ({ userId }) => { + const [data, setData] = React.useState([]); + const [loading, setLoading] = React.useState(false); + const [messageApi, messageHolder] = message.useMessage(); + const [tableParams, setTableParams] = useState({ + pagination: { + current: 1, + pageSize: 10, + showQuickJumper: true, + totalBoundaryShowSizeChanger: true, + }, + }); + + async function QueryUserSoftwareControlCollection() { + try { + if (userId == null) { + messageApi.error("用户ID不能为空"); + } + setLoading(true); + let res = await SoftwareControl.GetUserSoftwareControlCollection(tableParams, { + userId: userId + }); + setData(res.collection); + setTableParams({ + pagination: { + ...tableParams.pagination, + total: res.total + } + }) + } catch (error: any) { + messageApi.error(error.message); + } finally { + setLoading(false); + } + } + + useEffect(() => { + QueryUserSoftwareControlCollection().then(); + }, []); + + async function TableChangeHandle(pagination: TablePaginationConfig, filters: Record, sorter: SorterResult | SorterResult[], extra: TableCurrentDataSource): Promise { + await QueryUserSoftwareControlCollection(); + setTableParams({ + pagination: { + ...tableParams.pagination, + current: pagination.current, + pageSize: pagination.pageSize, + } + }); + } + + return ( +
+ columns={columns} dataSource={data} rowKey={(record) => record.id} pagination={tableParams.pagination} onChange={TableChangeHandle} loading={loading} /> + {messageHolder} +
+ ); +}; + +export default UserSoftwareInfo; \ No newline at end of file diff --git a/src/pages/User/ModifyUser/index.tsx b/src/pages/User/UserManage/ModifyUser/index.tsx similarity index 100% rename from src/pages/User/ModifyUser/index.tsx rename to src/pages/User/UserManage/ModifyUser/index.tsx diff --git a/src/pages/User/UserManagement/index.tsx b/src/pages/User/UserManage/UserManagement/index.tsx similarity index 77% rename from src/pages/User/UserManagement/index.tsx rename to src/pages/User/UserManage/UserManagement/index.tsx index 71586bd..9acbd59 100644 --- a/src/pages/User/UserManagement/index.tsx +++ b/src/pages/User/UserManage/UserManagement/index.tsx @@ -4,11 +4,13 @@ import { QueryRoleOption } from "@/services/services/role"; import { QueryUserList } from "@/services/services/user"; import { FormatDate } from "@/util/time"; import { useAccess, useModel } from "@umijs/max"; -import { Button, Form, Input, InputNumber, message, Modal, Select, SelectProps, Table, Tag, Tooltip } from "antd"; +import { Button, Dropdown, Form, Input, InputNumber, message, Modal, Select, SelectProps, Table, Tag, Tooltip } from "antd"; import { ColumnsType, TablePaginationConfig } from "antd/es/table"; import { FilterValue, SorterResult, TableCurrentDataSource } from "antd/es/table/interface"; import { useEffect, useState } from "react"; import ModifyUser from "../ModifyUser"; +import { DeleteOutlined, EditOutlined, MenuOutlined, SyncOutlined } from "@ant-design/icons"; +import { SoftwareControl } from "@/services/services/software"; const UserManagement: React.FC = () => { type TagRender = SelectProps['tagRender']; @@ -134,6 +136,33 @@ const UserManagement: React.FC = () => { ); }; + /** + * 给指定用户申请软件控制权限 + * @param userId 用户ID + * @returns + */ + async function ApplySoftwareControlHandle(userId: number) { + if (!access.isAdminOrSuperAdmin) { + messageApi.error("您没有权限执行此操作"); + return; + } + try { + setLoading(true); + let userCanApplyCount = await SoftwareControl.GetUserSoftwareControlCount(userId); + if (userCanApplyCount <= 0) { + messageApi.warning("用户已经没有可申请的软件控制权限了"); + return; + } + // 开始申请 + await SoftwareControl.ApplyUserSoftwareControl(userId); + messageApi.success("用户软件控制权限申请成功"); + } catch (error: any) { + messageApi.error(error.message); + } finally { + setLoading(false); + } + } + const columns: ColumnsType = [ { title: 'ID', @@ -200,17 +229,48 @@ const UserManagement: React.FC = () => { }, { title: '操作', - width: '120px', + width: '80px', + hidden: !access.isAdminOrSuperAdmin, render: (text, record) => ( -
- - -
+ , + hidden: !access.canEditUser, + primary: true, + onClick: () => { + setUserId(record.id); + setOpenModal(true); + } + }, + { + key: 'apply', + label: '初始化权限', + icon: , + hidden: !access.canApplySoftwareControl, + primary: true, + onClick: async () => { + await ApplySoftwareControlHandle(record.id); + } + }, + { + key: 'delete', + label: '删除', + icon: , + hidden: !access.canDeleteUser, + danger: true, + onClick: () => { + messageApi.error("暂不支持删除用户"); + } + } + ].filter(item => !item.hidden) + }} + > +