seeder-st2110-components 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.esm.js +467 -76
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +525 -133
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/styles/index.less +34 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var antd = require('antd');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var ahooks = require('ahooks');
|
|
@@ -80,7 +80,7 @@ const formatBytes = function (bytes) {
|
|
|
80
80
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
81
81
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
82
82
|
};
|
|
83
|
-
const UsageItem = /*#__PURE__*/
|
|
83
|
+
const UsageItem = /*#__PURE__*/React.memo(_ref => {
|
|
84
84
|
let {
|
|
85
85
|
title,
|
|
86
86
|
iconClass,
|
|
@@ -110,8 +110,8 @@ const UsageItem = /*#__PURE__*/react.memo(_ref => {
|
|
|
110
110
|
var UsageItem$1 = UsageItem;
|
|
111
111
|
|
|
112
112
|
const useHardwareWebSocket = socketUrl => {
|
|
113
|
-
const [systemStatus, setSystemStatus] =
|
|
114
|
-
const handleMessage =
|
|
113
|
+
const [systemStatus, setSystemStatus] = React.useState();
|
|
114
|
+
const handleMessage = React.useCallback(message => {
|
|
115
115
|
try {
|
|
116
116
|
if (message) {
|
|
117
117
|
setSystemStatus(prev => _objectSpread2(_objectSpread2({}, prev), message));
|
|
@@ -234,7 +234,7 @@ const useHardwareUsage = socketUrl => {
|
|
|
234
234
|
const {
|
|
235
235
|
ps_status
|
|
236
236
|
} = useHardwareWebSocket$1(socketUrl);
|
|
237
|
-
return
|
|
237
|
+
return React.useMemo(() => {
|
|
238
238
|
if (!ps_status || typeof ps_status !== 'object') return null;
|
|
239
239
|
const statusItems = getItems(getDetail(ps_status));
|
|
240
240
|
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -266,7 +266,7 @@ const AuthorizationModal = _ref => {
|
|
|
266
266
|
const {
|
|
267
267
|
message
|
|
268
268
|
} = antd.App.useApp();
|
|
269
|
-
const [code, setCode] =
|
|
269
|
+
const [code, setCode] = React.useState('');
|
|
270
270
|
const {
|
|
271
271
|
accredit_status: isActivated,
|
|
272
272
|
message: statusMessage = 'Unactivated',
|
|
@@ -360,13 +360,13 @@ const useAuth = options => {
|
|
|
360
360
|
autoShowModal = true
|
|
361
361
|
} = options || {};
|
|
362
362
|
const [messageApi, contextHolder] = antd.message.useMessage();
|
|
363
|
-
const [showModal, setShowModal] =
|
|
364
|
-
const [authData, setAuthData] =
|
|
365
|
-
const [isRegistered, setIsRegistered] =
|
|
366
|
-
const [loading, setLoading] =
|
|
367
|
-
const openModal =
|
|
368
|
-
const closeModal =
|
|
369
|
-
|
|
363
|
+
const [showModal, setShowModal] = React.useState(false); // 默认隐藏
|
|
364
|
+
const [authData, setAuthData] = React.useState(defaultAuthData);
|
|
365
|
+
const [isRegistered, setIsRegistered] = React.useState(false);
|
|
366
|
+
const [loading, setLoading] = React.useState(false);
|
|
367
|
+
const openModal = React.useCallback(() => setShowModal(true), []);
|
|
368
|
+
const closeModal = React.useCallback(() => setShowModal(false), []);
|
|
369
|
+
React.useEffect(() => {
|
|
370
370
|
async function loadAuthInfo() {
|
|
371
371
|
try {
|
|
372
372
|
setLoading(true);
|
|
@@ -442,22 +442,22 @@ const useUpgrade = _ref => {
|
|
|
442
442
|
uploadCompleteDelay = 3000,
|
|
443
443
|
statusPollingInterval = 1000
|
|
444
444
|
} = _ref;
|
|
445
|
-
const [isSpinning, setIsSpinning] =
|
|
446
|
-
const [interval, setInterval] =
|
|
447
|
-
const inputRef =
|
|
448
|
-
const [currentStatus, setCurrentStatus] =
|
|
449
|
-
const isUploadCompleteRef =
|
|
450
|
-
const [uploadProgress, setUploadProgress] =
|
|
445
|
+
const [isSpinning, setIsSpinning] = React.useState(false);
|
|
446
|
+
const [interval, setInterval] = React.useState(undefined); // 间隔时间,当设置值为 undefined 时会停止计时器
|
|
447
|
+
const inputRef = React.useRef(null);
|
|
448
|
+
const [currentStatus, setCurrentStatus] = React.useState('idle'); // 'idle' | 'uploading' | 'upgrading'
|
|
449
|
+
const isUploadCompleteRef = React.useRef(false); // 安装包上传是否完成
|
|
450
|
+
const [uploadProgress, setUploadProgress] = React.useState(0);
|
|
451
451
|
|
|
452
452
|
// 分别创建独立的取消令牌
|
|
453
|
-
const uploadCancelToken =
|
|
454
|
-
const statusCancelToken =
|
|
453
|
+
const uploadCancelToken = React.useRef(axios.CancelToken.source());
|
|
454
|
+
const statusCancelToken = React.useRef(axios.CancelToken.source());
|
|
455
455
|
const showLoader = () => setIsSpinning(true);
|
|
456
456
|
const hideLoader = () => setIsSpinning(false);
|
|
457
457
|
|
|
458
458
|
// 构建菜单项 - 确保至少包含download和upload
|
|
459
459
|
// 构建菜单项 - 最终完美版本
|
|
460
|
-
const finalMenuItems =
|
|
460
|
+
const finalMenuItems = React.useMemo(() => {
|
|
461
461
|
const hasDownload = menuItems.some(item => item.key === 'download');
|
|
462
462
|
const hasUpload = menuItems.some(item => item.key === 'upload');
|
|
463
463
|
if (hasDownload && hasUpload) {
|
|
@@ -694,7 +694,7 @@ const useUpgrade = _ref => {
|
|
|
694
694
|
ahooks.useInterval(fetchUpgradeStatus, interval);
|
|
695
695
|
|
|
696
696
|
// 组件卸载时清理
|
|
697
|
-
|
|
697
|
+
React.useEffect(() => {
|
|
698
698
|
return () => {
|
|
699
699
|
uploadCancelToken.current.cancel();
|
|
700
700
|
statusCancelToken.current.cancel();
|
|
@@ -748,7 +748,7 @@ const useSystemOperations = function () {
|
|
|
748
748
|
const {
|
|
749
749
|
modal: AntdModal
|
|
750
750
|
} = antd.App.useApp();
|
|
751
|
-
const doAction =
|
|
751
|
+
const doAction = React.useCallback(action => {
|
|
752
752
|
try {
|
|
753
753
|
AntdModal.confirm({
|
|
754
754
|
icon: /*#__PURE__*/jsxRuntime.jsx(icons.ExclamationCircleFilled, {}),
|
|
@@ -772,14 +772,14 @@ const useSystemOperations = function () {
|
|
|
772
772
|
console.error("".concat(action.toUpperCase(), " ERROR: "), error);
|
|
773
773
|
}
|
|
774
774
|
}, [AntdModal, confirmTitle, cancelText, okText, onPowerOff, onRestart]);
|
|
775
|
-
const getMenuItems =
|
|
775
|
+
const getMenuItems = React.useCallback(() => [{
|
|
776
776
|
key: "poweroff",
|
|
777
777
|
label: "Power Off"
|
|
778
778
|
}, {
|
|
779
779
|
key: "restart",
|
|
780
780
|
label: "Restart"
|
|
781
781
|
}], []);
|
|
782
|
-
const handleMenuClick =
|
|
782
|
+
const handleMenuClick = React.useCallback(_ref => {
|
|
783
783
|
let {
|
|
784
784
|
key
|
|
785
785
|
} = _ref;
|
|
@@ -881,15 +881,15 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
881
881
|
modal
|
|
882
882
|
} = antd.App.useApp();
|
|
883
883
|
const [form] = antd.Form.useForm();
|
|
884
|
-
const [st2110Interfaces, setSt2110Interfaces] =
|
|
885
|
-
const [lanConfigs, setLanConfigs] =
|
|
886
|
-
const [submitLoading, setSubmitLoading] =
|
|
887
|
-
const [isInitialized, setIsInitialized] =
|
|
888
|
-
const initializationStatus =
|
|
884
|
+
const [st2110Interfaces, setSt2110Interfaces] = React.useState([]);
|
|
885
|
+
const [lanConfigs, setLanConfigs] = React.useState([]);
|
|
886
|
+
const [submitLoading, setSubmitLoading] = React.useState(false);
|
|
887
|
+
const [isInitialized, setIsInitialized] = React.useState(false);
|
|
888
|
+
const initializationStatus = React.useRef({
|
|
889
889
|
hasFetched: false,
|
|
890
890
|
hasInitialized: false
|
|
891
891
|
});
|
|
892
|
-
const preparedFieldConfig =
|
|
892
|
+
const preparedFieldConfig = React.useMemo(() => {
|
|
893
893
|
const config = _objectSpread2({}, fieldConfig);
|
|
894
894
|
|
|
895
895
|
// 确保LAN和QSFP的配置存在
|
|
@@ -907,7 +907,7 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
907
907
|
}
|
|
908
908
|
return config;
|
|
909
909
|
}, [fieldConfig, showNetmask, sections]);
|
|
910
|
-
|
|
910
|
+
React.useEffect(() => {
|
|
911
911
|
if (!open) return;
|
|
912
912
|
const fetchData = async () => {
|
|
913
913
|
if (initializationStatus.current.hasFetched) return;
|
|
@@ -954,7 +954,7 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
954
954
|
}, [open, getLanConfig, getSysConfig, sections]);
|
|
955
955
|
|
|
956
956
|
// 当模态框关闭时重置状态
|
|
957
|
-
|
|
957
|
+
React.useEffect(() => {
|
|
958
958
|
if (!open) {
|
|
959
959
|
setIsInitialized(false);
|
|
960
960
|
setLanConfigs([]);
|
|
@@ -968,7 +968,7 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
968
968
|
}, [open, form]);
|
|
969
969
|
|
|
970
970
|
// 动态初始值配置
|
|
971
|
-
const initialValues =
|
|
971
|
+
const initialValues = React.useMemo(() => {
|
|
972
972
|
const values = {};
|
|
973
973
|
if (sections.includes('LAN') && lanConfigs.length > 0) {
|
|
974
974
|
values.LAN = lanConfigs.map(config => _objectSpread2({
|
|
@@ -993,13 +993,13 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
993
993
|
}, [lanConfigs, st2110Interfaces, sections, showNetmask]);
|
|
994
994
|
|
|
995
995
|
// 当初始值准备好后设置表单值
|
|
996
|
-
|
|
996
|
+
React.useEffect(() => {
|
|
997
997
|
if (isInitialized && !initializationStatus.current.hasInitialized) {
|
|
998
998
|
form.setFieldsValue(initialValues);
|
|
999
999
|
initializationStatus.current.hasInitialized = true;
|
|
1000
1000
|
}
|
|
1001
1001
|
}, [isInitialized, form, initialValues]);
|
|
1002
|
-
const handleSuccess =
|
|
1002
|
+
const handleSuccess = React.useCallback(async function () {
|
|
1003
1003
|
let {
|
|
1004
1004
|
messageText = 'Success',
|
|
1005
1005
|
isPopup = !!restart,
|
|
@@ -1039,7 +1039,7 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
1039
1039
|
}
|
|
1040
1040
|
onClose();
|
|
1041
1041
|
}, [message, modal, getSysConfig, restart, getConfig, sections, onClose]);
|
|
1042
|
-
const handleSubmit =
|
|
1042
|
+
const handleSubmit = React.useCallback(async () => {
|
|
1043
1043
|
setSubmitLoading(true);
|
|
1044
1044
|
try {
|
|
1045
1045
|
const values = await form.validateFields();
|
|
@@ -1088,16 +1088,13 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
1088
1088
|
const allSucceeded = results.every(result => result.status === 'fulfilled');
|
|
1089
1089
|
if (allSucceeded) {
|
|
1090
1090
|
handleSuccess();
|
|
1091
|
-
} else {
|
|
1092
|
-
message.error('Some configurations failed to update');
|
|
1093
1091
|
}
|
|
1094
1092
|
} catch (error) {
|
|
1095
1093
|
console.error('Failed to update configurations: ', error);
|
|
1096
|
-
message.error('Failed to update configurations');
|
|
1097
1094
|
} finally {
|
|
1098
1095
|
setSubmitLoading(false);
|
|
1099
1096
|
}
|
|
1100
|
-
}, [form, sections, lanConfigs, st2110Interfaces, updateLanConfig, updateSysConfig, handleSuccess
|
|
1097
|
+
}, [form, sections, lanConfigs, st2110Interfaces, updateLanConfig, updateSysConfig, handleSuccess]);
|
|
1101
1098
|
|
|
1102
1099
|
// 合并默认模态框属性和传入的属性
|
|
1103
1100
|
const mergedModalProps = _objectSpread2({
|
|
@@ -1150,7 +1147,7 @@ const NetworkSettingsModal = _ref2 => {
|
|
|
1150
1147
|
})), restartRemark]
|
|
1151
1148
|
}));
|
|
1152
1149
|
};
|
|
1153
|
-
var NetworkSettingsModal$1 = /*#__PURE__*/
|
|
1150
|
+
var NetworkSettingsModal$1 = /*#__PURE__*/React.memo(NetworkSettingsModal);
|
|
1154
1151
|
|
|
1155
1152
|
const defaultFieldConfigs = {
|
|
1156
1153
|
clock_class: {
|
|
@@ -1276,12 +1273,12 @@ const PtpModal = _ref => {
|
|
|
1276
1273
|
modalProps = {},
|
|
1277
1274
|
formProps = {}
|
|
1278
1275
|
} = _ref;
|
|
1279
|
-
const [ptpStatus, setPtpStatus] =
|
|
1276
|
+
const [ptpStatus, setPtpStatus] = React.useState(null);
|
|
1280
1277
|
const [form] = antd.Form.useForm();
|
|
1281
1278
|
const {
|
|
1282
1279
|
message
|
|
1283
1280
|
} = antd.App.useApp();
|
|
1284
|
-
|
|
1281
|
+
React.useEffect(() => {
|
|
1285
1282
|
if (open) {
|
|
1286
1283
|
getPtpInfo().then(data => {
|
|
1287
1284
|
if (data !== null && data !== void 0 && data[0]) {
|
|
@@ -1291,7 +1288,7 @@ const PtpModal = _ref => {
|
|
|
1291
1288
|
});
|
|
1292
1289
|
}
|
|
1293
1290
|
}, [open, form, getPtpInfo]);
|
|
1294
|
-
const ptpStatusArray =
|
|
1291
|
+
const ptpStatusArray = React.useMemo(() => {
|
|
1295
1292
|
if (!ptpStatus) return [];
|
|
1296
1293
|
return convertPtpStatusToArray(ptpStatus, fieldConfigs, fieldOrder);
|
|
1297
1294
|
}, [ptpStatus]);
|
|
@@ -1396,9 +1393,9 @@ const PtpModal = _ref => {
|
|
|
1396
1393
|
}))
|
|
1397
1394
|
}));
|
|
1398
1395
|
};
|
|
1399
|
-
var PtpModal$1 = /*#__PURE__*/
|
|
1396
|
+
var PtpModal$1 = /*#__PURE__*/React.memo(PtpModal);
|
|
1400
1397
|
|
|
1401
|
-
const LeftList = /*#__PURE__*/
|
|
1398
|
+
const LeftList = /*#__PURE__*/React.memo(_ref => {
|
|
1402
1399
|
let {
|
|
1403
1400
|
dataSource,
|
|
1404
1401
|
selectedPresetId,
|
|
@@ -1409,7 +1406,7 @@ const LeftList = /*#__PURE__*/react.memo(_ref => {
|
|
|
1409
1406
|
showDescription = false,
|
|
1410
1407
|
texts = {
|
|
1411
1408
|
newButton: "New Preset",
|
|
1412
|
-
removeButton: "
|
|
1409
|
+
removeButton: "Delete"
|
|
1413
1410
|
}
|
|
1414
1411
|
} = _ref;
|
|
1415
1412
|
// 动态计算列布局
|
|
@@ -1420,7 +1417,7 @@ const LeftList = /*#__PURE__*/react.memo(_ref => {
|
|
|
1420
1417
|
className: "list-container",
|
|
1421
1418
|
children: /*#__PURE__*/jsxRuntime.jsx(antd.List, {
|
|
1422
1419
|
header: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
1423
|
-
className: "grid ".concat(gridColumns, " w-full list-header"),
|
|
1420
|
+
className: "grid ".concat(gridColumns, " gap-2 w-full list-header"),
|
|
1424
1421
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1425
1422
|
children: "Name"
|
|
1426
1423
|
}), /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -1438,14 +1435,27 @@ const LeftList = /*#__PURE__*/react.memo(_ref => {
|
|
|
1438
1435
|
},
|
|
1439
1436
|
onClick: () => onSelectPreset(item),
|
|
1440
1437
|
children: /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
1441
|
-
className: "grid ".concat(gridColumns, " w-full text-text-normal"),
|
|
1438
|
+
className: "grid ".concat(gridColumns, " gap-2 w-full text-text-normal"),
|
|
1442
1439
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1443
|
-
|
|
1444
|
-
children:
|
|
1440
|
+
className: "min-w-0",
|
|
1441
|
+
children: /*#__PURE__*/jsxRuntime.jsx(antd.Typography.Text, {
|
|
1442
|
+
ellipsis: true,
|
|
1443
|
+
title: item.name,
|
|
1444
|
+
children: item.name || "Untitled Preset"
|
|
1445
|
+
})
|
|
1445
1446
|
}), /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1446
|
-
|
|
1447
|
+
className: "min-w-0",
|
|
1448
|
+
children: /*#__PURE__*/jsxRuntime.jsx(antd.Typography.Text, {
|
|
1449
|
+
ellipsis: true,
|
|
1450
|
+
children: item.create_time
|
|
1451
|
+
})
|
|
1447
1452
|
}), showDescription && /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1448
|
-
|
|
1453
|
+
className: "min-w-0",
|
|
1454
|
+
children: /*#__PURE__*/jsxRuntime.jsx(antd.Typography.Text, {
|
|
1455
|
+
ellipsis: true,
|
|
1456
|
+
title: item.description,
|
|
1457
|
+
children: item.description
|
|
1458
|
+
})
|
|
1449
1459
|
})]
|
|
1450
1460
|
})
|
|
1451
1461
|
}),
|
|
@@ -1461,7 +1471,7 @@ const LeftList = /*#__PURE__*/react.memo(_ref => {
|
|
|
1461
1471
|
onClick: onAddNew,
|
|
1462
1472
|
className: "p-0 h-auto",
|
|
1463
1473
|
icon: /*#__PURE__*/jsxRuntime.jsx(icons.PlusOutlined, {}),
|
|
1464
|
-
children: "Create
|
|
1474
|
+
children: "Create New Preset"
|
|
1465
1475
|
})
|
|
1466
1476
|
})
|
|
1467
1477
|
})
|
|
@@ -1477,18 +1487,16 @@ const LeftList = /*#__PURE__*/react.memo(_ref => {
|
|
|
1477
1487
|
size: "middle",
|
|
1478
1488
|
children: [/*#__PURE__*/jsxRuntime.jsx(antd.Button, {
|
|
1479
1489
|
type: "default",
|
|
1480
|
-
icon: /*#__PURE__*/jsxRuntime.jsx(icons.PlusOutlined, {})
|
|
1481
|
-
style:
|
|
1482
|
-
|
|
1483
|
-
},
|
|
1490
|
+
icon: /*#__PURE__*/jsxRuntime.jsx(icons.PlusOutlined, {})
|
|
1491
|
+
// style={{ padding: "20px 12px" }}
|
|
1492
|
+
,
|
|
1484
1493
|
className: "btn-gray",
|
|
1485
1494
|
onClick: onAddNew,
|
|
1486
1495
|
children: texts.newButton
|
|
1487
1496
|
}), /*#__PURE__*/jsxRuntime.jsx(antd.Button, {
|
|
1488
|
-
type: "default"
|
|
1489
|
-
style:
|
|
1490
|
-
|
|
1491
|
-
},
|
|
1497
|
+
type: "default"
|
|
1498
|
+
// style={{ padding: "20px 12px" }}
|
|
1499
|
+
,
|
|
1492
1500
|
className: "btn-gray",
|
|
1493
1501
|
onClick: onRemove,
|
|
1494
1502
|
children: texts.removeButton
|
|
@@ -1515,7 +1523,7 @@ const SubmitButton = _ref2 => {
|
|
|
1515
1523
|
})
|
|
1516
1524
|
});
|
|
1517
1525
|
};
|
|
1518
|
-
const RightDetailForm = /*#__PURE__*/
|
|
1526
|
+
const RightDetailForm = /*#__PURE__*/React.memo(_ref3 => {
|
|
1519
1527
|
let {
|
|
1520
1528
|
form,
|
|
1521
1529
|
onSave,
|
|
@@ -1525,8 +1533,8 @@ const RightDetailForm = /*#__PURE__*/react.memo(_ref3 => {
|
|
|
1525
1533
|
originalPresetData,
|
|
1526
1534
|
fields = {
|
|
1527
1535
|
name: {
|
|
1528
|
-
label: "
|
|
1529
|
-
placeholder: "
|
|
1536
|
+
label: "Name",
|
|
1537
|
+
placeholder: "Please enter name",
|
|
1530
1538
|
required: true
|
|
1531
1539
|
}
|
|
1532
1540
|
},
|
|
@@ -1534,16 +1542,16 @@ const RightDetailForm = /*#__PURE__*/react.memo(_ref3 => {
|
|
|
1534
1542
|
loadButton: "Load",
|
|
1535
1543
|
saveButton: "Save"
|
|
1536
1544
|
},
|
|
1537
|
-
presetChanged
|
|
1545
|
+
presetChanged // 作用:在切换选中预设时强制触发 Checkbox 的重新初始化
|
|
1538
1546
|
} = _ref3;
|
|
1539
|
-
const [initialSelected, setInitialSelected] =
|
|
1547
|
+
const [initialSelected, setInitialSelected] = React.useState([]);
|
|
1540
1548
|
const currentSelected = antd.Form.useWatch('category_list', form) || [];
|
|
1541
1549
|
|
|
1542
1550
|
// 检查是否包含category_list字段
|
|
1543
1551
|
const hasCategoryList = fields.category_list !== null && fields.category_list !== undefined;
|
|
1544
1552
|
|
|
1545
1553
|
// 初始化 category_list 的选择状态
|
|
1546
|
-
|
|
1554
|
+
React.useEffect(() => {
|
|
1547
1555
|
if (hasCategoryList) {
|
|
1548
1556
|
const currentValue = form.getFieldValue('category_list') || [];
|
|
1549
1557
|
setInitialSelected(currentValue);
|
|
@@ -1551,7 +1559,7 @@ const RightDetailForm = /*#__PURE__*/react.memo(_ref3 => {
|
|
|
1551
1559
|
}, [presetChanged, form, hasCategoryList]); // 当presetChanged变化时更新
|
|
1552
1560
|
|
|
1553
1561
|
// 动态生成 checkbox 选项
|
|
1554
|
-
const checkboxOptions =
|
|
1562
|
+
const checkboxOptions = React.useMemo(() => {
|
|
1555
1563
|
if (!hasCategoryList) return [];
|
|
1556
1564
|
return fields.category_list.options.map(category => {
|
|
1557
1565
|
const isInitiallySelected = initialSelected.includes(category.name);
|
|
@@ -1594,32 +1602,40 @@ const RightDetailForm = /*#__PURE__*/react.memo(_ref3 => {
|
|
|
1594
1602
|
},
|
|
1595
1603
|
children: [/*#__PURE__*/jsxRuntime.jsx(antd.Form.Item, {
|
|
1596
1604
|
name: "name",
|
|
1597
|
-
label: fields.name.label
|
|
1598
|
-
rules
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
}
|
|
1605
|
+
label: fields.name.label
|
|
1606
|
+
// rules={[
|
|
1607
|
+
// {
|
|
1608
|
+
// required: fields.name.required,
|
|
1609
|
+
// validator: async (_, value) => {
|
|
1610
|
+
// if (!value || value.trim() === '') {
|
|
1611
|
+
// return Promise.reject(new Error('Preset name cannot be empty or spaces only'));
|
|
1612
|
+
// }
|
|
1613
|
+
// }
|
|
1614
|
+
// }
|
|
1615
|
+
// ]}
|
|
1616
|
+
,
|
|
1617
|
+
required: true,
|
|
1606
1618
|
children: /*#__PURE__*/jsxRuntime.jsx(antd.Input, {
|
|
1607
1619
|
placeholder: fields.name.placeholder,
|
|
1608
1620
|
disabled: isEditing
|
|
1609
1621
|
})
|
|
1610
1622
|
}), hasCategoryList && /*#__PURE__*/jsxRuntime.jsx(antd.Form.Item, {
|
|
1611
1623
|
name: "category_list",
|
|
1612
|
-
label: fields.category_list.label
|
|
1613
|
-
rules
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
}
|
|
1624
|
+
label: fields.category_list.label
|
|
1625
|
+
// rules={[
|
|
1626
|
+
// {
|
|
1627
|
+
// required: fields.category_list.required,
|
|
1628
|
+
// message: 'Please select at least one category',
|
|
1629
|
+
// validator: (_, value) => {
|
|
1630
|
+
// if (value && value.length > 0) {
|
|
1631
|
+
// return Promise.resolve();
|
|
1632
|
+
// }
|
|
1633
|
+
// return Promise.reject(new Error('Please select at least one category'));
|
|
1634
|
+
// }
|
|
1635
|
+
// }
|
|
1636
|
+
// ]}
|
|
1637
|
+
,
|
|
1638
|
+
required: true,
|
|
1623
1639
|
children: /*#__PURE__*/jsxRuntime.jsx(antd.Checkbox.Group, {
|
|
1624
1640
|
className: "grid grid-cols-2 gap-2",
|
|
1625
1641
|
onChange: handleCheckboxChange,
|
|
@@ -1635,7 +1651,10 @@ const RightDetailForm = /*#__PURE__*/react.memo(_ref3 => {
|
|
|
1635
1651
|
children: /*#__PURE__*/jsxRuntime.jsx(antd.Input.TextArea, {
|
|
1636
1652
|
rows: 4,
|
|
1637
1653
|
placeholder: fields.description.placeholder,
|
|
1638
|
-
disabled: isEditing
|
|
1654
|
+
disabled: isEditing,
|
|
1655
|
+
style: {
|
|
1656
|
+
resize: 'none'
|
|
1657
|
+
}
|
|
1639
1658
|
})
|
|
1640
1659
|
})]
|
|
1641
1660
|
}), isEditing ? /*#__PURE__*/jsxRuntime.jsx(SubmitButton, _objectSpread2(_objectSpread2({
|
|
@@ -1668,20 +1687,20 @@ const Preset = _ref => {
|
|
|
1668
1687
|
// 字段配置
|
|
1669
1688
|
fields = {
|
|
1670
1689
|
name: {
|
|
1671
|
-
label: "
|
|
1672
|
-
placeholder: "
|
|
1690
|
+
label: "Name",
|
|
1691
|
+
placeholder: "Please enter name",
|
|
1673
1692
|
required: true
|
|
1674
1693
|
}
|
|
1675
1694
|
},
|
|
1676
1695
|
texts = {
|
|
1677
1696
|
title: "Preset Management",
|
|
1678
1697
|
emptyText: "Select a preset from the list to view details",
|
|
1679
|
-
deleteConfirm: "Are you sure to delete preset",
|
|
1698
|
+
deleteConfirm: "Are you sure you want to delete preset",
|
|
1680
1699
|
loadConfirm: "Are you sure you want to load preset",
|
|
1681
1700
|
loadText: "Loading...",
|
|
1682
1701
|
successText: "Success",
|
|
1683
1702
|
newButton: "New Preset",
|
|
1684
|
-
removeButton: "
|
|
1703
|
+
removeButton: "Delete",
|
|
1685
1704
|
loadButton: "Load",
|
|
1686
1705
|
saveButton: "Save"
|
|
1687
1706
|
},
|
|
@@ -1694,31 +1713,34 @@ const Preset = _ref => {
|
|
|
1694
1713
|
message: AntdMessage,
|
|
1695
1714
|
modal: AntdModal
|
|
1696
1715
|
} = antd.App.useApp();
|
|
1697
|
-
const [presetList, setPresetList] =
|
|
1698
|
-
const [selectedPreset, setSelectedPreset] =
|
|
1699
|
-
const [loading, setLoading] =
|
|
1700
|
-
const [presetChanged, setPresetChanged] =
|
|
1716
|
+
const [presetList, setPresetList] = React.useState([]);
|
|
1717
|
+
const [selectedPreset, setSelectedPreset] = React.useState(null);
|
|
1718
|
+
const [loading, setLoading] = React.useState(false);
|
|
1719
|
+
const [presetChanged, setPresetChanged] = React.useState(0);
|
|
1701
1720
|
const [form] = antd.Form.useForm();
|
|
1702
|
-
|
|
1703
|
-
// 获取预设列表
|
|
1704
|
-
react.useEffect(() => {
|
|
1705
|
-
fetchPresetList();
|
|
1706
|
-
}, []);
|
|
1707
|
-
const fetchPresetList = react.useCallback(async () => {
|
|
1721
|
+
const fetchPresetList = React.useCallback(async () => {
|
|
1708
1722
|
try {
|
|
1709
1723
|
const data = await getPresetList();
|
|
1710
1724
|
const presets = (data === null || data === void 0 ? void 0 : data.preset_list) || data || [];
|
|
1711
1725
|
setPresetList(presets);
|
|
1726
|
+
|
|
1727
|
+
// 自动选中第一个预设
|
|
1728
|
+
if (presets.length > 0) {
|
|
1729
|
+
const firstPreset = presets[0];
|
|
1730
|
+
setSelectedPreset(firstPreset);
|
|
1731
|
+
form.setFieldsValue(firstPreset);
|
|
1732
|
+
setPresetChanged(prev => prev + 1);
|
|
1733
|
+
}
|
|
1712
1734
|
} catch (error) {
|
|
1713
1735
|
console.error('Failed to fetch preset list:', error);
|
|
1714
1736
|
}
|
|
1715
1737
|
}, [getPresetList]);
|
|
1716
|
-
const handleSelectPreset =
|
|
1738
|
+
const handleSelectPreset = React.useCallback(preset => {
|
|
1717
1739
|
setSelectedPreset(preset);
|
|
1718
1740
|
form.setFieldsValue(preset);
|
|
1719
|
-
setPresetChanged(prev => prev + 1);
|
|
1741
|
+
setPresetChanged(prev => prev + 1);
|
|
1720
1742
|
}, [form]);
|
|
1721
|
-
const handleAddNew =
|
|
1743
|
+
const handleAddNew = React.useCallback(() => {
|
|
1722
1744
|
var _fields$category_list;
|
|
1723
1745
|
const unsavedPreset = presetList.find(item => !item.id);
|
|
1724
1746
|
if (unsavedPreset) {
|
|
@@ -1740,7 +1762,7 @@ const Preset = _ref => {
|
|
|
1740
1762
|
setSelectedPreset(newPreset);
|
|
1741
1763
|
form.setFieldsValue(newPreset);
|
|
1742
1764
|
}, [form, presetList, AntdMessage]);
|
|
1743
|
-
const handleRemove =
|
|
1765
|
+
const handleRemove = React.useCallback(async () => {
|
|
1744
1766
|
if (!selectedPreset) return;
|
|
1745
1767
|
|
|
1746
1768
|
// 检查是否为新建的未保存数据(无id)
|
|
@@ -1754,18 +1776,44 @@ const Preset = _ref => {
|
|
|
1754
1776
|
cancelText: 'No',
|
|
1755
1777
|
okText: 'Yes',
|
|
1756
1778
|
onOk: async () => {
|
|
1779
|
+
// 在删除前记录当前选中项的位置
|
|
1780
|
+
const currentIndex = presetList.findIndex(item => isUnsavedPreset ? !item.id : item.id === selectedPreset.id);
|
|
1757
1781
|
if (!isUnsavedPreset) {
|
|
1758
1782
|
await removePreset({
|
|
1759
1783
|
id: selectedPreset.id
|
|
1760
1784
|
});
|
|
1761
1785
|
AntdMessage.success(texts.successText);
|
|
1762
|
-
// 刷新列表
|
|
1763
|
-
await fetchPresetList();
|
|
1764
1786
|
} else {
|
|
1787
|
+
// 移除未保存的预设
|
|
1765
1788
|
setPresetList(prev => prev.filter(item => !!item.id));
|
|
1766
1789
|
}
|
|
1767
1790
|
|
|
1768
|
-
//
|
|
1791
|
+
// 获取删除后的列表
|
|
1792
|
+
const updatedList = isUnsavedPreset ? presetList.filter(item => !!item.id) : await getPresetList().then(data => (data === null || data === void 0 ? void 0 : data.preset_list) || data || []);
|
|
1793
|
+
|
|
1794
|
+
// 更新列表
|
|
1795
|
+
setPresetList(updatedList);
|
|
1796
|
+
if (updatedList.length > 0) {
|
|
1797
|
+
// 计算下一个索引
|
|
1798
|
+
let nextIndex = 0;
|
|
1799
|
+
if (currentIndex > 0) {
|
|
1800
|
+
// 如果删除的不是最后一项
|
|
1801
|
+
if (currentIndex < updatedList.length) {
|
|
1802
|
+
nextIndex = currentIndex; // 保持相同位置
|
|
1803
|
+
} else {
|
|
1804
|
+
nextIndex = updatedList.length - 1; // 选最后一个
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
const nextPreset = updatedList[nextIndex];
|
|
1808
|
+
if (nextPreset) {
|
|
1809
|
+
setSelectedPreset(nextPreset);
|
|
1810
|
+
form.setFieldsValue(nextPreset);
|
|
1811
|
+
setPresetChanged(prev => prev + 1);
|
|
1812
|
+
return;
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
// 列表为空
|
|
1769
1817
|
setSelectedPreset(null);
|
|
1770
1818
|
form.resetFields();
|
|
1771
1819
|
}
|
|
@@ -1773,8 +1821,8 @@ const Preset = _ref => {
|
|
|
1773
1821
|
} catch (error) {
|
|
1774
1822
|
console.error('Failed to delete preset:', error);
|
|
1775
1823
|
}
|
|
1776
|
-
}, [selectedPreset, form, AntdModal, AntdMessage,
|
|
1777
|
-
const handleLoadPreset =
|
|
1824
|
+
}, [selectedPreset, form, AntdModal, AntdMessage, texts, removePreset, getPresetList]);
|
|
1825
|
+
const handleLoadPreset = React.useCallback(async loadData => {
|
|
1778
1826
|
if (!loadData) return;
|
|
1779
1827
|
|
|
1780
1828
|
// 显示确认对话框
|
|
@@ -1826,30 +1874,56 @@ const Preset = _ref => {
|
|
|
1826
1874
|
}
|
|
1827
1875
|
});
|
|
1828
1876
|
}, [loadPreset, texts, AntdMessage, AntdModal, onLoadSuccess, onLoadError]);
|
|
1829
|
-
const handleSave =
|
|
1877
|
+
const handleSave = React.useCallback(async () => {
|
|
1830
1878
|
setLoading(true);
|
|
1831
1879
|
try {
|
|
1832
|
-
|
|
1833
|
-
|
|
1880
|
+
var _fields$name, _fields$category_list2;
|
|
1881
|
+
const values = await form.getFieldsValue();
|
|
1882
|
+
|
|
1883
|
+
// 验证预设名称
|
|
1884
|
+
if ((_fields$name = fields.name) !== null && _fields$name !== void 0 && _fields$name.required) {
|
|
1885
|
+
if (!values.name || values.name.trim() === '') {
|
|
1886
|
+
AntdMessage.error('Name is required.');
|
|
1887
|
+
return; // 直接返回 不执行
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
// 验证分类列表
|
|
1892
|
+
if ((_fields$category_list2 = fields.category_list) !== null && _fields$category_list2 !== void 0 && _fields$category_list2.required) {
|
|
1893
|
+
if (!values.category_list || values.category_list.length === 0) {
|
|
1894
|
+
AntdMessage.error('No category selected.');
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1834
1898
|
await savePreset(values);
|
|
1835
1899
|
AntdMessage.success(texts.successText);
|
|
1900
|
+
const savedPresetName = values.name;
|
|
1901
|
+
|
|
1836
1902
|
// 刷新列表
|
|
1837
|
-
await
|
|
1903
|
+
const data = await getPresetList();
|
|
1904
|
+
const presets = (data === null || data === void 0 ? void 0 : data.preset_list) || data || [];
|
|
1905
|
+
setPresetList(presets);
|
|
1838
1906
|
|
|
1839
|
-
//
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
console.error('Form validation failed:', error.errorFields);
|
|
1907
|
+
// 在刷新后的列表中查找同名的预设
|
|
1908
|
+
const newlySavedPreset = presets.find(item => item.name === savedPresetName);
|
|
1909
|
+
if (newlySavedPreset) {
|
|
1910
|
+
setSelectedPreset(newlySavedPreset);
|
|
1911
|
+
form.setFieldsValue(newlySavedPreset);
|
|
1912
|
+
setPresetChanged(prev => prev + 1);
|
|
1846
1913
|
} else {
|
|
1847
|
-
|
|
1914
|
+
setSelectedPreset(values);
|
|
1848
1915
|
}
|
|
1916
|
+
} catch (error) {
|
|
1917
|
+
console.error('Failed to save preset:', error);
|
|
1849
1918
|
} finally {
|
|
1850
1919
|
setLoading(false);
|
|
1851
1920
|
}
|
|
1852
|
-
}, [form, AntdMessage,
|
|
1921
|
+
}, [form, AntdMessage, texts, savePreset, getPresetList]);
|
|
1922
|
+
|
|
1923
|
+
// 初始化数据
|
|
1924
|
+
React.useEffect(() => {
|
|
1925
|
+
fetchPresetList();
|
|
1926
|
+
}, [fetchPresetList]);
|
|
1853
1927
|
return /*#__PURE__*/jsxRuntime.jsx(antd.Modal, {
|
|
1854
1928
|
title: texts.title,
|
|
1855
1929
|
width: width,
|
|
@@ -1913,9 +1987,9 @@ const Preset = _ref => {
|
|
|
1913
1987
|
})
|
|
1914
1988
|
});
|
|
1915
1989
|
};
|
|
1916
|
-
var PresetModal = /*#__PURE__*/
|
|
1990
|
+
var PresetModal = /*#__PURE__*/React.memo(Preset);
|
|
1917
1991
|
|
|
1918
|
-
const _excluded = ["menuItems", "onMenuClick", "downloadFiles", "upgradeExecute", "upgradeStatus", "acceptFileTypes", "uploadCompleteDelay", "statusPollingInterval", "children"];
|
|
1992
|
+
const _excluded$1 = ["menuItems", "onMenuClick", "downloadFiles", "upgradeExecute", "upgradeStatus", "acceptFileTypes", "uploadCompleteDelay", "statusPollingInterval", "children"];
|
|
1919
1993
|
const UpgradeManager = _ref => {
|
|
1920
1994
|
let {
|
|
1921
1995
|
menuItems = [],
|
|
@@ -1928,7 +2002,7 @@ const UpgradeManager = _ref => {
|
|
|
1928
2002
|
statusPollingInterval = 1000,
|
|
1929
2003
|
children
|
|
1930
2004
|
} = _ref,
|
|
1931
|
-
dropdownProps = _objectWithoutProperties(_ref, _excluded);
|
|
2005
|
+
dropdownProps = _objectWithoutProperties(_ref, _excluded$1);
|
|
1932
2006
|
const [upgradeElement] = useUpgrade$1({
|
|
1933
2007
|
menuItems,
|
|
1934
2008
|
onMenuClick,
|
|
@@ -3323,7 +3397,9 @@ const CommonHeader = _ref => {
|
|
|
3323
3397
|
getSocketUrl = defaultGetSocketUrl,
|
|
3324
3398
|
logoProps = {},
|
|
3325
3399
|
className = '',
|
|
3326
|
-
style = {}
|
|
3400
|
+
style = {},
|
|
3401
|
+
// 新增插槽
|
|
3402
|
+
leftContent // 左侧额外内容
|
|
3327
3403
|
} = _ref;
|
|
3328
3404
|
const [logo] = useSpaLogo$1(logoProps);
|
|
3329
3405
|
|
|
@@ -3353,7 +3429,7 @@ const CommonHeader = _ref => {
|
|
|
3353
3429
|
},
|
|
3354
3430
|
children: productInfo.version
|
|
3355
3431
|
})]
|
|
3356
|
-
})]
|
|
3432
|
+
}), leftContent]
|
|
3357
3433
|
}), /*#__PURE__*/jsxRuntime.jsxs(antd.Flex, {
|
|
3358
3434
|
align: "center",
|
|
3359
3435
|
gap: 10,
|
|
@@ -3397,8 +3473,324 @@ CommonHeader.propTypes = {
|
|
|
3397
3473
|
};
|
|
3398
3474
|
var CommonHeader$1 = CommonHeader;
|
|
3399
3475
|
|
|
3476
|
+
const _excluded = ["value", "min", "max", "className", "disablePointerLock", "modifierKeys", "decimalPlaces", "onChange", "onDragStart", "onDragEnd", "style"];
|
|
3477
|
+
|
|
3478
|
+
// 默认配置
|
|
3479
|
+
const DEFAULT_DECIMAL_PLACES = 2;
|
|
3480
|
+
|
|
3481
|
+
// src/react/defaults-and-utils.ts
|
|
3482
|
+
// eslint-disable-next-line no-var
|
|
3483
|
+
var defaultModifiers = {
|
|
3484
|
+
default: {
|
|
3485
|
+
multiplier: 1,
|
|
3486
|
+
sensitivity: 1
|
|
3487
|
+
}
|
|
3488
|
+
// ctrlKey: { multiplier: 1, sensitivity: 1 },
|
|
3489
|
+
// shiftKey: { multiplier: 10, sensitivity: 0.5 },
|
|
3490
|
+
// metaKey: { multiplier: 1, sensitivity: 1 },
|
|
3491
|
+
// altKey: { multiplier: 1, sensitivity: 1 }
|
|
3492
|
+
};
|
|
3493
|
+
|
|
3494
|
+
// multiplier: 控制每次鼠标移动时数值变化的基本单位 multiplier: 1- 鼠标移动1像素,值变化1 multiplier: 10- 鼠标移动1像素,值变化10
|
|
3495
|
+
// sensitivity: 控制数值变化的灵敏度 sensitivity: 1- 正常灵敏度 sensitivity: 0.5- 减半灵敏度,需要移动2像素才能产生正常1像素的效果
|
|
3496
|
+
|
|
3497
|
+
// 修改 formatNumber 函数,强制显示1位小数
|
|
3498
|
+
function formatNumber(value) {
|
|
3499
|
+
let decimalPlaces = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_DECIMAL_PLACES;
|
|
3500
|
+
return new Intl.NumberFormat("en-US", {
|
|
3501
|
+
minimumFractionDigits: decimalPlaces,
|
|
3502
|
+
maximumFractionDigits: decimalPlaces,
|
|
3503
|
+
useGrouping: false
|
|
3504
|
+
}).format(value);
|
|
3505
|
+
}
|
|
3506
|
+
function handleArrow(e, multiplier, value) {
|
|
3507
|
+
if (e.key === "ArrowUp") {
|
|
3508
|
+
return value + multiplier;
|
|
3509
|
+
}
|
|
3510
|
+
if (e.key === "ArrowDown") {
|
|
3511
|
+
return value - multiplier;
|
|
3512
|
+
}
|
|
3513
|
+
return value;
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3516
|
+
// eslint-disable-next-line no-var
|
|
3517
|
+
var DragCursor = _ref => {
|
|
3518
|
+
let {
|
|
3519
|
+
cursorPosition
|
|
3520
|
+
} = _ref;
|
|
3521
|
+
return /* @__PURE__ */React.createElement("div", {
|
|
3522
|
+
style: {
|
|
3523
|
+
position: "fixed",
|
|
3524
|
+
left: 0,
|
|
3525
|
+
top: 0,
|
|
3526
|
+
width: "100vw",
|
|
3527
|
+
height: "100vh",
|
|
3528
|
+
pointerEvents: "none"
|
|
3529
|
+
}
|
|
3530
|
+
}, /* @__PURE__ */React.createElement("svg", {
|
|
3531
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3532
|
+
width: "24",
|
|
3533
|
+
height: "24",
|
|
3534
|
+
viewBox: "0 0 24 24",
|
|
3535
|
+
style: {
|
|
3536
|
+
position: "absolute",
|
|
3537
|
+
left: cursorPosition.x,
|
|
3538
|
+
top: cursorPosition.y,
|
|
3539
|
+
transform: "translate(-50%, -50%)",
|
|
3540
|
+
pointerEvents: "none"
|
|
3541
|
+
}
|
|
3542
|
+
}, /* @__PURE__ */React.createElement("path", {
|
|
3543
|
+
fill: "#000",
|
|
3544
|
+
stroke: "#fff",
|
|
3545
|
+
strokeLinejoin: "round",
|
|
3546
|
+
d: "M6.5 9a.5.5 0 0 0-.8-.4l-4 3a.5.5 0 0 0 0 .8l4 3a.5.5 0 0 0 .8-.4v-1.5h11V15a.5.5 0 0 0 .8.4l4-3a.5.5 0 0 0 0-.8l-4-3a.5.5 0 0 0-.8.4v1.5h-11V9Z",
|
|
3547
|
+
style: {
|
|
3548
|
+
filter: "drop-shadow( 0px 2px 1px rgba(0, 0, 0, .35))"
|
|
3549
|
+
}
|
|
3550
|
+
})));
|
|
3551
|
+
};
|
|
3552
|
+
|
|
3553
|
+
// eslint-disable-next-line no-var
|
|
3554
|
+
var noop = () => {};
|
|
3555
|
+
function DraggableNumberInput(_ref2) {
|
|
3556
|
+
let {
|
|
3557
|
+
value,
|
|
3558
|
+
min,
|
|
3559
|
+
max,
|
|
3560
|
+
className = "",
|
|
3561
|
+
disablePointerLock = false,
|
|
3562
|
+
modifierKeys,
|
|
3563
|
+
decimalPlaces = DEFAULT_DECIMAL_PLACES,
|
|
3564
|
+
onChange = noop,
|
|
3565
|
+
onDragStart = noop,
|
|
3566
|
+
onDragEnd = noop,
|
|
3567
|
+
style
|
|
3568
|
+
} = _ref2,
|
|
3569
|
+
restProps = _objectWithoutProperties(_ref2, _excluded);
|
|
3570
|
+
const inputRef = React.useRef(null);
|
|
3571
|
+
const [isMouseDown, setIsMouseDown] = React.useState(false);
|
|
3572
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
3573
|
+
const [localValue, setLocalValue] = React.useState(() => formatNumber(value, decimalPlaces));
|
|
3574
|
+
const [cursorPosition, setCursorPosition] = React.useState({
|
|
3575
|
+
x: 0,
|
|
3576
|
+
y: 0
|
|
3577
|
+
});
|
|
3578
|
+
const totalMovement = React.useRef(0);
|
|
3579
|
+
const startValue = React.useRef(0);
|
|
3580
|
+
const startX = React.useRef(0);
|
|
3581
|
+
const currentMultiplier = React.useRef(1);
|
|
3582
|
+
|
|
3583
|
+
// === 新增:编辑状态跟踪 ===
|
|
3584
|
+
const [isEditing, setIsEditing] = React.useState(false);
|
|
3585
|
+
const lastExternalValueRef = React.useRef(value);
|
|
3586
|
+
|
|
3587
|
+
// 修改 formatNumber 调用,传入 decimalPlaces
|
|
3588
|
+
const formatValue = React.useCallback(val => {
|
|
3589
|
+
return formatNumber(val, decimalPlaces);
|
|
3590
|
+
}, [decimalPlaces]);
|
|
3591
|
+
const constrainedOnChange = React.useCallback(newValue => {
|
|
3592
|
+
let constrainedValue = newValue;
|
|
3593
|
+
if (typeof min === "number") {
|
|
3594
|
+
constrainedValue = Math.max(min, constrainedValue);
|
|
3595
|
+
}
|
|
3596
|
+
if (typeof max === "number") {
|
|
3597
|
+
constrainedValue = Math.min(max, constrainedValue);
|
|
3598
|
+
}
|
|
3599
|
+
onChange(constrainedValue);
|
|
3600
|
+
}, [onChange, min, max]);
|
|
3601
|
+
React.useEffect(() => {
|
|
3602
|
+
// 只有当用户不在编辑状态,且外部值真正变化时才更新
|
|
3603
|
+
if (!isEditing && lastExternalValueRef.current !== value) {
|
|
3604
|
+
const formattedValue = formatValue(value);
|
|
3605
|
+
setLocalValue(formattedValue);
|
|
3606
|
+
lastExternalValueRef.current = value;
|
|
3607
|
+
}
|
|
3608
|
+
}, [value, formatValue, isEditing]);
|
|
3609
|
+
const handleInputChange = e => {
|
|
3610
|
+
const val = e.target.value;
|
|
3611
|
+
|
|
3612
|
+
// 标记为编辑状态
|
|
3613
|
+
setIsEditing(true);
|
|
3614
|
+
setLocalValue(val);
|
|
3615
|
+
|
|
3616
|
+
// 允许输入中间状态,不立即触发onChange
|
|
3617
|
+
if (val === '' || val === '-' || val === '.' || val.endsWith('.')) {
|
|
3618
|
+
return; // 输入中,不触发onChange
|
|
3619
|
+
}
|
|
3620
|
+
const num = parseFloat(val);
|
|
3621
|
+
if (!isNaN(num)) {
|
|
3622
|
+
constrainedOnChange(num);
|
|
3623
|
+
}
|
|
3624
|
+
};
|
|
3625
|
+
const handleBlur = () => {
|
|
3626
|
+
// 退出编辑状态
|
|
3627
|
+
setIsEditing(false);
|
|
3628
|
+
const num = parseFloat(localValue);
|
|
3629
|
+
if (!isNaN(num)) {
|
|
3630
|
+
// 根据 decimalPlaces 进行四舍五入
|
|
3631
|
+
const precision = Math.pow(10, decimalPlaces);
|
|
3632
|
+
const processedValue = Math.round(num * precision) / precision;
|
|
3633
|
+
const formattedValue = formatValue(processedValue);
|
|
3634
|
+
|
|
3635
|
+
// 更新显示值
|
|
3636
|
+
setLocalValue(formattedValue);
|
|
3637
|
+
lastExternalValueRef.current = processedValue;
|
|
3638
|
+
// 触发外部变化
|
|
3639
|
+
constrainedOnChange(processedValue);
|
|
3640
|
+
} else {
|
|
3641
|
+
// 如果输入无效,重置为当前外部值
|
|
3642
|
+
const formattedValue = formatValue(value);
|
|
3643
|
+
setLocalValue(formattedValue);
|
|
3644
|
+
}
|
|
3645
|
+
};
|
|
3646
|
+
const handleMouseDown = React.useCallback(e => {
|
|
3647
|
+
if (!inputRef.current) return;
|
|
3648
|
+
let x = 0,
|
|
3649
|
+
y = 0;
|
|
3650
|
+
if ("clientX" in e && "clientY" in e) {
|
|
3651
|
+
[x, y] = [e.clientX, e.clientY];
|
|
3652
|
+
}
|
|
3653
|
+
if ("touches" in e) {
|
|
3654
|
+
[x, y] = [e.touches[0].clientX, e.touches[0].clientY];
|
|
3655
|
+
}
|
|
3656
|
+
setIsMouseDown(true);
|
|
3657
|
+
startX.current = x;
|
|
3658
|
+
startValue.current = value;
|
|
3659
|
+
totalMovement.current = 0;
|
|
3660
|
+
setCursorPosition({
|
|
3661
|
+
x,
|
|
3662
|
+
y
|
|
3663
|
+
});
|
|
3664
|
+
}, [value, disablePointerLock]);
|
|
3665
|
+
const updateDelta = React.useCallback(e => {
|
|
3666
|
+
if (!isMouseDown) return;
|
|
3667
|
+
applyMovement(totalMovement.current, e);
|
|
3668
|
+
}, [isMouseDown]);
|
|
3669
|
+
const getModifiers = React.useCallback(e => {
|
|
3670
|
+
const mods = _objectSpread2(_objectSpread2({}, defaultModifiers), modifierKeys);
|
|
3671
|
+
for (const key in mods) {
|
|
3672
|
+
if (key !== "default" && e[key]) {
|
|
3673
|
+
currentMultiplier.current = mods[key].multiplier;
|
|
3674
|
+
return mods[key];
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
currentMultiplier.current = mods.default.multiplier;
|
|
3678
|
+
return mods.default;
|
|
3679
|
+
}, [modifierKeys]);
|
|
3680
|
+
const applyMovement = React.useCallback((newMovement, e) => {
|
|
3681
|
+
const {
|
|
3682
|
+
sensitivity,
|
|
3683
|
+
multiplier
|
|
3684
|
+
} = getModifiers(e);
|
|
3685
|
+
const delta = newMovement * sensitivity * multiplier;
|
|
3686
|
+
let newValue = startValue.current + delta;
|
|
3687
|
+
// 根据 decimalPlaces 进行精度控制
|
|
3688
|
+
const precision = Math.pow(10, decimalPlaces);
|
|
3689
|
+
newValue = Math.round(newValue * precision) / precision;
|
|
3690
|
+
newValue = Object.is(newValue, -0) ? 0 : newValue;
|
|
3691
|
+
constrainedOnChange(newValue);
|
|
3692
|
+
}, [constrainedOnChange, getModifiers, decimalPlaces]);
|
|
3693
|
+
const handleArrowKeyDown = e => {
|
|
3694
|
+
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
3695
|
+
e.preventDefault();
|
|
3696
|
+
const {
|
|
3697
|
+
multiplier
|
|
3698
|
+
} = getModifiers(e);
|
|
3699
|
+
const newValue = handleArrow(e, multiplier, value);
|
|
3700
|
+
constrainedOnChange(newValue);
|
|
3701
|
+
}
|
|
3702
|
+
};
|
|
3703
|
+
const handleModifierKeyDuringDrag = React.useCallback(e => {
|
|
3704
|
+
if (e.key === "Shift" || e.key === "Control" || e.key === "Meta" || e.key === "Alt") {
|
|
3705
|
+
updateDelta(e);
|
|
3706
|
+
}
|
|
3707
|
+
}, [updateDelta]);
|
|
3708
|
+
const handleMouseMove = React.useCallback(e => {
|
|
3709
|
+
if (!isMouseDown) return;
|
|
3710
|
+
if ("touches" in e) {
|
|
3711
|
+
e.preventDefault();
|
|
3712
|
+
}
|
|
3713
|
+
if (!disablePointerLock && document.pointerLockElement && !("touches" in e)) {
|
|
3714
|
+
setCursorPosition(prev => {
|
|
3715
|
+
const width = window.innerWidth;
|
|
3716
|
+
const height = window.innerHeight;
|
|
3717
|
+
const x2 = (prev.x + e.movementX + width) % width;
|
|
3718
|
+
const y = (prev.y + e.movementY + height) % height;
|
|
3719
|
+
return {
|
|
3720
|
+
x: x2,
|
|
3721
|
+
y
|
|
3722
|
+
};
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
const x = "touches" in e ? e.touches[0].clientX : e.clientX;
|
|
3726
|
+
const newMovement = disablePointerLock || "touches" in e ? x - startX.current : totalMovement.current + e.movementX;
|
|
3727
|
+
if (!isDragging && newMovement !== 0) {
|
|
3728
|
+
if (!disablePointerLock && !("touches" in e)) {
|
|
3729
|
+
var _inputRef$current, _inputRef$current$req;
|
|
3730
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || (_inputRef$current$req = _inputRef$current.requestPointerLock) === null || _inputRef$current$req === void 0 || _inputRef$current$req.call(_inputRef$current);
|
|
3731
|
+
}
|
|
3732
|
+
setIsDragging(true);
|
|
3733
|
+
document.addEventListener("keydown", handleModifierKeyDuringDrag);
|
|
3734
|
+
document.addEventListener("keyup", handleModifierKeyDuringDrag);
|
|
3735
|
+
onDragStart();
|
|
3736
|
+
}
|
|
3737
|
+
totalMovement.current = newMovement;
|
|
3738
|
+
applyMovement(newMovement, e);
|
|
3739
|
+
}, [isMouseDown, disablePointerLock, startX, isDragging, onDragStart, applyMovement]);
|
|
3740
|
+
const handleMouseUp = React.useCallback(() => {
|
|
3741
|
+
setIsMouseDown(false);
|
|
3742
|
+
totalMovement.current = 0;
|
|
3743
|
+
if (isDragging) {
|
|
3744
|
+
setIsDragging(false);
|
|
3745
|
+
document.removeEventListener("keydown", handleModifierKeyDuringDrag);
|
|
3746
|
+
document.removeEventListener("keyup", handleModifierKeyDuringDrag);
|
|
3747
|
+
onDragEnd();
|
|
3748
|
+
}
|
|
3749
|
+
if (document.pointerLockElement) {
|
|
3750
|
+
document.exitPointerLock();
|
|
3751
|
+
}
|
|
3752
|
+
}, [isDragging, onDragEnd, disablePointerLock]);
|
|
3753
|
+
React.useEffect(() => {
|
|
3754
|
+
if (isMouseDown) {
|
|
3755
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
3756
|
+
document.addEventListener("touchmove", handleMouseMove, {
|
|
3757
|
+
passive: false
|
|
3758
|
+
});
|
|
3759
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
3760
|
+
document.addEventListener("touchend", handleMouseUp);
|
|
3761
|
+
return () => {
|
|
3762
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
3763
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
3764
|
+
document.removeEventListener("touchmove", handleMouseMove);
|
|
3765
|
+
document.removeEventListener("touchend", handleMouseUp);
|
|
3766
|
+
};
|
|
3767
|
+
}
|
|
3768
|
+
}, [isMouseDown, handleMouseMove, handleMouseUp]);
|
|
3769
|
+
return /* @__PURE__ */React.createElement(React.Fragment, null, /* @__PURE__ */React.createElement("input", _objectSpread2({
|
|
3770
|
+
ref: inputRef,
|
|
3771
|
+
type: "text",
|
|
3772
|
+
inputMode: "numeric",
|
|
3773
|
+
pattern: "-?[0-9]*\\.?[0-9]*",
|
|
3774
|
+
value: localValue,
|
|
3775
|
+
onChange: handleInputChange,
|
|
3776
|
+
onBlur: handleBlur,
|
|
3777
|
+
onMouseDown: handleMouseDown,
|
|
3778
|
+
onTouchStart: handleMouseDown,
|
|
3779
|
+
onKeyDown: handleArrowKeyDown,
|
|
3780
|
+
className: "draggable-number-input ".concat(className, " ").concat(isDragging ? "dragging" : ""),
|
|
3781
|
+
style: _objectSpread2(_objectSpread2({}, {
|
|
3782
|
+
cursor: "ew-resize",
|
|
3783
|
+
userSelect: "none",
|
|
3784
|
+
caretColor: isDragging ? "transparent" : "initial"
|
|
3785
|
+
}), style)
|
|
3786
|
+
}, restProps)), isDragging && !disablePointerLock && /* @__PURE__ */React.createElement(DragCursor, {
|
|
3787
|
+
cursorPosition
|
|
3788
|
+
}));
|
|
3789
|
+
}
|
|
3790
|
+
|
|
3400
3791
|
exports.AuthorizationModal = AuthorizationModal$1;
|
|
3401
3792
|
exports.CommonHeader = CommonHeader$1;
|
|
3793
|
+
exports.DraggableNumberInput = DraggableNumberInput;
|
|
3402
3794
|
exports.NetworkSettingsModal = NetworkSettingsModal$1;
|
|
3403
3795
|
exports.PresetModal = PresetModal;
|
|
3404
3796
|
exports.PtpModal = PtpModal$1;
|