批量设备升级弹窗实现
This commit is contained in:
parent
292277b635
commit
3a2301efce
@ -464,6 +464,26 @@ export const BatchCreateDeviceAggregationInputSchema = {
|
|||||||
description: '批量创建设备信息'
|
description: '批量创建设备信息'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const BatchUpdateStatusInputSchema = {
|
||||||
|
required: ['ids', 'upgradeStatus'],
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
ids: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid'
|
||||||
|
},
|
||||||
|
description: '设备升级记录Id集合'
|
||||||
|
},
|
||||||
|
upgradeStatus: {
|
||||||
|
'$ref': '#/components/schemas/DeviceUpgradeStatusTypeEnum'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
description: '批量更新设备升级记录状态信息输入'
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const BindingDeviceThingModelInputSchema = {
|
export const BindingDeviceThingModelInputSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@ -2013,6 +2033,40 @@ export const DeleteTextTemplateInputSchema = {
|
|||||||
description: '删除模板'
|
description: '删除模板'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const DeviceBatchUpgradeForApiInputSchema = {
|
||||||
|
required: ['addressList', 'ioTPlatform', 'ioTPlatformProductId', 'nowFirmwareVersionDataId'],
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
addressList: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string'
|
||||||
|
},
|
||||||
|
description: '设备地址列表'
|
||||||
|
},
|
||||||
|
ioTPlatform: {
|
||||||
|
'$ref': '#/components/schemas/IoTPlatformTypeEnum'
|
||||||
|
},
|
||||||
|
ioTPlatformProductId: {
|
||||||
|
minLength: 1,
|
||||||
|
type: 'string',
|
||||||
|
description: '物联网平台中对应的产品Id'
|
||||||
|
},
|
||||||
|
nowFirmwareVersionDataId: {
|
||||||
|
type: 'string',
|
||||||
|
description: '固件版本信息',
|
||||||
|
format: 'uuid'
|
||||||
|
},
|
||||||
|
upgradeDescription: {
|
||||||
|
type: 'string',
|
||||||
|
description: '升级描述',
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
description: '设备批量升级信息'
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const DeviceCommandForApiInputSchema = {
|
export const DeviceCommandForApiInputSchema = {
|
||||||
required: ['commandContent', 'id'],
|
required: ['commandContent', 'id'],
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@ -11190,6 +11244,23 @@ export const UpdateSettingInputSchema = {
|
|||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const UpdateStatusInputSchema = {
|
||||||
|
required: ['id', 'upgradeStatus'],
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string',
|
||||||
|
description: '设备升级记录Id',
|
||||||
|
format: 'uuid'
|
||||||
|
},
|
||||||
|
upgradeStatus: {
|
||||||
|
'$ref': '#/components/schemas/DeviceUpgradeStatusTypeEnum'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
additionalProperties: false,
|
||||||
|
description: '更新升级状态'
|
||||||
|
} as const;
|
||||||
|
|
||||||
export const UpdateTenantInputSchema = {
|
export const UpdateTenantInputSchema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -172,6 +172,17 @@ export type BatchCreateDeviceAggregationInput = {
|
|||||||
deviceSourceTypeEnum?: DeviceSourceTypeEnum;
|
deviceSourceTypeEnum?: DeviceSourceTypeEnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新设备升级记录状态信息输入
|
||||||
|
*/
|
||||||
|
export type BatchUpdateStatusInput = {
|
||||||
|
/**
|
||||||
|
* 设备升级记录Id集合
|
||||||
|
*/
|
||||||
|
ids: Array<(string)>;
|
||||||
|
upgradeStatus: DeviceUpgradeStatusTypeEnum;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定设备物模型输入
|
* 绑定设备物模型输入
|
||||||
*/
|
*/
|
||||||
@ -1106,6 +1117,29 @@ export type DeleteTextTemplateInput = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备批量升级信息
|
||||||
|
*/
|
||||||
|
export type DeviceBatchUpgradeForApiInput = {
|
||||||
|
/**
|
||||||
|
* 设备地址列表
|
||||||
|
*/
|
||||||
|
addressList: Array<(string)>;
|
||||||
|
ioTPlatform: IoTPlatformTypeEnum;
|
||||||
|
/**
|
||||||
|
* 物联网平台中对应的产品Id
|
||||||
|
*/
|
||||||
|
ioTPlatformProductId: string;
|
||||||
|
/**
|
||||||
|
* 固件版本信息
|
||||||
|
*/
|
||||||
|
nowFirmwareVersionDataId: string;
|
||||||
|
/**
|
||||||
|
* 升级描述
|
||||||
|
*/
|
||||||
|
upgradeDescription?: (string) | null;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备命令
|
* 设备命令
|
||||||
*/
|
*/
|
||||||
@ -6086,6 +6120,17 @@ export type UpdateSettingInput = {
|
|||||||
} | null;
|
} | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新升级状态
|
||||||
|
*/
|
||||||
|
export type UpdateStatusInput = {
|
||||||
|
/**
|
||||||
|
* 设备升级记录Id
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
upgradeStatus: DeviceUpgradeStatusTypeEnum;
|
||||||
|
};
|
||||||
|
|
||||||
export type UpdateTenantInput = {
|
export type UpdateTenantInput = {
|
||||||
id?: string;
|
id?: string;
|
||||||
name?: (string) | null;
|
name?: (string) | null;
|
||||||
@ -6537,6 +6582,16 @@ export type PostAggregationDeviceDeviceUpgradeForApiAsyncResponse = (boolean);
|
|||||||
|
|
||||||
export type PostAggregationDeviceDeviceUpgradeForApiAsyncError = unknown;
|
export type PostAggregationDeviceDeviceUpgradeForApiAsyncError = unknown;
|
||||||
|
|
||||||
|
export type PostAggregationDeviceDeviceBatchUpgradeForApiAsyncData = {
|
||||||
|
query?: {
|
||||||
|
input?: DeviceBatchUpgradeForApiInput;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PostAggregationDeviceDeviceBatchUpgradeForApiAsyncResponse = (boolean);
|
||||||
|
|
||||||
|
export type PostAggregationDeviceDeviceBatchUpgradeForApiAsyncError = unknown;
|
||||||
|
|
||||||
export type PostAggregationDeviceDownloadFirmwareData = {
|
export type PostAggregationDeviceDownloadFirmwareData = {
|
||||||
query?: {
|
query?: {
|
||||||
input?: IdInput;
|
input?: IdInput;
|
||||||
@ -6907,6 +6962,26 @@ export type PostDeviceThingModelManagementCacheAllDeviceThingModelToRedisAsyncRe
|
|||||||
|
|
||||||
export type PostDeviceThingModelManagementCacheAllDeviceThingModelToRedisAsyncError = unknown;
|
export type PostDeviceThingModelManagementCacheAllDeviceThingModelToRedisAsyncError = unknown;
|
||||||
|
|
||||||
|
export type PostUpgradeRecordUpdateStatusAsyncData = {
|
||||||
|
query?: {
|
||||||
|
input?: UpdateStatusInput;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PostUpgradeRecordUpdateStatusAsyncResponse = (DeviceUpgradeRecordDto);
|
||||||
|
|
||||||
|
export type PostUpgradeRecordUpdateStatusAsyncError = unknown;
|
||||||
|
|
||||||
|
export type PostUpgradeRecordBatchUpdateStatusAsyncData = {
|
||||||
|
query?: {
|
||||||
|
input?: BatchUpdateStatusInput;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PostUpgradeRecordBatchUpdateStatusAsyncResponse = (DeviceUpgradeRecordDto);
|
||||||
|
|
||||||
|
export type PostUpgradeRecordBatchUpdateStatusAsyncError = unknown;
|
||||||
|
|
||||||
export type PostUpgradeRecordDeleteAsyncData = {
|
export type PostUpgradeRecordDeleteAsyncData = {
|
||||||
query?: {
|
query?: {
|
||||||
input?: IdInput;
|
input?: IdInput;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
postAggregationDeviceBatchCreateAsync,
|
postAggregationDeviceBatchCreateAsync,
|
||||||
postAggregationDeviceCreateAsync,
|
postAggregationDeviceCreateAsync,
|
||||||
postAggregationDeviceDeleteAsync,
|
postAggregationDeviceDeleteAsync,
|
||||||
|
postAggregationDeviceDeviceBatchUpgradeForApiAsync,
|
||||||
postAggregationDeviceDeviceCommandForApiAsync,
|
postAggregationDeviceDeviceCommandForApiAsync,
|
||||||
postAggregationDeviceDeviceUpgradeForApiAsync,
|
postAggregationDeviceDeviceUpgradeForApiAsync,
|
||||||
postAggregationDeviceGetDevicePropertyValueForApiAsync,
|
postAggregationDeviceGetDevicePropertyValueForApiAsync,
|
||||||
@ -31,7 +32,6 @@ import {
|
|||||||
postDeviceInfoBindingDeviceThingModel,
|
postDeviceInfoBindingDeviceThingModel,
|
||||||
postDeviceInfoCacheDeviceDataToRedis,
|
postDeviceInfoCacheDeviceDataToRedis,
|
||||||
postDeviceInfoPage,
|
postDeviceInfoPage,
|
||||||
postFirmwareInfoFindByDeviceProductIdAsync,
|
|
||||||
postIoTplatformThingModelInfoPageAsync,
|
postIoTplatformThingModelInfoPageAsync,
|
||||||
} from '#/api-client';
|
} from '#/api-client';
|
||||||
import { Icon } from '#/components/icon';
|
import { Icon } from '#/components/icon';
|
||||||
@ -42,6 +42,7 @@ import { $t } from '#/locales';
|
|||||||
import {
|
import {
|
||||||
addDeviceFormSchema,
|
addDeviceFormSchema,
|
||||||
batchAddDeviceFormSchema,
|
batchAddDeviceFormSchema,
|
||||||
|
batchUpgradeDeviceFormSchema,
|
||||||
bindDeviceThingModelFormSchema,
|
bindDeviceThingModelFormSchema,
|
||||||
commandFormSchema,
|
commandFormSchema,
|
||||||
deviceUpgradeFormSchema,
|
deviceUpgradeFormSchema,
|
||||||
@ -70,10 +71,8 @@ const formOptions: VbenFormProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 当平台类型变化时,清除产品ID(因为不同平台的产品列表不同)
|
// 当平台类型变化时,清除产品ID(因为不同平台的产品列表不同)
|
||||||
if (changedFields.includes('ioTPlatform')) {
|
if (changedFields.includes('ioTPlatform') && gridApi?.formApi) {
|
||||||
if (gridApi?.formApi) {
|
await gridApi.formApi.setFieldValue('ioTPlatformProductId', undefined);
|
||||||
await gridApi.formApi.setFieldValue('ioTPlatformProductId', undefined);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当产品切换时,触发搜索
|
// 当产品切换时,触发搜索
|
||||||
@ -765,6 +764,259 @@ const [BatchAddModal, batchAddModalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 批量设备升级表单
|
||||||
|
const [BatchUpgradeForm, batchUpgradeFormApi] = useVbenForm({
|
||||||
|
collapsed: false,
|
||||||
|
commonConfig: {
|
||||||
|
labelWidth: 120,
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
layout: 'horizontal',
|
||||||
|
schema: batchUpgradeDeviceFormSchema.value,
|
||||||
|
showCollapseButton: false,
|
||||||
|
showDefaultActions: false,
|
||||||
|
wrapperClass: 'grid-cols-1',
|
||||||
|
handleValuesChange: async (values, changedFields) => {
|
||||||
|
// 当账号切换时,清空产品名称字段
|
||||||
|
if (changedFields.includes('ioTPlatformAccountId')) {
|
||||||
|
await batchUpgradeFormApi.setFieldValue(
|
||||||
|
'ioTPlatformProductId',
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
await batchUpgradeFormApi.setFieldValue('targetVersionId', undefined);
|
||||||
|
}
|
||||||
|
// 当产品ID变化时,触发目标版本字段重新加载
|
||||||
|
if (changedFields.includes('ioTPlatformProductId')) {
|
||||||
|
await nextTick();
|
||||||
|
await batchUpgradeFormApi.setFieldValue('targetVersionId', undefined);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 批量设备升级提交逻辑
|
||||||
|
const submitBatchUpgrade = async () => {
|
||||||
|
const { valid } = await batchUpgradeFormApi.validate();
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
const formValues = await batchUpgradeFormApi.getValues();
|
||||||
|
|
||||||
|
// 处理设备地址列表
|
||||||
|
const addressList = formValues.addressList
|
||||||
|
.split('\n')
|
||||||
|
.map((address: string) => address.trim())
|
||||||
|
.filter((address: string) => address.length > 0);
|
||||||
|
|
||||||
|
if (addressList.length === 0) {
|
||||||
|
Message.error('请输入至少一个设备地址');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证必要字段
|
||||||
|
if (!formValues.ioTPlatform) {
|
||||||
|
Message.error('请选择平台类型');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formValues.ioTPlatformProductId) {
|
||||||
|
Message.error('请选择产品');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证目标版本
|
||||||
|
if (!formValues.targetVersionId) {
|
||||||
|
Message.error('请选择目标版本');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
batchUpgradeModalApi.setState({ loading: true, confirmLoading: true });
|
||||||
|
|
||||||
|
// 调用批量升级接口
|
||||||
|
const result = await postAggregationDeviceDeviceBatchUpgradeForApiAsync({
|
||||||
|
body: {
|
||||||
|
addressList,
|
||||||
|
ioTPlatform:
|
||||||
|
typeof formValues.ioTPlatform === 'string'
|
||||||
|
? Number.parseInt(formValues.ioTPlatform)
|
||||||
|
: formValues.ioTPlatform,
|
||||||
|
ioTPlatformProductId: String(formValues.ioTPlatformProductId),
|
||||||
|
nowFirmwareVersionDataId: formValues.targetVersionId,
|
||||||
|
upgradeDescription: formValues.upgradeDescription || null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.data) {
|
||||||
|
Message.success(`批量升级任务已提交,共 ${addressList.length} 个设备`);
|
||||||
|
batchUpgradeModalApi.close();
|
||||||
|
batchUpgradeFormApi.resetForm();
|
||||||
|
gridApi.reload();
|
||||||
|
} else {
|
||||||
|
Message.error('批量升级失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('批量升级失败:', error);
|
||||||
|
Message.error('批量升级失败');
|
||||||
|
} finally {
|
||||||
|
batchUpgradeModalApi.setState({ loading: false, confirmLoading: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量升级地址行数
|
||||||
|
const batchUpgradeAddressLines = ref(0);
|
||||||
|
|
||||||
|
// 监听批量升级表单值变化,实时更新行数
|
||||||
|
watch(
|
||||||
|
() => batchUpgradeFormApi.getValues()?.addressList,
|
||||||
|
(newValue) => {
|
||||||
|
try {
|
||||||
|
if (!newValue || typeof newValue !== 'string') {
|
||||||
|
batchUpgradeAddressLines.value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lines = newValue.split('\n').filter((line: string) => line.trim());
|
||||||
|
batchUpgradeAddressLines.value = lines.length;
|
||||||
|
} catch {
|
||||||
|
batchUpgradeAddressLines.value = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听表单值变化,实时更新行数(备用方案)
|
||||||
|
watch(
|
||||||
|
() => batchUpgradeFormApi.getValues(),
|
||||||
|
(formValues) => {
|
||||||
|
try {
|
||||||
|
const addressList = formValues?.addressList;
|
||||||
|
if (!addressList || typeof addressList !== 'string') {
|
||||||
|
batchUpgradeAddressLines.value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lines = addressList
|
||||||
|
.split('\n')
|
||||||
|
.filter((line: string) => line.trim());
|
||||||
|
batchUpgradeAddressLines.value = lines.length;
|
||||||
|
} catch {
|
||||||
|
batchUpgradeAddressLines.value = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用定时器定期检查批量升级行数(第三种方案)
|
||||||
|
let batchUpgradeLineCheckInterval: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
|
// 在批量升级模态框打开时启动定时器
|
||||||
|
const startBatchUpgradeLineCheck = () => {
|
||||||
|
if (batchUpgradeLineCheckInterval) {
|
||||||
|
clearInterval(batchUpgradeLineCheckInterval);
|
||||||
|
}
|
||||||
|
batchUpgradeLineCheckInterval = setInterval(() => {
|
||||||
|
try {
|
||||||
|
// 尝试多种方式获取表单值
|
||||||
|
let addressList = '';
|
||||||
|
|
||||||
|
// 方式1:直接获取
|
||||||
|
const formValues = batchUpgradeFormApi.getValues();
|
||||||
|
addressList = formValues?.addressList || '';
|
||||||
|
|
||||||
|
// 方式2:如果方式1失败,尝试其他方法
|
||||||
|
if (!addressList) {
|
||||||
|
try {
|
||||||
|
const rawValues = batchUpgradeFormApi.getValues();
|
||||||
|
addressList = rawValues?.addressList || '';
|
||||||
|
} catch (error) {
|
||||||
|
console.log('方式2失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方式3:直接从DOM获取
|
||||||
|
if (!addressList) {
|
||||||
|
const textarea = document.querySelector(
|
||||||
|
'textarea[name="addressList"]',
|
||||||
|
) as HTMLTextAreaElement;
|
||||||
|
if (textarea) {
|
||||||
|
addressList = textarea.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressList && typeof addressList === 'string') {
|
||||||
|
const lines = addressList
|
||||||
|
.split('\n')
|
||||||
|
.filter((line: string) => line.trim());
|
||||||
|
const newLineCount = lines.length;
|
||||||
|
console.log(
|
||||||
|
'批量升级计算出的行数:',
|
||||||
|
newLineCount,
|
||||||
|
'当前行数:',
|
||||||
|
batchUpgradeAddressLines.value,
|
||||||
|
);
|
||||||
|
// 无论是否相同都更新,确保响应式触发
|
||||||
|
if (newLineCount !== batchUpgradeAddressLines.value) {
|
||||||
|
console.log('批量升级更新行数:', newLineCount);
|
||||||
|
batchUpgradeAddressLines.value = newLineCount;
|
||||||
|
// 使用 nextTick 确保 DOM 更新
|
||||||
|
nextTick(() => {
|
||||||
|
console.log(
|
||||||
|
'批量升级行数已更新到:',
|
||||||
|
batchUpgradeAddressLines.value,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果地址列表为空,重置为0
|
||||||
|
if (batchUpgradeAddressLines.value !== 0) {
|
||||||
|
batchUpgradeAddressLines.value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('定时器检查批量升级行数失败:', error);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 在批量升级模态框关闭时清除定时器
|
||||||
|
const stopBatchUpgradeLineCheck = () => {
|
||||||
|
if (batchUpgradeLineCheckInterval) {
|
||||||
|
clearInterval(batchUpgradeLineCheckInterval);
|
||||||
|
batchUpgradeLineCheckInterval = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开批量升级弹窗
|
||||||
|
const openBatchUpgradeModal = () => {
|
||||||
|
batchUpgradeFormApi.resetForm();
|
||||||
|
batchUpgradeAddressLines.value = 0; // 重置行数
|
||||||
|
batchUpgradeModalApi.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const [BatchUpgradeModal, batchUpgradeModalApi] = useVbenModal({
|
||||||
|
draggable: true,
|
||||||
|
onConfirm: submitBatchUpgrade,
|
||||||
|
onBeforeClose: () => {
|
||||||
|
batchUpgradeFormApi.resetForm();
|
||||||
|
batchUpgradeAddressLines.value = 0; // 重置行数
|
||||||
|
stopBatchUpgradeLineCheck();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onOpenChange: (isOpen) => {
|
||||||
|
if (isOpen) {
|
||||||
|
// 模态框打开时启动行数检查
|
||||||
|
setTimeout(() => {
|
||||||
|
startBatchUpgradeLineCheck();
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
// 模态框关闭时停止行数检查
|
||||||
|
stopBatchUpgradeLineCheck();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取批量升级模态框的状态
|
||||||
|
const batchUpgradeModalState = batchUpgradeModalApi.useStore();
|
||||||
|
|
||||||
// 设备升级表单
|
// 设备升级表单
|
||||||
const [UpgradeForm, upgradeFormApi] = useVbenForm({
|
const [UpgradeForm, upgradeFormApi] = useVbenForm({
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
@ -1640,6 +1892,13 @@ const toolbarActions = computed(() => [
|
|||||||
onClick: openBatchBindModal,
|
onClick: openBatchBindModal,
|
||||||
auth: ['AbpIdentity.Users.Create'],
|
auth: ['AbpIdentity.Users.Create'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '批量升级',
|
||||||
|
type: 'default',
|
||||||
|
icon: 'ant-design:link-outlined',
|
||||||
|
onClick: openBatchUpgradeModal,
|
||||||
|
auth: ['AbpIdentity.Users.Create'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: cacheRefreshLoading.value
|
label: cacheRefreshLoading.value
|
||||||
? $t('common.loading')
|
? $t('common.loading')
|
||||||
@ -1820,5 +2079,26 @@ const toolbarActions = computed(() => [
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</BatchAddModal>
|
</BatchAddModal>
|
||||||
|
<BatchUpgradeModal title="批量升级设备" class="w-[800px]">
|
||||||
|
<BatchUpgradeForm />
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex w-full items-center justify-between">
|
||||||
|
<div class="text-sm text-gray-500">
|
||||||
|
<span v-if="batchUpgradeAddressLines > 0">
|
||||||
|
共 {{ batchUpgradeAddressLines }} 个设备地址
|
||||||
|
</span>
|
||||||
|
<span v-else> 当前设备地址数: {{ batchUpgradeAddressLines }} </span>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button @click="batchUpgradeModalApi.close()">
|
||||||
|
{{ $t('common.cancel') }}
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" :loading="batchUpgradeModalState?.confirmLoading" @click="submitBatchUpgrade">
|
||||||
|
{{ $t('common.confirm') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BatchUpgradeModal>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -941,3 +941,249 @@ export const batchAddDeviceFormSchema: any = computed(() => [
|
|||||||
rules: z.string().optional(),
|
rules: z.string().optional(),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 批量设备升级表单
|
||||||
|
export const batchUpgradeDeviceFormSchema: any = computed(() => [
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
fieldName: 'addressList',
|
||||||
|
label: '设备地址列表',
|
||||||
|
componentProps: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: '请输入设备地址,每行一个设备地址',
|
||||||
|
showCount: false,
|
||||||
|
maxLength: 10_000,
|
||||||
|
style: {
|
||||||
|
resize: 'vertical',
|
||||||
|
minHeight: '32px',
|
||||||
|
maxHeight: '200px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: '请输入设备地址',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'ApiSelect',
|
||||||
|
fieldName: 'ioTPlatform',
|
||||||
|
label: $t('abp.deviceInfos.ioTPlatform'),
|
||||||
|
componentProps: {
|
||||||
|
api: getCommonGetSelectList,
|
||||||
|
params: {
|
||||||
|
query: {
|
||||||
|
typeName: 'IoTPlatformTypeEnum',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
labelField: 'value',
|
||||||
|
valueField: 'key',
|
||||||
|
optionsPropName: 'options',
|
||||||
|
immediate: true,
|
||||||
|
allowClear: true,
|
||||||
|
placeholder:
|
||||||
|
$t('common.pleaseSelect') + $t('abp.deviceInfos.ioTPlatform'),
|
||||||
|
afterFetch: (res: any) => {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (res && Array.isArray(res.items)) {
|
||||||
|
return res.items;
|
||||||
|
}
|
||||||
|
if (res && Array.isArray(res.data)) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: z.string().min(1, {
|
||||||
|
message: `${$t('common.pleaseSelect')}${$t('abp.deviceInfos.ioTPlatform')}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'ApiSelect',
|
||||||
|
fieldName: 'ioTPlatformAccountId',
|
||||||
|
label: $t('abp.deviceInfos.ioTPlatformAccountName'),
|
||||||
|
dependencies: {
|
||||||
|
show(values: any) {
|
||||||
|
return !!values.ioTPlatform;
|
||||||
|
},
|
||||||
|
rules(values: any) {
|
||||||
|
if (values.ioTPlatform) {
|
||||||
|
return 'required';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
triggerFields: ['ioTPlatform'],
|
||||||
|
},
|
||||||
|
componentProps: (formValues: any) => {
|
||||||
|
const platform = formValues?.ioTPlatform;
|
||||||
|
|
||||||
|
return {
|
||||||
|
api: platform
|
||||||
|
? postAggregationIoTplatformGetIoTplatformAccountInfoAsync
|
||||||
|
: null,
|
||||||
|
params: platform
|
||||||
|
? {
|
||||||
|
body: {
|
||||||
|
ioTPlatformType:
|
||||||
|
typeof platform === 'string'
|
||||||
|
? Number.parseInt(platform)
|
||||||
|
: platform,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
labelField: 'ioTPlatformPhoneNumber',
|
||||||
|
valueField: 'ioTPlatformAccountId',
|
||||||
|
optionsPropName: 'options',
|
||||||
|
immediate: false,
|
||||||
|
allowClear: true,
|
||||||
|
placeholder:
|
||||||
|
$t('common.pleaseSelect') +
|
||||||
|
$t('abp.deviceInfos.ioTPlatformAccountName'),
|
||||||
|
afterFetch: (res: any) => {
|
||||||
|
let items: any[] = [];
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
items = res;
|
||||||
|
} else if (res && Array.isArray(res.items)) {
|
||||||
|
items = res.items;
|
||||||
|
} else if (res && Array.isArray(res.data)) {
|
||||||
|
items = res.data;
|
||||||
|
} else if (res && res.data && Array.isArray(res.data.items)) {
|
||||||
|
items = res.data.items;
|
||||||
|
}
|
||||||
|
return items.map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
ioTPlatformAccountId: item.ioTPlatformAccount,
|
||||||
|
label: item.ioTPlatformPhoneNumber || item.ioTPlatformAccount || '',
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
rules: z.string().optional(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'ApiSelect',
|
||||||
|
fieldName: 'ioTPlatformProductId',
|
||||||
|
label: $t('abp.deviceInfos.ioTPlatformProductName'),
|
||||||
|
dependencies: {
|
||||||
|
show(values: any) {
|
||||||
|
return !!values.ioTPlatform && !!values.ioTPlatformAccountId;
|
||||||
|
},
|
||||||
|
rules(values: any) {
|
||||||
|
if (values.ioTPlatform && values.ioTPlatformAccountId) {
|
||||||
|
return 'required';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
triggerFields: ['ioTPlatform', 'ioTPlatformAccountId'],
|
||||||
|
},
|
||||||
|
componentProps: (formValues: any) => {
|
||||||
|
const platform = formValues?.ioTPlatform;
|
||||||
|
const accountId = formValues?.ioTPlatformAccountId;
|
||||||
|
|
||||||
|
return {
|
||||||
|
api:
|
||||||
|
platform && accountId
|
||||||
|
? postAggregationIoTplatformGetIoTplatformProductInfoAsync
|
||||||
|
: null,
|
||||||
|
params:
|
||||||
|
platform && accountId
|
||||||
|
? {
|
||||||
|
body: {
|
||||||
|
ioTPlatformType:
|
||||||
|
typeof platform === 'string'
|
||||||
|
? Number.parseInt(platform)
|
||||||
|
: platform,
|
||||||
|
ioTPlatformAccount: accountId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
labelField: 'productName',
|
||||||
|
valueField: 'ioTPlatformProductId',
|
||||||
|
optionsPropName: 'options',
|
||||||
|
immediate: false,
|
||||||
|
allowClear: true,
|
||||||
|
placeholder:
|
||||||
|
$t('common.pleaseSelect') +
|
||||||
|
$t('abp.deviceInfos.ioTPlatformProductName'),
|
||||||
|
afterFetch: (res: any) => {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (res && Array.isArray(res.items)) {
|
||||||
|
return res.items;
|
||||||
|
}
|
||||||
|
if (res && Array.isArray(res.data)) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
if (res && res.data && Array.isArray(res.data.items)) {
|
||||||
|
return res.data.items;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
rules: z.string().optional(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'ApiSelect',
|
||||||
|
fieldName: 'targetVersionId',
|
||||||
|
label: '目标版本',
|
||||||
|
dependencies: {
|
||||||
|
show(values: any) {
|
||||||
|
return !!values.ioTPlatformProductId;
|
||||||
|
},
|
||||||
|
rules(values: any) {
|
||||||
|
if (values.ioTPlatformProductId) {
|
||||||
|
return 'required';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
triggerFields: ['ioTPlatformProductId'],
|
||||||
|
},
|
||||||
|
componentProps: (formValues: any) => {
|
||||||
|
const productId = formValues?.ioTPlatformProductId;
|
||||||
|
|
||||||
|
return {
|
||||||
|
api: productId ? postFirmwareInfoFindByDeviceProductIdAsync : null,
|
||||||
|
params: productId
|
||||||
|
? {
|
||||||
|
query: {
|
||||||
|
id: String(productId),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
labelField: 'firmwareVersion',
|
||||||
|
valueField: 'id',
|
||||||
|
optionsPropName: 'options',
|
||||||
|
immediate: false,
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择目标版本',
|
||||||
|
afterFetch: (res: any) => {
|
||||||
|
let firmwareList: any[] = [];
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
firmwareList = res;
|
||||||
|
} else if (res && Array.isArray(res.items)) {
|
||||||
|
firmwareList = res.items;
|
||||||
|
} else if (res && Array.isArray(res.data)) {
|
||||||
|
firmwareList = res.data;
|
||||||
|
} else if (res && res.data && Array.isArray(res.data.items)) {
|
||||||
|
firmwareList = res.data.items;
|
||||||
|
}
|
||||||
|
return firmwareList.filter((item: any) => item.isEnable === true);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
rules: z.string().optional(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Textarea',
|
||||||
|
fieldName: 'upgradeDescription',
|
||||||
|
label: '升级说明',
|
||||||
|
componentProps: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: '请输入升级说明(可选)',
|
||||||
|
maxLength: 500,
|
||||||
|
showCount: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user