修改请求重试,修改所有的request方法
添加部分权限控制
完善软件授权码设置
This commit is contained in:
2025-05-16 17:51:58 +08:00
parent e448cf6c6b
commit 79479bfdc5
36 changed files with 954 additions and 351 deletions
@@ -243,7 +243,7 @@ const MachineManagement: React.FC = () => {
];
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<Spin spinning={spinning} tip={spinTip}>
<Form
layout='inline'
@@ -28,6 +28,7 @@ const ModifyMachine: React.FC<ModifyMachineProps> = ({ id, setFormRef, open }) =
setSpinning(true);
setSpinTip("加载中。。。");
GetMachineInfo(id).then((res) => {
debugger
// 对一些数据做处理
form.setFieldsValue({
...res,
@@ -37,6 +38,7 @@ const ModifyMachine: React.FC<ModifyMachineProps> = ({ id, setFormRef, open }) =
ownUserName: res.ownUser?.userName,
updatedUserName: res.updatedUser?.userName,
deactivationTime: res.deactivationTime ? moment(res.deactivationTime) : undefined,
id: id
});
}).catch((error: any) => {
@@ -24,7 +24,7 @@ const LaitoolOptions: React.FC = () => {
}]
return (
<TemplateContainer title={false} navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer title={false} navTheme={initialState?.settings?.navTheme ?? "light"}>
<Tabs defaultActiveKey="1" destroyInactiveTabPane={true} items={items} />
</TemplateContainer>
);
@@ -4,7 +4,7 @@ import { MailOutlined } from '@ant-design/icons';
import { useSoftStore } from '@/store/software';
import { GetOptions, getOptionsValue, GetSimpleOptions, SaveOptions } from '@/services/services/options/optionsTool';
import { AllOptionKeyName, OptionKeyName } from '@/services/enum/optionEnum';
import { request } from '@umijs/max';
import cusRequest from '@/request';
interface MailSettingProps {
visible?: boolean;
@@ -94,7 +94,7 @@ const MailSettingOption: React.FC<MailSettingProps> = ({ visible }) => {
setTopSpinTip('正在发送测试邮件');
let res = await request<ApiResponse.SuccessItem<string>>('/lms/LaitoolOptions/TestSendMail', {
let res = await cusRequest<string>('/lms/LaitoolOptions/TestSendMail', {
method: 'POST',
});
+1 -1
View File
@@ -22,7 +22,7 @@ const LaitoolOptions: React.FC = () => {
};
return (
<TemplateContainer title={false} navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer title={false} navTheme={initialState?.settings?.navTheme ?? "light"}>
<Tabs defaultActiveKey="1" destroyInactiveTabPane={true} items={items} onChange={onChange} />
</TemplateContainer>
);
+8 -3
View File
@@ -1,12 +1,13 @@
import React, { useState, useEffect } from 'react';
import { Table, Button, message, Space, Spin, Form, Input, Select, Modal } from 'antd';
import TemplateContainer from '@/pages/TemplateContainer';
import { request, useModel } from '@umijs/max';
import { useModel } from '@umijs/max';
import { objectToQueryString } from '@/services/services/common';
import { GetDataInfoTypeOption, GetDataInfoTypeOptions } from '@/services/enum/dataInfo';
import { SearchOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/lib/table';
import JsonView from '@uiw/react-json-view';
import cusRequest from '@/request';
const DataInfo: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false);
@@ -37,13 +38,17 @@ const DataInfo: React.FC = () => {
pageSize: tableParams.pagination?.pageSize,
};
let query = objectToQueryString(data);
let res = await request<ApiResponse.SuccessItem<DataInfoModel.QueryDataInfoData>>(`/lms/Other/QueryDataInfoCollection?${query}`, {
let res = await cusRequest<DataInfoModel.QueryDataInfoData>(`/lms/Other/QueryDataInfoCollection?${query}`, {
method: 'GET',
});
if (res.code != 1) {
throw new Error(res.message);
}
let resData = res.data;
if (resData?.collection == undefined) {
messageApi.error('请求获取数据为空,请重试!');
return;
}
setDataList(resData.collection);
setTableParams({
pagination: {
@@ -140,7 +145,7 @@ const DataInfo: React.FC = () => {
];
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? 'realDark'}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? 'light'}>
<Spin spinning={loading}>
<Form
form={form}
@@ -1,20 +1,20 @@
import React, { useEffect, useState } from 'react';
import { Form, Input, DatePicker, Select, Button, message, FormInstance } from 'antd';
import { Form, Input, DatePicker, Select, Button, message, FormInstance, Space } from 'antd';
import moment from 'moment';
import { useNavigate } from 'react-router-dom';
import { GetMachineAuthorizationTypeOptions } from '@/services/enum/machineAuthorizationEnum';
const { TextArea } = Input;
import CryptoJS from 'crypto-js'; // 添加这一行导入
import * as LZString from 'lz-string';
import { request } from '@umijs/max';
import cusRequest from '@/request';
import { AddMachineIdAuthorizationFunc } from '@/services/services/other';
interface AddMachineIdAuthorizationProps {
setFormRef: (form: FormInstance) => void;
id: string;
}
const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ setFormRef, id }) => {
const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ setFormRef }) => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [messageApi, messageHolder] = message.useMessage();
@@ -22,33 +22,21 @@ const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ s
useEffect(() => {
setFormRef(form);
form.setFieldsValue({
authorizedDate: moment(),
expiryDate: moment().add(1, 'year'),
type: 0,
authorizationCode: '123'
useType: 0,
expiryTime: 365,
authorizationCode: ""
})
}, [form, setFormRef, id]);
}, [form, setFormRef]);
const handleSubmit = async () => {
try {
setLoading(true);
// TODO: Implement API call to save the authorization
let values = form.getFieldsValue();
console.log('Form values:', values);
let res = await request<ApiResponse.SuccessItem<string>>('lms/Other/AddMachineAuthorization', {
method: "POST",
data: {
...values,
authorizedDate: values.authorizedDate.toISOString(),
expiryDate: values.expiryDate.toISOString()
}
})
if (res.code !== 1) {
throw new Error(res.message);
}
await AddMachineIdAuthorizationFunc(values);
messageApi.success('Machine ID authorization added successfully');
} catch (error : any) {
} catch (error: any) {
messageApi.error(error.message);
} finally {
setLoading(false);
@@ -167,13 +155,7 @@ const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ s
onFinish={handleSubmit}
autoComplete="off"
>
<Form.Item
name="machineId"
label="机器码/唯一授权码"
rules={[{ required: true, message: '请输入 machine ID' }]}
>
<Input placeholder="输入 machine ID" />
</Form.Item>
<Form.Item
name="type"
@@ -183,12 +165,23 @@ const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ s
<Select placeholder="选择授权软件类型" options={GetMachineAuthorizationTypeOptions()}></Select>
</Form.Item>
<Form.Item
name="useType"
label="授权使用类型"
rules={[{ required: true, message: '请输入授权软件类型' }]}
>
<Select placeholder="选择授权软件类型" options={[
{ label: '基础', value: 0 },
{ label: '专业', value: 1 },
]}></Select>
</Form.Item>
<Form.Item
name="authorizedDate"
label="授权时间"
rules={[{ required: true, message: '请选择授权时间' }]}
>
<DatePicker
disabled
showTime
style={{ width: '100%' }}
placeholder="选择授权日期和时间"
@@ -199,9 +192,9 @@ const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ s
<Form.Item
name="expiryDate"
label="到期时间"
rules={[{ required: true, message: '请选择到期时间' }]}
>
<DatePicker
disabled
showTime
style={{ width: '100%' }}
placeholder="选择到期日期和时间"
@@ -209,18 +202,44 @@ const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ s
/>
</Form.Item>
<Form.Item name="authorizationCode" label="请输入授权码">
<TextArea rows={4} placeholder="请输入授权码" />
<Form.Item
name="expiryTime"
label="授权到期时间"
rules={[{ required: true, message: '请选择授权到期时间' }]}
>
<Select
placeholder="请选择授权时间"
showSearch
allowClear
optionFilterProp="children"
options={[
{ label: '0天', value: 0 },
{ label: '30天', value: 30 },
{ label: '90天', value: 90 },
{ label: '180天', value: 180 },
{ label: '365天', value: 365 },
]}
/>
</Form.Item>
<Form.Item name="authorizationCode" label="授权码"
rules={[{ required: true, message: '请先生成授权码' }]}
>
<Space.Compact style={{ width: '100%' }}>
<Input
placeholder="授权码将显示在这里"
/>
<Button
type="primary"
onClick={GenerateAuthorizationCode}
>
</Button>
</Space.Compact>
</Form.Item>
<Form.Item style={{ textAlign: 'right' }}>
<Button
style={{ marginRight: 8 }}
type="primary"
onClick={GenerateAuthorizationCode}
>
</Button>
<Button
style={{ marginRight: 8 }}
type="primary"
@@ -0,0 +1,283 @@
import React, { useEffect, useState } from 'react';
import { Form, Input, DatePicker, Select, Button, message, FormInstance, Space } from 'antd';
import moment from 'moment';
import { useNavigate } from 'react-router-dom';
import { GetMachineAuthorizationTypeOptions } from '@/services/enum/machineAuthorizationEnum';
const { TextArea } = Input;
import CryptoJS from 'crypto-js'; // 添加这一行导入
import * as LZString from 'lz-string';
import cusRequest from '@/request';
import { FormatDate } from '@/util/time';
import { GetMachineAuthorizationById, ModifyMachineAuthorization } from '@/services/services/other';
interface ModifyMachineIdAuthorizationProps {
setFormRef: (form: FormInstance) => void;
id: string;
}
const ModifyMachineIdAuthorization: React.FC<ModifyMachineIdAuthorizationProps> = ({ setFormRef, id }) => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [messageApi, messageHolder] = message.useMessage();
useEffect(() => {
setFormRef(form);
getMachineAuthorizationById(id);
}, [form, setFormRef, id]);
// 先获取数据
const getMachineAuthorizationById = async (id: string) => {
try {
debugger
let data = await GetMachineAuthorizationById(id);
form.setFieldsValue({
...data,
// 使用 moment 对象而不是格式化字符串
authorizedDate: data.authorizedDate ? moment(data.authorizedDate) : null,
expiryDate: data.expiryDate ? moment(data.expiryDate) : null,
});
} catch (error) {
messageApi.error('获取数据失败');
}
}
const handleSubmit = async () => {
try {
debugger
setLoading(true);
let values = form.getFieldsValue();
await ModifyMachineAuthorization(id, values);
messageApi.success('Machine ID authorization added successfully');
} catch (error: any) {
messageApi.error(error.message);
} finally {
setLoading(false);
}
};
function GenerateAuthorizationCode() {
const values = form.getFieldsValue();
const { machineId, type, authorizedDate, expiryDate } = values;
if (!machineId || type === undefined || !authorizedDate || !expiryDate) {
messageApi.error('请先填写必要信息(机器码、类型和日期)');
return;
}
try {
// Format dates to strings
const authDate = moment(authorizedDate).format('YYYY-MM-DD HH:mm:ss');
const expDate = moment(expiryDate).format('YYYY-MM-DD HH:mm:ss');
let obj = {
machineId: machineId,
type: type,
authorizedDate: authDate,
expiryDate: expDate
}
// Create the string to encrypt
const dataToEncrypt = JSON.stringify(obj);
// Assuming CryptoJS is imported
const secretKey = machineId;
// Generate a secure encryption key from machineId
const key = CryptoJS.enc.Utf8.parse(CryptoJS.SHA256(secretKey).toString());
// Generate a random initialization vector
const iv = CryptoJS.lib.WordArray.random(16);
// Encrypt the data using AES encryption
const encrypted = CryptoJS.AES.encrypt(dataToEncrypt, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// Convert IV to base64 for storage
const ivBase64 = CryptoJS.enc.Base64.stringify(iv);
// Get the encrypted data in base64 format
const encryptedBase64 = encrypted.toString();
// Combine IV and encrypted data with a delimiter for future decryption
const authCode = ivBase64 + ':' + encryptedBase64;
// 使用LZString压缩
const compressedCode = LZString.compressToEncodedURIComponent(authCode);
// Set the encrypted value in the form
form.setFieldsValue({ authorizationCode: compressedCode });
messageApi.success('授权码已生成');
} catch (error) {
console.error('生成授权码时出错:', error);
messageApi.error('生成授权码失败');
}
}
function DecryptAuthorizationCode(authCode: string, machineId: string) {
try {
// 解压缩
const originalAuthCode = LZString.decompressFromEncodedURIComponent(authCode);
// 拆分授权码,获取IV和加密数据
const [ivBase64, encryptedBase64] = originalAuthCode.split(':');
if (!ivBase64 || !encryptedBase64) {
throw new Error('无效的授权码格式');
}
// 从Base64转换回IV
const iv = CryptoJS.enc.Base64.parse(ivBase64);
// 使用相同的方法生成密钥
const secretKey = machineId;
const key = CryptoJS.enc.Utf8.parse(CryptoJS.SHA256(secretKey).toString());
// 解密数据
const decrypted = CryptoJS.AES.decrypt(encryptedBase64, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 将解密后的数据转换为字符串
const decryptedData = decrypted.toString(CryptoJS.enc.Utf8);
// 将JSON字符串解析为对象
const decodedObject = JSON.parse(decryptedData);
return {
success: true,
data: decodedObject
};
} catch (error) {
console.error('解密授权码时出错:', error);
return {
success: false,
error: error instanceof Error ? error.message : '未知错误'
};
}
}
return (
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
autoComplete="off"
>
<Form.Item
name="type"
label="授权软件类型"
rules={[{ required: true, message: '请输入授权软件类型' }]}
>
<Select placeholder="选择授权软件类型" options={GetMachineAuthorizationTypeOptions()}></Select>
</Form.Item>
<Form.Item
name="useType"
label="授权使用类型"
rules={[{ required: true, message: '请输入授权软件类型' }]}
>
<Select placeholder="选择授权软件类型" options={[
{ label: '基础', value: 0 },
{ label: '专业', value: 1 },
]}></Select>
</Form.Item>
<Form.Item
name="authorizedDate"
label="授权时间"
>
<DatePicker
disabled
showTime
style={{ width: '100%' }}
placeholder="选择授权日期和时间"
/>
</Form.Item>
<Form.Item
name="expiryDate"
label="到期时间"
>
<DatePicker
showTime
style={{ width: '100%' }}
placeholder="选择到期日期和时间"
/>
</Form.Item>
<Form.Item
name="expiryTime"
label="授权到期时间"
rules={[{ required: true, message: '请选择授权到期时间' }]}
>
<Select
placeholder="请选择授权时间"
showSearch
allowClear
optionFilterProp="children"
options={[
{ label: '0天', value: 0 },
{ label: '30天', value: 30 },
{ label: '90天', value: 90 },
{ label: '180天', value: 180 },
{ label: '365天', value: 365 },
]}
/>
</Form.Item>
<Form.Item name="authorizationCode" label="授权码"
rules={[{ required: true, message: '请先生成授权码' }]}
>
<Input
placeholder="授权码将显示在这里"
/>
</Form.Item>
<Form.Item name="machineID" label="机器码/唯一标识"
>
<Input
placeholder="授权码将显示在这里"
/>
</Form.Item>
<Form.Item style={{ textAlign: 'right' }}>
<Button
style={{ marginRight: 8 }}
type="primary"
onClick={() => {
const values = form.getFieldsValue();
const { machineId, authorizationCode } = values;
if (!machineId || !authorizationCode) {
messageApi.error('请先填写机器码和授权码');
return;
}
const result = DecryptAuthorizationCode(authorizationCode, machineId);
if (result.success) {
messageApi.success('授权码解密成功');
console.log('解密结果:', result.data);
} else {
messageApi.error(`解密失败: ${result.error}`);
}
}}
>
</Button>
<Button type="primary" htmlType="submit" loading={loading}>
</Button>
</Form.Item>
{messageHolder}
</Form >
);
};
export default ModifyMachineIdAuthorization;
+168 -93
View File
@@ -1,14 +1,18 @@
import React, { useState, useEffect } from 'react';
import { Table, Button, Space, Input, Form, Modal, message, Popconfirm, Tooltip, Select } from 'antd';
import { Table, Button, Space, Input, Form, Modal, message, Popconfirm, Tooltip, Select, Checkbox, Tag } from 'antd';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
import TemplateContainer from '@/pages/TemplateContainer';
import { request, useModel } from '@umijs/max';
import { useModel } from '@umijs/max';
import { ColumnsType, FilterValue, SorterResult, TableCurrentDataSource, TablePaginationConfig } from 'antd/es/table/interface';
import { objectToQueryString } from '@/services/services/common';
import { FormatDate } from '@/util/time';
import { GetMachineAuthorizationTypeOption, GetMachineAuthorizationTypeOptions } from '@/services/enum/machineAuthorizationEnum';
import { useFormReset } from '@/hooks/useFormReset';
import AddMachineIdAuthorization from './AddMachineIdAuthorization';
import cusRequest from '@/request';
import { isEmpty } from 'lodash';
import ModifyMachineIdAuthorization from './ModifyMachineIdAuthorization';
import { BatchDeleteMachine, DeleteMachineAuthorization, QueryMachineAuthorization } from '@/services/services/other';
const MachineIdAuthorization: React.FC = () => {
@@ -17,7 +21,8 @@ const MachineIdAuthorization: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false);
const [modalVisible, setModalVisible] = useState<boolean>(false);
const [form] = Form.useForm();
const [messageApi, messageHolder] = message.useMessage();
const [messageApi, messageHolder,] = message.useMessage();
const [modalApi, modalHolder] = Modal.useModal();
const { setFormRef, resetForm } = useFormReset();
const [id, setId] = useState<string>('');
const [tableParams, setTableParams] = useState<TableModel.TableParams>({
@@ -33,23 +38,11 @@ const MachineIdAuthorization: React.FC = () => {
QueryMachineAuthorizationCollection(tableParams, form.getFieldsValue());
}, []);
// 查询数据
async function QueryMachineAuthorizationCollection(tableParams: TableModel.TableParams, options?: any) {
try {
setLoading(true);
let data = {
...options,
page: tableParams.pagination?.current,
pageSize: tableParams.pagination?.pageSize,
}
let query = objectToQueryString(data)
let res = await request<ApiResponse.SuccessItem<MachineAuthorizationModel.QueryMachineAuthorizationData>>(`/lms/Other/QueryMachineAuthorizationCollection?${query}`, {
method: 'GET',
});
if (res.code != 1) {
throw new Error(res.message);
}
let resData = res.data;
let resData = await QueryMachineAuthorization(tableParams, options);
setDataSource(resData.collection);
setTableParams({
pagination: {
@@ -57,6 +50,7 @@ const MachineIdAuthorization: React.FC = () => {
total: resData.total
}
})
console.log('获取数据成功', resData);
messageApi.success('Data fetched successfully');
} catch (error: any) {
messageApi.error(error.message);
@@ -67,6 +61,17 @@ const MachineIdAuthorization: React.FC = () => {
const columns: ColumnsType<MachineAuthorizationModel.MachineAuthorizationBase> = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: '120px',
render: (text) => (
<Tooltip title={text}>
<span>{text?.length > 10 ? `${text.substring(0, 10)}...` : text}</span>
</Tooltip>
),
fixed: 'left',
}, {
title: '机器码/唯一授权码',
dataIndex: 'machineID',
key: 'machineId',
@@ -77,34 +82,59 @@ const MachineIdAuthorization: React.FC = () => {
</Tooltip>
),
},
{
title: '授权类型',
dataIndex: 'type',
key: 'type',
render: (text, record) => GetMachineAuthorizationTypeOption(record.type),
},
{
title: '授权时间',
dataIndex: 'authorizedDate',
key: 'authorizedDate',
render: (text) => FormatDate(text),
},
{
title: '授权到期时间',
dataIndex: 'expiryDate',
key: 'expiryDate',
render: (text) => FormatDate(text),
},
{
title: '授权码',
dataIndex: 'authorizationCode',
key: 'authorizationCode',
width: '300px',
render: (text) => (
<Tooltip title={text}>
<span>{text?.length > 30 ? `${text.substring(0, 30)}...` : text}</span>
</Tooltip>
),
},
{
title: '授权类型',
dataIndex: 'type',
key: 'type',
width: '80px',
render: (text, record) => GetMachineAuthorizationTypeOption(record.type),
},
{
title: '使用类型',
dataIndex: 'useType',
key: 'useType',
width: '80px',
render: (text, record) => {
return <Tag color={record.useType == 0 ? 'green' : 'blue'}>
{record.useType == 0 ? '基础' : '专业'}
</Tag>
}
},
{
title: '授权时间',
dataIndex: 'expiryTime',
key: 'expiryTime',
width: '80px',
render: (text, record) => <Tag color='success'>
{record.expiryTime + '天'}
</Tag>
},
{
title: '授权时间',
dataIndex: 'authorizedDate',
key: 'authorizedDate',
width: '160px',
render: (text) => FormatDate(text),
},
{
title: '授权到期时间',
dataIndex: 'expiryDate',
key: 'expiryDate',
width: '160px',
render: (text) => FormatDate(text),
},
{
title: '创建人',
dataIndex: 'createdUser',
@@ -113,53 +143,49 @@ const MachineIdAuthorization: React.FC = () => {
const userName = text?.userName || '';
return (
<Tooltip title={userName}>
<span>{userName.length > 10 ? `${userName.substring(0, 10)}...` : userName}</span>
<span>{userName.length > 20 ? `${userName.substring(0, 20)}...` : userName}</span>
</Tooltip>
);
}
},
{
title: '创建时间',
dataIndex: 'createdDate',
key: 'createdDate',
render: (text, record) => FormatDate(record.createdDate),
},
{
title: 'Actions',
key: 'actions',
render: (_, record) => (
<Space>
<Button type="link" onClick={() => handleEdit(record)}>
Edit
<Button color="primary" variant="text" onClick={() => handleEdit(record)}>
</Button>
<Popconfirm
title="Are you sure you want to revoke this authorization?"
onConfirm={() => handleRevoke(record.id)}
okText="Yes"
cancelText="No"
title="确定要删除当前的授权吗?"
description="删除后将无法恢复,请谨慎操作!"
onConfirm={() => handleDelete(record.id)}
okText="继续"
cancelText="取消"
>
<Button type="link" danger>
Revoke
<Button color="danger" variant="text">
</Button>
</Popconfirm>
</Space>
),
fixed: 'right',
},
];
const handleEdit = (record: MachineAuthorizationModel.MachineAuthorizationBase) => {
setModalVisible(true);
setId(record.id);
};
const handleRevoke = async (id: string) => {
// 单个删除
const handleDelete = async (id: string) => {
try {
const newData = dataSource.map(item =>
item.id === id ? { ...item, status: 'revoked' as const } : item
);
setDataSource(newData);
messageApi.success('Authorization revoked successfully');
} catch (error) {
messageApi.error('Failed to revoke authorization');
await DeleteMachineAuthorization(id);
await QueryMachineAuthorizationCollection(tableParams, form.getFieldsValue());
messageApi.success('删除成功');
} catch (error: any) {
messageApi.error(error.message);
}
};
@@ -168,6 +194,28 @@ const MachineIdAuthorization: React.FC = () => {
setModalVisible(true);
};
//
const handleBatchDelete = async () => {
try {
const confirmed = await modalApi.confirm({
title: "确认批量删除",
content: "确定需要批量删除?该操作会删除所有授权到期的机器码授权,请谨慎操作!",
okText: "继续",
});
if (!confirmed) {
messageApi.warning('取消操作');
return;
}
// 开始删除
await BatchDeleteMachine();
messageApi.success('批量删除成功');
// 重新加载数据\
await QueryMachineAuthorizationCollection(tableParams, form.getFieldsValue());
} catch (error: any) {
messageApi.error(error.message);
}
};
async function TableChangeHandle(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>, sorter: SorterResult<MachineAuthorizationModel.MachineAuthorizationBase> | SorterResult<MachineAuthorizationModel.MachineAuthorizationBase>[], extra: TableCurrentDataSource<MachineAuthorizationModel.MachineAuthorizationBase>): Promise<void> {
await QueryMachineAuthorizationCollection({ pagination }, form.getFieldsValue());
@@ -189,45 +237,66 @@ const MachineIdAuthorization: React.FC = () => {
}
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<Form
form={form}
layout="inline"
onFinish={(values) => QueryMachineAuthorizationCollection(tableParams, values)}
style={{ marginBottom: 16 }}
style={{ marginBottom: 8 }}
>
<Form.Item name="machineID" label="机器码">
<Input placeholder="Machine ID" style={{ width: 200 }} />
</Form.Item>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '16px', alignItems: 'flex-end' }}>
<Form.Item name="ID" label="id">
<Input placeholder="ID" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="machineID" label="机器码">
<Input placeholder="Machine ID" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="emptyMachineId" valuePropName="checked">
<Checkbox></Checkbox>
</Form.Item>
<Form.Item name="authorizationCode" label="授权码">
<Input placeholder="Authorization Code" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="type" label="授权类型">
<Select
placeholder="Authorization Type"
style={{ width: 180 }}
allowClear
options={GetMachineAuthorizationTypeOptions()}
/>
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
</Button>
<Button onClick={() => form.resetFields()}>
</Button>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
>
</Button>
</Space>
</Form.Item>
<Form.Item name="authorizationCode" label="授权码">
<Input placeholder="Authorization Code" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="type" label="授权类型">
<Select
placeholder="Authorization Type"
style={{ width: 180 }}
allowClear
options={GetMachineAuthorizationTypeOptions()}
/>
</Form.Item>
<Form.Item >
<Space>
<Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
</Button>
<Button onClick={() => {
form.resetFields();
QueryMachineAuthorizationCollection(tableParams, form.getFieldsValue())
}
}>
</Button>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
>
</Button>
<Button
danger
onClick={handleBatchDelete}
>
</Button>
</Space>
</Form.Item>
</div>
</Form>
<Table
@@ -237,12 +306,18 @@ const MachineIdAuthorization: React.FC = () => {
loading={loading}
pagination={tableParams.pagination}
onChange={TableChangeHandle}
scroll={{ x: 1500 }} // 添加这一行,设置表格的最小宽度
/>
<Modal width={600} title="新增机器码" maskClosable={false} open={modalVisible} footer={null} onCancel={modalCancel}>
<AddMachineIdAuthorization setFormRef={setFormRef} id={id} />
{
isEmpty(id) ? <AddMachineIdAuthorization setFormRef={setFormRef} /> :
<ModifyMachineIdAuthorization setFormRef={setFormRef} id={id} />
}
</Modal>
{messageHolder}
{modalHolder}
</TemplateContainer>
);
};
+2 -2
View File
@@ -203,7 +203,7 @@ const PromptManagement: React.FC = () => {
};
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<Card
style={{
borderRadius: 8,
@@ -211,7 +211,7 @@ const PromptManagement: React.FC = () => {
styles={{
body: {
backgroundImage:
initialState?.settings?.navTheme === 'realDark'
initialState?.settings?.navTheme === 'light'
? 'background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)'
: 'background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)',
}
@@ -180,7 +180,7 @@ const PromptManagement: React.FC = () => {
};
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<Card
style={{
borderRadius: 8,
@@ -188,7 +188,7 @@ const PromptManagement: React.FC = () => {
styles={{
body: {
backgroundImage:
initialState?.settings?.navTheme === 'realDark'
initialState?.settings?.navTheme === 'light'
? 'background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)'
: 'background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)',
}
+1 -1
View File
@@ -196,7 +196,7 @@ const RoleManagement: React.FC = () => {
}
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<div>
<Form
layout='inline'
@@ -14,9 +14,11 @@ import { AllOptionKeyName } from '@/services/enum/optionEnum';
interface SoftwareControlManagementProps {
// Add your props here
userId?: number;
cantModify?: boolean;
}
const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
const SoftwareControlManagement: FC<SoftwareControlManagementProps> = ({ userId, cantModify }) => {
const { initialState } = useModel('@@initialState');
const [messageApi, messageHolder] = message.useMessage();
const [loading, setLoading] = React.useState<boolean>(false);
@@ -101,7 +103,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
title: '操作',
key: 'action',
width: 100,
hidden: !access.isAdminOrSuperAdmin,
hidden: !access.isAdminOrSuperAdmin && !access.canSofrwareControlManagement,
render: (_, record) => (
<Dropdown
menu={{
@@ -109,6 +111,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
{
key: 'edit',
label: '编辑',
hidden: !access.canEditSoftwareControl,
icon: <EditOutlined />,
onClick: () => {
// 编辑
@@ -119,6 +122,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
key: 'addTrail',
label: '添加试用',
style: { color: '#faad14' },
hidden: !access.canAddTrailSoftwareControl,
icon: <PlusSquareOutlined />,
onClick: async () => {
// 添加试用
@@ -128,6 +132,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
{
key: 'addMouth',
label: '添加月付',
hidden: !access.canAddMouthSoftwareControl,
style: { color: '#38a2fc' },
icon: <PlusSquareOutlined />,
onClick: async () => {
@@ -139,6 +144,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
key: 'addQuarterly',
label: '添加季付',
style: { color: '#38a2fc' },
hidden: !access.canAddQuarterlySoftwareControl,
icon: <PlusSquareOutlined />,
onClick: async () => {
// 延长到期时间
@@ -148,6 +154,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
{
key: 'addHalfYear',
label: '添加半年',
hidden: !access.canAddHalfYearSoftwareControl,
style: { color: '#38a2fc' },
icon: <PlusSquareOutlined />,
onClick: async () => {
@@ -158,6 +165,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
{
key: 'addYear',
label: '添加年付',
hidden: !access.canAddYearSoftwareControl,
style: { color: '#38a2fc' },
icon: <PlusSquareOutlined />,
onClick: async () => {
@@ -168,6 +176,7 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
{
key: 'addForever',
label: '永久',
hidden: !access.canAddForeverSoftwareControl,
style: { color: '#38a2fc' },
icon: <PlusSquareOutlined />,
onClick: async () => {
@@ -179,12 +188,13 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
key: 'delete',
label: '停用权限',
danger: true,
hidden: !access.canDeleteSoftwareControl,
icon: <DeleteOutlined />,
onClick: async () => {
await DeleteSoftwareControl(record.id);
}
},
],
].filter(item => !item.hidden)
}}
>
<Button type="text" color="primary" variant="filled" icon={<MenuOutlined />} />
@@ -272,6 +282,11 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
}
useEffect(() => {
if (userId) {
form.setFieldsValue({
userId: userId
})
}
QueryUserSoftwareControlCollection(tableParams, form.getFieldsValue()).then();
Software.GetSoftwareBaseCollection().then((res) => {
setSoftwareBasicInfo(res);
@@ -307,10 +322,11 @@ const SoftwareControlManagement: FC<SoftwareControlManagementProps> = () => {
}
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<Form
layout='inline'
form={form}
disabled={cantModify}
onFinish={QuerySoftwareControlByCondition}
>
<Form.Item label="用户ID" name='userId' style={{ marginBottom: 5 }}>
+3 -2
View File
@@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react';
import { Form, Input, Button, Spin, message, Row, Col } from 'antd';
import { UserRegistr } from '@/services/services/login';
import { history, request } from '@umijs/max';
import { history } from '@umijs/max';
import cusRequest from '@/request';
const Register: React.FC = () => {
const [form] = Form.useForm();
@@ -36,7 +37,7 @@ const Register: React.FC = () => {
// 开始请求发送的接口
let res = await request<ApiResponse.SuccessItem<string>>(`/lms/User/SendVerificationCode`, {
let res = await cusRequest<string>(`/lms/User/SendVerificationCode`, {
method: 'POST',
data: { email }
});
+4 -3
View File
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { Form, Input, Button, message, Row, Col } from 'antd';
import { request } from '@umijs/max';
import cusRequest from '@/request';
interface ResetPasswordProps {
onCancel: () => void;
@@ -31,7 +32,7 @@ const ResetPassword: React.FC<ResetPasswordProps> = ({ onCancel, onSuccess }) =>
setLoading(true);
// 发送验证码请求
const res = await request<ApiResponse.SuccessItem<string>>('/lms/User/SendResetPasswordCode', {
const res = await cusRequest<string>('/lms/User/SendResetPasswordCode', {
method: 'POST',
data: { email: emailValue }
});
@@ -67,7 +68,7 @@ const ResetPassword: React.FC<ResetPasswordProps> = ({ onCancel, onSuccess }) =>
setLoading(true);
// 发送重置密码请求
const res = await request<ApiResponse.SuccessItem<string>>(`/lms/User/ResetPassword/${values.email}/${values.verificationCode}`, {
const res = await cusRequest<string>(`/lms/User/ResetPassword/${values.email}/${values.verificationCode}`, {
method: 'POST'
});
+3 -2
View File
@@ -1,8 +1,9 @@
import React, { useState } from 'react';
import { Form, Input, Button, message, Card, Typography } from 'antd';
import { LockOutlined } from '@ant-design/icons';
import { request, useModel } from '@umijs/max';
import { useModel } from '@umijs/max';
import { isEmpty } from 'lodash';
import cusRequest from '@/request';
const { Title } = Typography;
@@ -33,7 +34,7 @@ const ResetPassword: React.FC = () => {
setLoading(true);
// 发送重置密码请求
const res = await request<ApiResponse.SuccessItem<string>>(`/lms/User/ResetPassword/${initialState?.currentUser?.id}`, {
const res = await cusRequest<string>(`/lms/User/ResetPassword/${initialState?.currentUser?.id}`, {
method: 'POST',
data: {
"newPassword": values.newPassword,
+1 -1
View File
@@ -110,7 +110,7 @@ const UserCenter: React.FC = () => {
}
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"} style={{ minWidth: 600 }}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"} style={{ minWidth: 600 }}>
<div>
<Card hoverable title={renderTitie()} style={{ width: "100%" }}>
<Row justify="start" wrap>
@@ -9,12 +9,13 @@ 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 Icon, { DeleteOutlined, EditOutlined, KeyOutlined, MenuOutlined, SyncOutlined } from "@ant-design/icons";
import Icon, { DeleteOutlined, EditOutlined, KeyOutlined, MenuOutlined, SyncOutlined, ToolOutlined } from "@ant-design/icons";
import { SoftwareControl } from "@/services/services/software";
import { CustomIconComponentProps } from "@ant-design/icons/lib/components/Icon";
import DiceIcon from "@/components/Icon/DiceIcon";
import { generateRandomPassword } from "@/util/password";
import ResetUserPassword from "./ResetUserPassword";
import SofrwareControlManagement from "@/pages/Software/SofrwareControl/SofrwareControlManagement";
const UserManagement: React.FC = () => {
type TagRender = SelectProps['tagRender'];
@@ -158,7 +159,7 @@ const UserManagement: React.FC = () => {
* @returns
*/
async function ApplySoftwareControlHandle(userId: number) {
if (!access.isAdminOrSuperAdmin) {
if (!access.isAdminOrSuperAdmin && !access.isAgentUser) {
messageApi.error("您没有权限执行此操作");
return;
}
@@ -246,7 +247,7 @@ const UserManagement: React.FC = () => {
{
title: '操作',
width: '80px',
hidden: !access.isAdminOrSuperAdmin,
hidden: !(access.isAdminOrSuperAdmin || access.isAdmin || access.isSuperAdmin || access.isAgentUser),
render: (text, record) => (
<Dropdown
menu={{
@@ -281,6 +282,22 @@ const UserManagement: React.FC = () => {
await ApplySoftwareControlHandle(record.id);
}
},
{
key: 'modifySoftwareControl',
label: '修改软件控制权限',
icon: <ToolOutlined />,
hidden: !access.canApplySoftwareControl,
primary: true,
onClick: async () => {
modal.info({
title: '修改软件控制权限',
width: window.innerWidth * 0.8,
closable: true,
content: <SofrwareControlManagement userId={record.id} cantModify={true} />,
footer: null
});
}
},
{
key: 'delete',
label: '删除',
@@ -301,7 +318,7 @@ const UserManagement: React.FC = () => {
];
return (
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "realDark"}>
<TemplateContainer navTheme={initialState?.settings?.navTheme ?? "light"}>
<div>
<Form
layout='inline'
+1 -1
View File
@@ -96,7 +96,7 @@ const Welcome: React.FC = () => {
body: {
backgroundImage:
initialState?.settings?.navTheme === 'realDark'
initialState?.settings?.navTheme === 'light'
? 'background-image: linear-gradient(75deg, #1A1B1F 0%, #191C1F 100%)'
: 'background-image: linear-gradient(75deg, #FBFDFF 0%, #F5F7FF 100%)',
}