2025-05-15 14:05:03 +08:00
|
|
|
|
import React, { useEffect, useState } from 'react';
|
2025-05-16 17:51:58 +08:00
|
|
|
|
import { Form, Input, DatePicker, Select, Button, message, FormInstance, Space } from 'antd';
|
2025-05-15 14:05:03 +08:00
|
|
|
|
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';
|
2025-05-16 17:51:58 +08:00
|
|
|
|
import cusRequest from '@/request';
|
|
|
|
|
|
import { AddMachineIdAuthorizationFunc } from '@/services/services/other';
|
2025-05-15 14:05:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface AddMachineIdAuthorizationProps {
|
|
|
|
|
|
setFormRef: (form: FormInstance) => void;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-16 17:51:58 +08:00
|
|
|
|
const AddMachineIdAuthorization: React.FC<AddMachineIdAuthorizationProps> = ({ setFormRef }) => {
|
2025-05-15 14:05:03 +08:00
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
const [messageApi, messageHolder] = message.useMessage();
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
setFormRef(form);
|
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
type: 0,
|
2025-05-16 17:51:58 +08:00
|
|
|
|
useType: 0,
|
|
|
|
|
|
expiryTime: 365,
|
|
|
|
|
|
authorizationCode: ""
|
2025-05-15 14:05:03 +08:00
|
|
|
|
})
|
2025-05-16 17:51:58 +08:00
|
|
|
|
}, [form, setFormRef]);
|
2025-05-15 14:05:03 +08:00
|
|
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
// TODO: Implement API call to save the authorization
|
|
|
|
|
|
let values = form.getFieldsValue();
|
2025-05-16 17:51:58 +08:00
|
|
|
|
await AddMachineIdAuthorizationFunc(values);
|
2025-05-15 14:05:03 +08:00
|
|
|
|
messageApi.success('Machine ID authorization added successfully');
|
2025-05-16 17:51:58 +08:00
|
|
|
|
} catch (error: any) {
|
2025-05-15 14:05:03 +08:00
|
|
|
|
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"
|
|
|
|
|
|
>
|
2025-05-16 17:51:58 +08:00
|
|
|
|
|
2025-05-15 14:05:03 +08:00
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="type"
|
|
|
|
|
|
label="授权软件类型"
|
|
|
|
|
|
rules={[{ required: true, message: '请输入授权软件类型' }]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Select placeholder="选择授权软件类型" options={GetMachineAuthorizationTypeOptions()}></Select>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
2025-05-16 17:51:58 +08:00
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="useType"
|
|
|
|
|
|
label="授权使用类型"
|
|
|
|
|
|
rules={[{ required: true, message: '请输入授权软件类型' }]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Select placeholder="选择授权软件类型" options={[
|
|
|
|
|
|
{ label: '基础', value: 0 },
|
|
|
|
|
|
{ label: '专业', value: 1 },
|
|
|
|
|
|
]}></Select>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
2025-05-15 14:05:03 +08:00
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="authorizedDate"
|
|
|
|
|
|
label="授权时间"
|
|
|
|
|
|
>
|
|
|
|
|
|
<DatePicker
|
2025-05-16 17:51:58 +08:00
|
|
|
|
disabled
|
2025-05-15 14:05:03 +08:00
|
|
|
|
showTime
|
|
|
|
|
|
style={{ width: '100%' }}
|
|
|
|
|
|
placeholder="选择授权日期和时间"
|
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
|
name="expiryDate"
|
|
|
|
|
|
label="到期时间"
|
|
|
|
|
|
>
|
|
|
|
|
|
<DatePicker
|
2025-05-16 17:51:58 +08:00
|
|
|
|
disabled
|
2025-05-15 14:05:03 +08:00
|
|
|
|
showTime
|
|
|
|
|
|
style={{ width: '100%' }}
|
|
|
|
|
|
placeholder="选择到期日期和时间"
|
|
|
|
|
|
format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
2025-05-16 17:51:58 +08:00
|
|
|
|
<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>
|
2025-05-15 14:05:03 +08:00
|
|
|
|
</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 AddMachineIdAuthorization;
|