新增软件管理权限,包括申请,管理,删除,添加使用时间等
This commit is contained in:
parent
ae15530766
commit
7781c6c95c
@ -41,7 +41,7 @@ export default [
|
|||||||
path: '/userCenter',
|
path: '/userCenter',
|
||||||
name: 'userCenter',
|
name: 'userCenter',
|
||||||
icon: 'User',
|
icon: 'User',
|
||||||
component: './User/UserCenter/index',
|
component: './User/UserCenter/UserCenter.tsx',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'prompt',
|
name: 'prompt',
|
||||||
@ -89,7 +89,7 @@ export default [
|
|||||||
name: 'userManagement',
|
name: 'userManagement',
|
||||||
icon: 'User',
|
icon: 'User',
|
||||||
access: 'canUserManagement',
|
access: 'canUserManagement',
|
||||||
component: './User/UserManagement/index',
|
component: './User/UserManage/UserManagement/index',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/machineManagement',
|
path: '/machineManagement',
|
||||||
@ -98,6 +98,13 @@ export default [
|
|||||||
access: 'canMachineManagement',
|
access: 'canMachineManagement',
|
||||||
component: './Machine/MachineManagement/index',
|
component: './Machine/MachineManagement/index',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/sofrwareControlManagement',
|
||||||
|
name: 'sofrwareControlManagement',
|
||||||
|
icon: 'Reconciliation',
|
||||||
|
access: 'canSofrwareControlManagement',
|
||||||
|
component: './Software/SofrwareControl/SofrwareControlManagement',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: '/welcome',
|
redirect: '/welcome',
|
||||||
|
|||||||
@ -3,8 +3,6 @@
|
|||||||
* */
|
* */
|
||||||
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined): AccessType.AccessType {
|
export default function access(initialState: { currentUser?: API.CurrentUser } | undefined): AccessType.AccessType {
|
||||||
const { currentUser } = initialState ?? {};
|
const { currentUser } = initialState ?? {};
|
||||||
console.log("currentUser", currentUser);
|
|
||||||
console.log("userRole", currentUser?.roleNames);
|
|
||||||
|
|
||||||
let access = {
|
let access = {
|
||||||
canPrompt: false,
|
canPrompt: false,
|
||||||
@ -20,6 +18,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
|
|||||||
canOptions: false,
|
canOptions: false,
|
||||||
canLaitoolOptions: false,
|
canLaitoolOptions: false,
|
||||||
|
|
||||||
|
canApplySoftwareControl: false,
|
||||||
|
canSofrwareControlManagement: false,
|
||||||
|
|
||||||
canMachineManagement: false,
|
canMachineManagement: false,
|
||||||
canAddMachine: true,
|
canAddMachine: true,
|
||||||
canEditMachine: false,
|
canEditMachine: false,
|
||||||
@ -72,6 +73,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
|
|||||||
canEditMachine: true,
|
canEditMachine: true,
|
||||||
canDeleteMachine: true,
|
canDeleteMachine: true,
|
||||||
canUpgradeMachine: true,
|
canUpgradeMachine: true,
|
||||||
|
|
||||||
|
canApplySoftwareControl: true,
|
||||||
|
canSofrwareControlManagement: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +99,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
|
|||||||
canEditMachine: true,
|
canEditMachine: true,
|
||||||
canDeleteMachine: true,
|
canDeleteMachine: true,
|
||||||
canUpgradeMachine: true,
|
canUpgradeMachine: true,
|
||||||
|
|
||||||
|
canApplySoftwareControl: true,
|
||||||
|
canSofrwareControlManagement: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
console.log("accsee", access);
|
console.log("accsee", access);
|
||||||
|
|||||||
@ -57,7 +57,6 @@ export async function getInitialState(): Promise<{
|
|||||||
let currentUser = currentUserString ? JSON.parse(currentUserString) : null;
|
let currentUser = currentUserString ? JSON.parse(currentUserString) : null;
|
||||||
let token = localStorage.getItem('token') ?? null;
|
let token = localStorage.getItem('token') ?? null;
|
||||||
if (token == null || currentUser == null) {
|
if (token == null || currentUser == null) {
|
||||||
console.log('没有登录,重定向到登录页面123')
|
|
||||||
history.push('/user/login');
|
history.push('/user/login');
|
||||||
return {
|
return {
|
||||||
fetchUserInfo,
|
fetchUserInfo,
|
||||||
|
|||||||
@ -49,7 +49,6 @@ export const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu, childre
|
|||||||
/** 此方法会跳转到 redirect 参数所在的位置 */
|
/** 此方法会跳转到 redirect 参数所在的位置 */
|
||||||
const redirect = urlParams.get('redirect');
|
const redirect = urlParams.get('redirect');
|
||||||
// Note: There may be security issues, please note
|
// Note: There may be security issues, please note
|
||||||
console.log('没有登录,重定向到登录页面12333333333333333')
|
|
||||||
if (window.location.pathname !== '/user/login' && !redirect) {
|
if (window.location.pathname !== '/user/login' && !redirect) {
|
||||||
history.replace({
|
history.replace({
|
||||||
pathname: '/user/login',
|
pathname: '/user/login',
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const clearCache = () => {
|
|||||||
caches.delete(key);
|
caches.delete(key);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((e) => console.log(e));
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export default {
|
|||||||
'menu.userManagement': '用户管理',
|
'menu.userManagement': '用户管理',
|
||||||
|
|
||||||
'menu.machineManagement': '机器码管理',
|
'menu.machineManagement': '机器码管理',
|
||||||
|
'menu.sofrwareControlManagement': '软件控制管理',
|
||||||
|
|
||||||
'menu.more-blocks': '更多区块',
|
'menu.more-blocks': '更多区块',
|
||||||
'menu.home': '首页',
|
'menu.home': '首页',
|
||||||
|
|||||||
@ -66,7 +66,6 @@ const ModifyMachine: React.FC<ModifyMachineProps> = ({ id, setFormRef, open }) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onOk = (value: DatePickerProps['value'] | RangePickerProps['value']) => {
|
const onOk = (value: DatePickerProps['value'] | RangePickerProps['value']) => {
|
||||||
console.log('onOk: ', value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -145,8 +144,6 @@ const ModifyMachine: React.FC<ModifyMachineProps> = ({ id, setFormRef, open }) =
|
|||||||
<DatePicker
|
<DatePicker
|
||||||
showTime
|
showTime
|
||||||
onChange={(value, dateString) => {
|
onChange={(value, dateString) => {
|
||||||
console.log('Selected Time: ', value);
|
|
||||||
console.log('Formatted Selected Time: ', dateString);
|
|
||||||
}}
|
}}
|
||||||
onOk={onOk}
|
onOk={onOk}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import TrailOptions from './TrialOptions';
|
|||||||
const DubSetting: React.FC = () => {
|
const DubSetting: React.FC = () => {
|
||||||
|
|
||||||
const onChange = (key: string | string[]) => {
|
const onChange = (key: string | string[]) => {
|
||||||
console.log(key);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const items: CollapseProps['items'] = [
|
const items: CollapseProps['items'] = [
|
||||||
|
|||||||
@ -13,7 +13,6 @@ const DubSettingTTsOptions: React.FC = () => {
|
|||||||
const [messageApi, messageHolder] = message.useMessage();
|
const [messageApi, messageHolder] = message.useMessage();
|
||||||
|
|
||||||
async function onFinish(values: any): Promise<void> {
|
async function onFinish(values: any): Promise<void> {
|
||||||
console.log('Received values of form: ', values);
|
|
||||||
setTopSpinning(true);
|
setTopSpinning(true);
|
||||||
setTopSpinTip("正在保存EdgeTTs配置");
|
setTopSpinTip("正在保存EdgeTTs配置");
|
||||||
try {
|
try {
|
||||||
@ -32,7 +31,6 @@ const DubSettingTTsOptions: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("DubSettingTTsOptions", ttsOptions)
|
|
||||||
form.setFieldsValue({ edgeTTsRoles: getOptionsStringValue(ttsOptions, 'EdgeTTsRoles', "{}") })
|
form.setFieldsValue({ edgeTTsRoles: getOptionsStringValue(ttsOptions, 'EdgeTTsRoles', "{}") })
|
||||||
}, [ttsOptions])
|
}, [ttsOptions])
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ const DubSetting: React.FC = () => {
|
|||||||
const { setTopSpinning, setTopSpinTip } = useSoftStore();
|
const { setTopSpinning, setTopSpinTip } = useSoftStore();
|
||||||
|
|
||||||
const onChange = (key: string | string[]) => {
|
const onChange = (key: string | string[]) => {
|
||||||
console.log(key);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -22,9 +21,8 @@ const DubSetting: React.FC = () => {
|
|||||||
setTTsOptions(res);
|
setTTsOptions(res);
|
||||||
}
|
}
|
||||||
).catch((err) => {
|
).catch((err) => {
|
||||||
console.log(err);
|
console.error(err);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
console.log('finally');
|
|
||||||
setTopSpinning(false);
|
setTopSpinning(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,6 @@ const PromptManagement: React.FC = () => {
|
|||||||
okText: "确认",
|
okText: "确认",
|
||||||
cancelText: "取消"
|
cancelText: "取消"
|
||||||
});
|
});
|
||||||
console.log(confirmed)
|
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
setTopSpinning(true);
|
setTopSpinning(true);
|
||||||
setTopSpinTip("正在删除数据。。。")
|
setTopSpinTip("正在删除数据。。。")
|
||||||
|
|||||||
@ -82,7 +82,6 @@ const PromptManagement: React.FC<PromptManagementProps> = ({ type, setFormRef, i
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onFinishFailed: FormProps<Prompt.AddPromptType>['onFinishFailed'] = (errorInfo) => {
|
const onFinishFailed: FormProps<Prompt.AddPromptType>['onFinishFailed'] = (errorInfo) => {
|
||||||
console.log('Failed:', errorInfo);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
|
|||||||
@ -52,7 +52,6 @@ const PromptManagement: React.FC = () => {
|
|||||||
page: tableParams.pagination?.current ?? 1,
|
page: tableParams.pagination?.current ?? 1,
|
||||||
} as Prompt.PromptTypeQueryCondition;
|
} as Prompt.PromptTypeQueryCondition;
|
||||||
|
|
||||||
console.log("fetchData", params)
|
|
||||||
let promptRes = await QueryPromptypeCollection(params)
|
let promptRes = await QueryPromptypeCollection(params)
|
||||||
setData(promptRes.collection);
|
setData(promptRes.collection);
|
||||||
setTableParams({
|
setTableParams({
|
||||||
|
|||||||
@ -15,7 +15,6 @@ const AddRoleForm: React.FC<AddRoleModalProps> = ({ setFormRef }) => {
|
|||||||
}, [form, setFormRef]);
|
}, [form, setFormRef]);
|
||||||
|
|
||||||
const onFinish = async (values: any) => {
|
const onFinish = async (values: any) => {
|
||||||
console.log('Success:', values);
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
await AddRole(values.name, values.remark);
|
await AddRole(values.name, values.remark);
|
||||||
|
|||||||
@ -41,7 +41,6 @@ const ManageRoleModal: React.FC<ManageRoleModalProps> = ({ roleId, setFormRef })
|
|||||||
}, [roleId]);
|
}, [roleId]);
|
||||||
|
|
||||||
async function onFinish(values: RoleModel.Collection): Promise<void> {
|
async function onFinish(values: RoleModel.Collection): Promise<void> {
|
||||||
console.log("onFinish", values);
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setSpinTip("更新中...");
|
setSpinTip("更新中...");
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -35,7 +35,6 @@ const RoleManagement: React.FC = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("RoleManagement useEffect");
|
|
||||||
// 初始化加载数据
|
// 初始化加载数据
|
||||||
QueryRoleList(tableParams, form.getFieldsValue())
|
QueryRoleList(tableParams, form.getFieldsValue())
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -49,7 +48,6 @@ const RoleManagement: React.FC = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
|
||||||
messageApi.error(error.message);
|
messageApi.error(error.message);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|||||||
313
src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx
Normal file
313
src/pages/Software/SofrwareControl/SofrwareControlManagement.tsx
Normal file
@ -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<SoftwareControlManagementProps> = () => {
|
||||||
|
const { initialState } = useModel('@@initialState');
|
||||||
|
const [messageApi, messageHolder] = message.useMessage();
|
||||||
|
const [loading, setLoading] = React.useState<boolean>(false);
|
||||||
|
const [modalApi, modalHolder] = Modal.useModal();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [softwareBasicInfo, setSoftwareBasicInfo] = useState<SoftwareModel.SoftwareBasicInfo[]>();
|
||||||
|
const [softwareOptions, setSoftwareOptions] = useState<any>([]);
|
||||||
|
const [data, setData] = React.useState<SoftwareModel.SoftwareControlBase[]>([]);
|
||||||
|
const [tableParams, setTableParams] = useState<TableModel.TableParams>({
|
||||||
|
pagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
showQuickJumper: true,
|
||||||
|
totalBoundaryShowSizeChanger: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const columns: TableProps<SoftwareModel.SoftwareControlBase>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '软件代码',
|
||||||
|
dataIndex: 'software',
|
||||||
|
width: 100,
|
||||||
|
key: 'softwareCode',
|
||||||
|
render: (software) => <span> {software.softwareCode}</span >
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '软件名称',
|
||||||
|
dataIndex: 'software',
|
||||||
|
key: 'softwareName',
|
||||||
|
render: (software) => <span>{software.softwareName}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属用户ID',
|
||||||
|
dataIndex: 'user',
|
||||||
|
key: 'userId',
|
||||||
|
render: (user) => <span>{user.id}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所属用户名称',
|
||||||
|
dataIndex: 'user',
|
||||||
|
key: 'userName',
|
||||||
|
render: (user) => <span>{user.nickName}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建者',
|
||||||
|
dataIndex: 'createdUser',
|
||||||
|
key: 'createdUserNickName',
|
||||||
|
render: (createdUser) => <span>{createdUser.nickName}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '更新者',
|
||||||
|
dataIndex: 'updatedUser',
|
||||||
|
key: 'updatedUserNickName',
|
||||||
|
render: (updatedUser) => <span>{updatedUser.nickName}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 ? <Tag color="green">是</Tag> : <Tag color="red">否</Tag>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 100,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
key: 'edit',
|
||||||
|
label: '编辑',
|
||||||
|
icon: <EditOutlined />,
|
||||||
|
onClick: () => {
|
||||||
|
// 编辑
|
||||||
|
messageApi.warning("暂不支持编辑");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addMouth',
|
||||||
|
label: '添加月付',
|
||||||
|
style: { color: '#38a2fc' },
|
||||||
|
icon: <PlusSquareOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
// 延长到期时间
|
||||||
|
await AddSoftwareControlExpirationTime(record.id, 30);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addQuarterly',
|
||||||
|
label: '添加季付',
|
||||||
|
style: { color: '#38a2fc' },
|
||||||
|
icon: <PlusSquareOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
// 延长到期时间
|
||||||
|
await AddSoftwareControlExpirationTime(record.id, 90);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addHalfYear',
|
||||||
|
label: '添加半年',
|
||||||
|
style: { color: '#38a2fc' },
|
||||||
|
icon: <PlusSquareOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
// 延长到期时间
|
||||||
|
await AddSoftwareControlExpirationTime(record.id, 180);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addYear',
|
||||||
|
label: '添加年付',
|
||||||
|
style: { color: '#38a2fc' },
|
||||||
|
icon: <PlusSquareOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
// 延长到期时间
|
||||||
|
await AddSoftwareControlExpirationTime(record.id, 365);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addForever',
|
||||||
|
label: '永久',
|
||||||
|
style: { color: '#38a2fc' },
|
||||||
|
icon: <PlusSquareOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
// 延长到期时间
|
||||||
|
await AddSoftwareControlExpirationTime(record.id, 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'delete',
|
||||||
|
label: '停用权限',
|
||||||
|
danger: true,
|
||||||
|
icon: <DeleteOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
await DeleteSoftwareControl(record.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button type="text" color="primary" variant="filled" icon={<MenuOutlined />} />
|
||||||
|
</Dropdown>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
async function DeleteSoftwareControl(id: string) {
|
||||||
|
try {
|
||||||
|
const confirmed = await modalApi.confirm({
|
||||||
|
title: "确认停用",
|
||||||
|
content: "确定停用吗,重置到期时间和永久选项"
|
||||||
|
});
|
||||||
|
if (confirmed) {
|
||||||
|
setLoading(true);
|
||||||
|
await SoftwareControl.AddSoftwareControlExpirationTime(id, 0, false);
|
||||||
|
// 重新查询
|
||||||
|
await QueryUserSoftwareControlCollection();
|
||||||
|
messageApi.success("停用成功");
|
||||||
|
} else {
|
||||||
|
messageApi.info("取消停用");
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
messageApi.error(error.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function AddSoftwareControlExpirationTime(id: string, days: number) {
|
||||||
|
try {
|
||||||
|
const confirmed = await modalApi.confirm({
|
||||||
|
title: "确认添加",
|
||||||
|
content: `确认添加 ${days == 0 ? "永久" : days + " 天"} 吗?`
|
||||||
|
});
|
||||||
|
if (confirmed) {
|
||||||
|
setLoading(true);
|
||||||
|
await SoftwareControl.AddSoftwareControlExpirationTime(id, days, days == 0);
|
||||||
|
// 重新查询
|
||||||
|
await QueryUserSoftwareControlCollection();
|
||||||
|
if (days == 0) {
|
||||||
|
messageApi.success("添加永久成功");
|
||||||
|
} else {
|
||||||
|
messageApi.success("添加 " + days + " 天成功");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageApi.info("取消添加");
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
messageApi.error(error.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function QueryUserSoftwareControlCollection(options?: SoftwareModel.SoftwareControlQueryParams) {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
let res = await SoftwareControl.GetUserSoftwareControlCollection(tableParams, options ?? {});
|
||||||
|
setData(res.collection);
|
||||||
|
setTableParams({
|
||||||
|
pagination: {
|
||||||
|
...tableParams.pagination,
|
||||||
|
total: res.total
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
messageApi.error(error.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
QueryUserSoftwareControlCollection().then();
|
||||||
|
Software.GetSoftwareBaseCollection().then((res) => {
|
||||||
|
setSoftwareBasicInfo(res);
|
||||||
|
let options = []
|
||||||
|
for (let i = 0; i < res.length; i++) {
|
||||||
|
const element = res[i];
|
||||||
|
let option = {
|
||||||
|
label: element.isUse == false ? element.softwareName + "(未启用)" : element.softwareName,
|
||||||
|
value: element.id
|
||||||
|
}
|
||||||
|
options.push(option);
|
||||||
|
}
|
||||||
|
setSoftwareOptions(options);
|
||||||
|
}).catch((error) => {
|
||||||
|
messageApi.error(error.message);
|
||||||
|
})
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function TableChangeHandle(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>, sorter: SorterResult<SoftwareModel.SoftwareControlBase> | SorterResult<SoftwareModel.SoftwareControlBase>[], extra: TableCurrentDataSource<SoftwareModel.SoftwareControlBase>): Promise<void> {
|
||||||
|
await QueryUserSoftwareControlCollection();
|
||||||
|
setTableParams({
|
||||||
|
pagination: {
|
||||||
|
...tableParams.pagination,
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function QuerySoftwareControlByCondition(values: any) {
|
||||||
|
await QueryUserSoftwareControlCollection(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
|
||||||
|
<Form
|
||||||
|
layout='inline'
|
||||||
|
form={form}
|
||||||
|
onFinish={QuerySoftwareControlByCondition}
|
||||||
|
>
|
||||||
|
<Form.Item label="用户ID" name='userId' style={{ marginBottom: 5 }}>
|
||||||
|
<Input placeholder="请输入用户ID" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="软件" name='softwareId' style={{ marginBottom: 5 }}>
|
||||||
|
<Select placeholder="请选择用户名称" style={{ width: 200 }} options={softwareOptions} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="是否永久" name='IsForever' style={{ marginBottom: 5 }}>
|
||||||
|
<Select placeholder="请选择是否永久" style={{ width: 200 }} options={[{ label: "是", value: true }, { label: "否", value: false }]} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="备注" name='remark' style={{ marginBottom: 5 }}>
|
||||||
|
<Input placeholder="请输入备注" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item>
|
||||||
|
<Button type="primary" htmlType="submit">查询</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
<div>
|
||||||
|
<Table<SoftwareModel.SoftwareControlBase> columns={columns} dataSource={data} rowKey={(record) => record.id} pagination={tableParams.pagination} onChange={TableChangeHandle} loading={loading} />
|
||||||
|
</div>
|
||||||
|
{messageHolder}
|
||||||
|
{modalHolder}
|
||||||
|
</TemplateContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SoftwareControlManagement;
|
||||||
@ -130,7 +130,6 @@ const Login: React.FC = () => {
|
|||||||
setUserLoginState({
|
setUserLoginState({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
});
|
});
|
||||||
console.log(error);
|
|
||||||
message.error(error.message);
|
message.error(error.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,7 +19,6 @@ const Register: React.FC = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onFinish = async (values: UserModel.UserRegisterParams) => {
|
const onFinish = async (values: UserModel.UserRegisterParams) => {
|
||||||
console.log('Received values of form: ', values);
|
|
||||||
// 判断两次密码是否一致
|
// 判断两次密码是否一致
|
||||||
if (values.password !== values.confirm) {
|
if (values.password !== values.confirm) {
|
||||||
messageApi.warning('两次密码不一致!');
|
messageApi.warning('两次密码不一致!');
|
||||||
|
|||||||
@ -2,16 +2,19 @@ import TemplateContainer from '@/pages/TemplateContainer';
|
|||||||
import { GetUserAgentInfo, GetUserInfo } from '@/services/services/user';
|
import { GetUserAgentInfo, GetUserInfo } from '@/services/services/user';
|
||||||
import { RedoOutlined } from '@ant-design/icons';
|
import { RedoOutlined } from '@ant-design/icons';
|
||||||
import { useModel } from '@umijs/max';
|
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 React, { useEffect, useState } from 'react';
|
||||||
import UserCenterUserInfo from '../UserCenterUserInfo';
|
import UserCenterUserInfo from './UserCenterUserInfo';
|
||||||
import UserCenterAgentMessage from '../UserCenterAgentMessage';
|
import UserCenterAgentMessage from './UserCenterAgentMessage';
|
||||||
import { useSoftStore } from '@/store/software';
|
import { useSoftStore } from '@/store/software';
|
||||||
|
import { SoftwareControl } from '@/services/services/software';
|
||||||
|
import UserSoftwareInfo from './UserSoftwareInfo';
|
||||||
|
|
||||||
const UserCenter: React.FC = () => {
|
const UserCenter: React.FC = () => {
|
||||||
const { initialState, setInitialState } = useModel('@@initialState');
|
const { initialState, setInitialState } = useModel('@@initialState');
|
||||||
const [messageApi, messageHolder] = message.useMessage();
|
const [messageApi, messageHolder] = message.useMessage();
|
||||||
const [modalApi, modalHolder] = Modal.useModal();
|
const [modalApi, modalHolder] = Modal.useModal();
|
||||||
|
const [badgeCount, setBadgeCount] = useState(0);
|
||||||
const { setTopSpinTip, setTopSpinning } = useSoftStore();
|
const { setTopSpinTip, setTopSpinning } = useSoftStore();
|
||||||
const [userAgentUserInfo, setUserAgentUserInfo] = useState<UserModel.UserAgentInfo>();
|
const [userAgentUserInfo, setUserAgentUserInfo] = useState<UserModel.UserAgentInfo>();
|
||||||
|
|
||||||
@ -26,13 +29,62 @@ const UserCenter: React.FC = () => {
|
|||||||
let agentInfo = await GetUserAgentInfo();
|
let agentInfo = await GetUserAgentInfo();
|
||||||
setUserAgentUserInfo(agentInfo);
|
setUserAgentUserInfo(agentInfo);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.log(error)
|
messageApi.error(error.message);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
setTopSpinning(false);
|
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: <UserSoftwareInfo userId={initialState?.currentUser?.id} />,
|
||||||
|
width: 800,
|
||||||
|
footer: null,
|
||||||
|
closable: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderTitie() {
|
function renderTitie() {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex' }}>
|
<div style={{ display: 'flex' }}>
|
||||||
@ -81,6 +133,18 @@ const UserCenter: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<strong style={{ fontSize: 24, color: "goldenrod" }}>{initialState?.currentUser?.affiliateCode}</strong>
|
<strong style={{ fontSize: 24, color: "goldenrod" }}>{initialState?.currentUser?.affiliateCode}</strong>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={3} style={{ minWidth: 100 }}>
|
||||||
|
<div>
|
||||||
|
<span>软件控制权限</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
badgeCount > 0 ? <Badge count={badgeCount}>
|
||||||
|
<Button variant="filled" color="default" onClick={ApplyUserSoftwareControlHandle}> 申请</Button>
|
||||||
|
</Badge> : <Button variant="filled" color="default" onClick={ApplyUserSoftwareControlHandle}> 申请</Button>
|
||||||
|
}
|
||||||
|
<Button color="primary" variant="filled" style={{ marginLeft: 10 }} onClick={ShowSoftwareControlHandle} > 查看</Button>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
103
src/pages/User/UserCenter/UserSoftwareInfo.tsx
Normal file
103
src/pages/User/UserCenter/UserSoftwareInfo.tsx
Normal file
@ -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<SoftwareModel.SoftwareControlBase>['columns'] = [
|
||||||
|
{
|
||||||
|
title: '软件代码',
|
||||||
|
dataIndex: 'software',
|
||||||
|
width: 100,
|
||||||
|
key: 'softwareCode',
|
||||||
|
render: (software) => <span> {software.softwareCode}</span >
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '软件名称',
|
||||||
|
dataIndex: 'software',
|
||||||
|
key: 'softwareName',
|
||||||
|
render: (software) => <span>{software.softwareName}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 ? <Tag color="green">是</Tag> : <Tag color="red">否</Tag>,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
interface UserSoftwareInfoProps {
|
||||||
|
userId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const UserSoftwareInfo: React.FC<UserSoftwareInfoProps> = ({ userId }) => {
|
||||||
|
const [data, setData] = React.useState<SoftwareModel.SoftwareControlBase[]>([]);
|
||||||
|
const [loading, setLoading] = React.useState<boolean>(false);
|
||||||
|
const [messageApi, messageHolder] = message.useMessage();
|
||||||
|
const [tableParams, setTableParams] = useState<TableModel.TableParams>({
|
||||||
|
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<string, FilterValue | null>, sorter: SorterResult<SoftwareModel.SoftwareControlBase> | SorterResult<SoftwareModel.SoftwareControlBase>[], extra: TableCurrentDataSource<SoftwareModel.SoftwareControlBase>): Promise<void> {
|
||||||
|
await QueryUserSoftwareControlCollection();
|
||||||
|
setTableParams({
|
||||||
|
pagination: {
|
||||||
|
...tableParams.pagination,
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table<SoftwareModel.SoftwareControlBase> columns={columns} dataSource={data} rowKey={(record) => record.id} pagination={tableParams.pagination} onChange={TableChangeHandle} loading={loading} />
|
||||||
|
{messageHolder}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserSoftwareInfo;
|
||||||
@ -4,11 +4,13 @@ import { QueryRoleOption } from "@/services/services/role";
|
|||||||
import { QueryUserList } from "@/services/services/user";
|
import { QueryUserList } from "@/services/services/user";
|
||||||
import { FormatDate } from "@/util/time";
|
import { FormatDate } from "@/util/time";
|
||||||
import { useAccess, useModel } from "@umijs/max";
|
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 { ColumnsType, TablePaginationConfig } from "antd/es/table";
|
||||||
import { FilterValue, SorterResult, TableCurrentDataSource } from "antd/es/table/interface";
|
import { FilterValue, SorterResult, TableCurrentDataSource } from "antd/es/table/interface";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import ModifyUser from "../ModifyUser";
|
import ModifyUser from "../ModifyUser";
|
||||||
|
import { DeleteOutlined, EditOutlined, MenuOutlined, SyncOutlined } from "@ant-design/icons";
|
||||||
|
import { SoftwareControl } from "@/services/services/software";
|
||||||
|
|
||||||
const UserManagement: React.FC = () => {
|
const UserManagement: React.FC = () => {
|
||||||
type TagRender = SelectProps['tagRender'];
|
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<UserModel.UserCollection> = [
|
const columns: ColumnsType<UserModel.UserCollection> = [
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
@ -200,17 +229,48 @@ const UserManagement: React.FC = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: '120px',
|
width: '80px',
|
||||||
|
hidden: !access.isAdminOrSuperAdmin,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<div style={{ display: "flex" }}>
|
<Dropdown
|
||||||
<Button hidden={!access.canEditUser} size='small' style={{ marginRight: 5 }} type="primary" onClick={() => {
|
menu={{
|
||||||
setUserId(record.id);
|
items: [
|
||||||
setOpenModal(true);
|
{
|
||||||
}}>编辑</Button>
|
key: 'edit',
|
||||||
<Button hidden={!access.canDeleteUser} danger size='small' type="primary" onClick={() => {
|
label: '编辑',
|
||||||
messageApi.error("暂不支持删除用户");
|
icon: <EditOutlined />,
|
||||||
}} >删除</Button>
|
hidden: !access.canEditUser,
|
||||||
</div>
|
primary: true,
|
||||||
|
onClick: () => {
|
||||||
|
setUserId(record.id);
|
||||||
|
setOpenModal(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'apply',
|
||||||
|
label: '初始化权限',
|
||||||
|
icon: <SyncOutlined />,
|
||||||
|
hidden: !access.canApplySoftwareControl,
|
||||||
|
primary: true,
|
||||||
|
onClick: async () => {
|
||||||
|
await ApplySoftwareControlHandle(record.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'delete',
|
||||||
|
label: '删除',
|
||||||
|
icon: <DeleteOutlined />,
|
||||||
|
hidden: !access.canDeleteUser,
|
||||||
|
danger: true,
|
||||||
|
onClick: () => {
|
||||||
|
messageApi.error("暂不支持删除用户");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
].filter(item => !item.hidden)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button color="primary" variant="filled" icon={<MenuOutlined />} />
|
||||||
|
</Dropdown>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -101,33 +101,25 @@ export const errorConfig: RequestConfig = {
|
|||||||
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
|
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
|
||||||
const { status } = error.response;
|
const { status } = error.response;
|
||||||
if (status === 401) {
|
if (status === 401) {
|
||||||
console.log('401 error', url);
|
|
||||||
if (url.toLowerCase().includes('/refreshtoken')) {
|
if (url.toLowerCase().includes('/refreshtoken')) {
|
||||||
console.log('refresh token error');
|
|
||||||
message.error('登录已过期,请重新登录');
|
message.error('登录已过期,请重新登录');
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
localStorage.removeItem('userInfo');
|
localStorage.removeItem('userInfo');
|
||||||
history.push('/user/login');
|
history.push('/user/login');
|
||||||
} else {
|
} else {
|
||||||
console.log('normal 401 error, try to refresh token');
|
|
||||||
// 尝试刷新 token
|
// 尝试刷新 token
|
||||||
const refreshSuccess = await refreshToken();
|
const refreshSuccess = await refreshToken();
|
||||||
console.log('refresh token result', refreshSuccess);
|
|
||||||
if (refreshSuccess) {
|
if (refreshSuccess) {
|
||||||
console.log('refresh token success, retry request');
|
|
||||||
// 刷新成功,重试原请求
|
// 刷新成功,重试原请求
|
||||||
// 这里需要实现重试逻辑,可能需要修改您的请求库
|
// 这里需要实现重试逻辑,可能需要修改您的请求库
|
||||||
message.success('已重新获取授权,正在重试请求');
|
message.success('已重新获取授权,正在重试请求');
|
||||||
// 刷新成功,重试原请求
|
// 刷新成功,重试原请求
|
||||||
try {
|
try {
|
||||||
console.log('retry request', opts);
|
|
||||||
const retryResponse = await retryRequest(url, opts);
|
const retryResponse = await retryRequest(url, opts);
|
||||||
// 如果重试成功,返回重试的响应
|
// 如果重试成功,返回重试的响应
|
||||||
console.log('retry success', retryResponse);
|
|
||||||
return retryResponse;
|
return retryResponse;
|
||||||
} catch (retryError) {
|
} catch (retryError) {
|
||||||
console.log('retry error', retryError);
|
|
||||||
message.error('重试请求失败,请重新登录');
|
message.error('重试请求失败,请重新登录');
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
@ -136,7 +128,6 @@ export const errorConfig: RequestConfig = {
|
|||||||
}
|
}
|
||||||
// 重试原请求的逻辑
|
// 重试原请求的逻辑
|
||||||
} else {
|
} else {
|
||||||
console.log('refresh token failed');
|
|
||||||
// 刷新失败,重定向到登录页面
|
// 刷新失败,重定向到登录页面
|
||||||
message.error('授权已过期,请重新登录');
|
message.error('授权已过期,请重新登录');
|
||||||
localStorage.removeItem('token');
|
localStorage.removeItem('token');
|
||||||
|
|||||||
@ -65,7 +65,6 @@ export class TokenStorage {
|
|||||||
const request = objectStore.put({ id: 'token', value: token });
|
const request = objectStore.put({ id: 'token', value: token });
|
||||||
|
|
||||||
transaction.oncomplete = () => {
|
transaction.oncomplete = () => {
|
||||||
console.log('Token saved');
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,7 +85,6 @@ export class TokenStorage {
|
|||||||
request.onsuccess = (event) => {
|
request.onsuccess = (event) => {
|
||||||
const result = (event.target as IDBRequest).result;
|
const result = (event.target as IDBRequest).result;
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log('Token:', result.value);
|
|
||||||
let claims: any = null;
|
let claims: any = null;
|
||||||
if (result.value) {
|
if (result.value) {
|
||||||
const decodedToken = jwtDecode(result.value);
|
const decodedToken = jwtDecode(result.value);
|
||||||
@ -100,7 +98,6 @@ export class TokenStorage {
|
|||||||
}
|
}
|
||||||
resolve(claims);
|
resolve(claims);
|
||||||
} else {
|
} else {
|
||||||
console.log('Token not found');
|
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -122,10 +119,8 @@ export class TokenStorage {
|
|||||||
request.onsuccess = (event) => {
|
request.onsuccess = (event) => {
|
||||||
const result = (event.target as IDBRequest).result;
|
const result = (event.target as IDBRequest).result;
|
||||||
if (result) {
|
if (result) {
|
||||||
console.log('Token:', result.value);
|
|
||||||
resolve(result.value);
|
resolve(result.value);
|
||||||
} else {
|
} else {
|
||||||
console.log('Token not found');
|
|
||||||
reject(new Error("Token not found"));
|
reject(new Error("Token not found"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -145,7 +140,6 @@ export class TokenStorage {
|
|||||||
const request = objectStore.delete('token');
|
const request = objectStore.delete('token');
|
||||||
|
|
||||||
transaction.oncomplete = () => {
|
transaction.oncomplete = () => {
|
||||||
console.log('Token deleted');
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,6 @@ async function QueryMachineList(tableParams: TableModel.TableParams, userParams:
|
|||||||
let res = await request<ApiResponse.SuccessItem<MachineModel.QueryMachineData>>(`/lms/Machine/QueryMachineCollection?${query}`, {
|
let res = await request<ApiResponse.SuccessItem<MachineModel.QueryMachineData>>(`/lms/Machine/QueryMachineCollection?${query}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
console.log(QueryMachineList, res)
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -59,7 +58,6 @@ async function GetMachineInfo(id: string): Promise<MachineModel.MachineInfo> {
|
|||||||
let res = await request<ApiResponse.SuccessItem<MachineModel.MachineInfo>>(`/lms/Machine/GetMachineDetail/${id}`, {
|
let res = await request<ApiResponse.SuccessItem<MachineModel.MachineInfo>>(`/lms/Machine/GetMachineDetail/${id}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
console.log("GetMachineInfo", res)
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -77,7 +75,6 @@ async function ModifyMachineData(id: string, params: MachineModel.ModifyMachineP
|
|||||||
...params,
|
...params,
|
||||||
deactivationTime: deactivationTimeString
|
deactivationTime: deactivationTimeString
|
||||||
}
|
}
|
||||||
console.log("ModifyMachineData", params)
|
|
||||||
let res = await request<ApiResponse.SuccessItem<null>>(`/lms/Machine/ModifyMachine/${id}`, {
|
let res = await request<ApiResponse.SuccessItem<null>>(`/lms/Machine/ModifyMachine/${id}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: data
|
data: data
|
||||||
|
|||||||
@ -99,7 +99,6 @@ export async function GetOptions(optionsKey: string): Promise<OptionModel.Option
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("GetTTSOptions", res)
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -120,7 +119,6 @@ export async function SaveOptions(options: object): Promise<void> {
|
|||||||
data.push({ key: key, value: value.toString() });
|
data.push({ key: key, value: value.toString() });
|
||||||
return "";
|
return "";
|
||||||
}, {});
|
}, {});
|
||||||
console.log("SaveOptionsDataParams", data)
|
|
||||||
|
|
||||||
let res = await request<ApiResponse.SuccessItem<boolean>>('/lms/LaitoolOptions/ModifyOptions', {
|
let res = await request<ApiResponse.SuccessItem<boolean>>('/lms/LaitoolOptions/ModifyOptions', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@ -31,7 +31,6 @@ export async function GetPromptInfo(id: string): Promise<Prompt.PromptItem> {
|
|||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
console.log("GetPromptInfo", res.data);
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +41,6 @@ export async function GetPromptInfo(id: string): Promise<Prompt.PromptItem> {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export async function AddPrompt(data: Prompt.PromptItem): Promise<string> {
|
export async function AddPrompt(data: Prompt.PromptItem): Promise<string> {
|
||||||
console.log("AddPrompt", data)
|
|
||||||
let res = await request('/lms/Prompt/AddPrompt', {
|
let res = await request('/lms/Prompt/AddPrompt', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {
|
data: {
|
||||||
@ -104,14 +102,12 @@ export async function DeletePrompt(id: string): Promise<void> {
|
|||||||
*/
|
*/
|
||||||
export async function QueryPromptypeCollection(param: Prompt.PromptTypeQueryCondition): Promise<Prompt.PromptTypeResponse> {
|
export async function QueryPromptypeCollection(param: Prompt.PromptTypeQueryCondition): Promise<Prompt.PromptTypeResponse> {
|
||||||
let query = objectToQueryString(param)
|
let query = objectToQueryString(param)
|
||||||
console.log("query", query)
|
|
||||||
let res = await request<ApiResponse.SuccessItem<Prompt.PromptTypeResponse>>(`/lms/Prompt/QueryPromptypeCollection/?${query}`, {
|
let res = await request<ApiResponse.SuccessItem<Prompt.PromptTypeResponse>>(`/lms/Prompt/QueryPromptypeCollection/?${query}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
console.log("QueryPromptypeCollection", res.data);
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,6 @@ export async function QueryRoleList(tableParams: TableModel.TableParams, rolePar
|
|||||||
let res = await request<ApiResponse.SuccessItem<RoleModel.QueryRoleData>>(`/lms/Role/QueryRoleCollection?${query}`, {
|
let res = await request<ApiResponse.SuccessItem<RoleModel.QueryRoleData>>(`/lms/Role/QueryRoleCollection?${query}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
console.log("QueryRoleList", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -35,7 +34,6 @@ export async function QueryRoleOption() {
|
|||||||
let res = await request<ApiResponse.SuccessItem<string[]>>(`/lms/Role/QueryRoleOption`, {
|
let res = await request<ApiResponse.SuccessItem<string[]>>(`/lms/Role/QueryRoleOption`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
console.log("QueryRoleOption", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -49,11 +47,9 @@ export async function QueryRoleOption() {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export async function GetRoleById(roleId: number): Promise<RoleModel.Collection> {
|
export async function GetRoleById(roleId: number): Promise<RoleModel.Collection> {
|
||||||
console.log("GetRoleById", roleId);
|
|
||||||
let res = await request<ApiResponse.SuccessItem<RoleModel.Collection>>(`/lms/Role/QueryRoleById/${roleId}`, {
|
let res = await request<ApiResponse.SuccessItem<RoleModel.Collection>>(`/lms/Role/QueryRoleById/${roleId}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
console.log("GetRoleByIdRes", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -74,7 +70,6 @@ export async function UpdeteRole(roleId: number, roleName: string, roleRemark: s
|
|||||||
remark: roleRemark
|
remark: roleRemark
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("UpdeteRole", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -89,7 +84,6 @@ export async function DeleteRoleById(roleId: number): Promise<void> {
|
|||||||
let res = await request<ApiResponse.SuccessItem<void>>(`/lms/Role/DeleteRole/${roleId}`, {
|
let res = await request<ApiResponse.SuccessItem<void>>(`/lms/Role/DeleteRole/${roleId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
console.log("DeleteRole", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
@ -111,7 +105,6 @@ export async function AddRole(roleNmae: string, roleRemark: string): Promise<voi
|
|||||||
remark: roleRemark
|
remark: roleRemark
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("AddRole", res);
|
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
|
|||||||
94
src/services/services/software.ts
Normal file
94
src/services/services/software.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
import { request } from '@umijs/max';
|
||||||
|
import { objectToQueryString } from './common';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户的软件控制权限数量
|
||||||
|
* @param userId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function GetUserSoftwareControlCount(userId: number) {
|
||||||
|
let res = await request<ApiResponse.SuccessItem<number>>(`/lms/SoftWare/GetUserSoftwareControlCount/${userId}`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
if (res.code == 1) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请指定的用户的软件控制权限
|
||||||
|
* @param userId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function ApplyUserSoftwareControl(userId: number) {
|
||||||
|
let res = await request<ApiResponse.SuccessItem<boolean>>(`/lms/SoftWare/ApplySoftwareControl/${userId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
if (res.code == 1) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定用户的软件控制权限列表
|
||||||
|
* @param tableParams 表数据参数
|
||||||
|
* @param queryParams 查询参数
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function GetUserSoftwareControlCollection(tableParams: TableModel.TableParams, queryParams: SoftwareModel.SoftwareControlQueryParams) {
|
||||||
|
let data = {
|
||||||
|
...queryParams,
|
||||||
|
page: tableParams.pagination?.current,
|
||||||
|
pageSize: tableParams.pagination?.pageSize,
|
||||||
|
}
|
||||||
|
let query = objectToQueryString(data)
|
||||||
|
let res = await request<ApiResponse.SuccessItem<SoftwareModel.QuerySoftwareControlData>>(`/lms/SoftWare/GetSoftwareControlCollection?${query}`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
if (res.code != 1) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function AddSoftwareControlExpirationTime(id: string, days: number, isForever: boolean) {
|
||||||
|
let res = await request<ApiResponse.SuccessItem<null>>(`/lms/SoftWare/ModifySoftwareControlValidity/${id}`, {
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
expirationTime: days,
|
||||||
|
isForever: isForever
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (res.code != 1) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SoftwareControl = {
|
||||||
|
GetUserSoftwareControlCount,
|
||||||
|
ApplyUserSoftwareControl,
|
||||||
|
GetUserSoftwareControlCollection,
|
||||||
|
AddSoftwareControlExpirationTime
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取软件初始信息的集合
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function GetSoftwareBaseCollection() {
|
||||||
|
let res = await request<ApiResponse.SuccessItem<SoftwareModel.SoftwareBasicInfo[]>>(`/lms/SoftWare/GetSoftwareBaseCollection`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
if (res.code == 1) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Software = {
|
||||||
|
GetSoftwareBaseCollection
|
||||||
|
}
|
||||||
@ -74,7 +74,6 @@ async function QueryUserList(tableParams: TableModel.TableParams, userParams: Us
|
|||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
throw new Error(res.message);
|
throw new Error(res.message);
|
||||||
}
|
}
|
||||||
console.log("QueryUserList", res);
|
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/services/typing/access.d.ts
vendored
13
src/services/typing/access.d.ts
vendored
@ -20,9 +20,9 @@ declare namespace AccessType {
|
|||||||
|
|
||||||
//#region 软件配置项操作权限
|
//#region 软件配置项操作权限
|
||||||
/** 是不是可以操作配置型 */
|
/** 是不是可以操作配置型 */
|
||||||
canOptions : boolean;
|
canOptions: boolean;
|
||||||
/** 是不是可以操作软件配置项 */
|
/** 是不是可以操作软件配置项 */
|
||||||
canLaitoolOptions : boolean;
|
canLaitoolOptions: boolean;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region 机器权限
|
//#region 机器权限
|
||||||
@ -39,5 +39,14 @@ declare namespace AccessType {
|
|||||||
/** 是不是有停用机器码的权限 */
|
/** 是不是有停用机器码的权限 */
|
||||||
canDisableMachine: boolean;
|
canDisableMachine: boolean;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
//#region 软件控制权限
|
||||||
|
|
||||||
|
/** 是否可以同步用户软件控制权限 */
|
||||||
|
canApplySoftwareControl: boolean;
|
||||||
|
/** 是否可以查看软件控制管理 */
|
||||||
|
canSofrwareControlManagement: boolean;
|
||||||
|
//#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
47
src/services/typing/software.d.ts
vendored
Normal file
47
src/services/typing/software.d.ts
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
declare namespace SoftwareModel {
|
||||||
|
|
||||||
|
interface SoftwareBasicInfo {
|
||||||
|
id: string;
|
||||||
|
softwareName: string;
|
||||||
|
softwareCode: string;
|
||||||
|
isUse: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SoftwareBase {
|
||||||
|
id: string;
|
||||||
|
softwareName: string;
|
||||||
|
softwareCode: string;
|
||||||
|
createdUserId: number;
|
||||||
|
updatedUserId: number;
|
||||||
|
createdTime: Date;
|
||||||
|
updatedTime: Date;
|
||||||
|
remark: string;
|
||||||
|
isUse: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SoftwareControlBase {
|
||||||
|
id: string;
|
||||||
|
user: UserModel.UserBasic;
|
||||||
|
software: SoftwareBase;
|
||||||
|
createdUser: UserModel.UserBasic;
|
||||||
|
createdTime: Date;
|
||||||
|
updatedUser: UserModel.UserBasic;
|
||||||
|
updatedTime: Date;
|
||||||
|
remark: string;
|
||||||
|
expirationTime: string;
|
||||||
|
isForever: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SoftwareControlQueryParams = {
|
||||||
|
userId?: number;
|
||||||
|
softwareId?: string;
|
||||||
|
isForever?: boolean;
|
||||||
|
remark?: string
|
||||||
|
};
|
||||||
|
|
||||||
|
type QuerySoftwareControlData = {
|
||||||
|
collection: SoftwareControlBase[];
|
||||||
|
current: number;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user