diff --git a/apps/web-antd/src/api/iot/device/device/index.ts b/apps/web-antd/src/api/iot/device/device/index.ts index 7bd59886f..a0d4659b0 100644 --- a/apps/web-antd/src/api/iot/device/device/index.ts +++ b/apps/web-antd/src/api/iot/device/device/index.ts @@ -77,14 +77,6 @@ export namespace IotDeviceApi { } } -/** IoT 设备状态枚举 */ -// TODO @haohao:packages/constants/src/biz-iot-enum.ts 枚举; -export enum DeviceStateEnum { - INACTIVE = 0, // 未激活 - OFFLINE = 2, // 离线 - ONLINE = 1, // 在线 -} - /** 查询设备分页 */ export function getDevicePage(params: PageParam) { return requestClient.get>( @@ -154,6 +146,14 @@ export function importDeviceTemplate() { return requestClient.download('/iot/device/get-import-template'); } +/** 导入设备 */ +export function importDevice(file: File, updateSupport: boolean) { + return requestClient.upload('/iot/device/import', { + file, + updateSupport, + }); +} + /** 获取设备属性最新数据 */ export function getLatestDeviceProperties(params: any) { return requestClient.get( diff --git a/apps/web-antd/src/api/iot/product/product/index.ts b/apps/web-antd/src/api/iot/product/product/index.ts index bf5682d2d..2833b1e5d 100644 --- a/apps/web-antd/src/api/iot/product/product/index.ts +++ b/apps/web-antd/src/api/iot/product/product/index.ts @@ -27,33 +27,6 @@ export namespace IotProductApi { } } -// TODO @haohao:packages/constants/src/biz-iot-enum.ts 枚举; - -/** IOT 产品设备类型枚举类 */ -export enum DeviceTypeEnum { - DEVICE = 0, // 直连设备 - GATEWAY = 2, // 网关设备 - GATEWAY_SUB = 1, // 网关子设备 -} - -/** IOT 产品定位类型枚举类 */ -export enum LocationTypeEnum { - IP = 1, // IP 定位 - MANUAL = 3, // 手动定位 - MODULE = 2, // 设备定位 -} - -/** IOT 数据格式(编解码器类型)枚举类 */ -export enum CodecTypeEnum { - ALINK = 'Alink', // 阿里云 Alink 协议 -} - -/** IOT 产品状态枚举类 */ -export enum ProductStatusEnum { - UNPUBLISHED = 0, // 开发中 - PUBLISHED = 1, // 已发布 -} - /** 查询产品分页 */ export function getProductPage(params: PageParam) { return requestClient.get>( diff --git a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue index 5d92119a9..eb7a1d1ec 100644 --- a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue +++ b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/ElementListeners.vue @@ -48,20 +48,25 @@ const editingListenerIndex = ref(-1); // 监听器所在下标,-1 为新增 const editingListenerFieldIndex = ref(-1); // 字段所在下标,-1 为新增 const listenerTypeObject = ref(listenerType); const fieldTypeObject = ref(fieldType); -const bpmnElement = ref(); const otherExtensionList = ref(); const bpmnElementListeners = ref(); const listenerFormRef = ref(); const bpmnInstances = () => (window as any)?.bpmnInstances; const resetListenersList = () => { - bpmnElement.value = bpmnInstances().bpmnElement; + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + // 直接使用原始BPMN元素,避免Vue响应式代理问题 + const bpmnElement = instances.bpmnElement; + const businessObject = bpmnElement.businessObject; + otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:ExecutionListener`, ) ?? []; // 保留非监听器类型的扩展属性,避免移除监听器时清空其他配置(如审批人等)。相关案例:https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues/ICMSYC bpmnElementListeners.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type === `${prefix}:ExecutionListener`, ) ?? []; elementListenersList.value = bpmnElementListeners.value.map((listener: any) => @@ -126,9 +131,11 @@ const removeListener = (index: number) => { title: '提示', content: '确认移除该监听器吗?', }).then(() => { + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; bpmnElementListeners.value.splice(index, 1); elementListenersList.value.splice(index, 1); - updateElementExtensions(bpmnElement.value, [ + updateElementExtensions(instances.bpmnElement, [ ...otherExtensionList.value, ...bpmnElementListeners.value, ]); @@ -146,6 +153,12 @@ const saveListenerConfig = async () => { false, prefix, ); + + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + const bpmnElement = instances.bpmnElement; + if (editingListenerIndex.value === -1) { bpmnElementListeners.value.push(listenerObject); elementListenersList.value.push(listenerForm.value); @@ -162,10 +175,10 @@ const saveListenerConfig = async () => { ); } otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + bpmnElement.businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:ExecutionListener`, ) ?? []; - updateElementExtensions(bpmnElement.value, [ + updateElementExtensions(bpmnElement, [ ...otherExtensionList.value, ...bpmnElementListeners.value, ]); @@ -266,6 +279,10 @@ const openProcessListenerDialog = async () => { processListenerSelectModalApi.setData({ type: 'execution' }).open(); }; const selectProcessListener = (listener: any) => { + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + const bpmnElement = instances.bpmnElement; const listenerForm = initListenerForm2(listener); const listenerObject = createListenerObject(listenerForm, false, prefix); bpmnElementListeners.value.push(listenerObject); @@ -273,10 +290,10 @@ const selectProcessListener = (listener: any) => { // 保存其他配置 otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + bpmnElement.businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:ExecutionListener`, ) ?? []; - updateElementExtensions(bpmnElement.value, [ + updateElementExtensions(bpmnElement, [ ...otherExtensionList.value, ...bpmnElementListeners.value, ]); diff --git a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue index 310435f78..ba5747d08 100644 --- a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue +++ b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/listeners/UserTaskListeners.vue @@ -48,7 +48,6 @@ const fieldTypeObject = ref(fieldType); const fieldsListOfListener = ref([]); const editingListenerIndex = ref(-1); const editingListenerFieldIndex = ref(-1); -const bpmnElement = ref(); const bpmnElementListeners = ref([]); const otherExtensionList = ref([]); const listenerFormRef = ref({}); @@ -56,13 +55,19 @@ const listenerFormRef = ref({}); const bpmnInstances = () => (window as any)?.bpmnInstances; const resetListenersList = () => { - bpmnElement.value = bpmnInstances()?.bpmnElement; + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + // 直接使用原始BPMN元素,避免Vue响应式代理问题 + const bpmnElement = instances.bpmnElement; + const businessObject = bpmnElement.businessObject; + otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:TaskListener`, ) ?? []; bpmnElementListeners.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type === `${prefix}:TaskListener`, ) ?? []; elementListenersList.value = bpmnElementListeners.value.map((listener) => @@ -98,9 +103,12 @@ const removeListener = (_: any, index: number) => { title: '提示', content: '确认移除该监听器吗?', }).then(() => { + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + bpmnElementListeners.value.splice(index, 1); elementListenersList.value.splice(index, 1); - updateElementExtensions(bpmnElement.value, [ + updateElementExtensions(instances.bpmnElement, [ ...otherExtensionList.value, ...bpmnElementListeners.value, ]); @@ -113,7 +121,13 @@ async function saveListenerConfig() { } catch { return; } + + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + const bpmnElement = instances.bpmnElement; const listenerObject = createListenerObject(listenerForm.value, true, prefix); + if (editingListenerIndex.value === -1) { bpmnElementListeners.value.push(listenerObject); elementListenersList.value.push(listenerForm.value); @@ -130,10 +144,10 @@ async function saveListenerConfig() { ); } otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + bpmnElement.businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:TaskListener`, ) ?? []; - updateElementExtensions(bpmnElement.value, [ + updateElementExtensions(bpmnElement, [ ...otherExtensionList.value, ...bpmnElementListeners.value, ]); @@ -209,6 +223,10 @@ const openProcessListenerDialog = async () => { processListenerSelectModalApi.setData({ type: 'task' }).open(); }; const selectProcessListener = (listener: any) => { + const instances = bpmnInstances(); + if (!instances || !instances.bpmnElement) return; + + const bpmnElement = instances.bpmnElement; const listenerForm = initListenerForm2(listener); listenerForm.id = listener.id; const listenerObject = createListenerObject(listenerForm, true, prefix); @@ -216,11 +234,11 @@ const selectProcessListener = (listener: any) => { elementListenersList.value.push(listenerForm); otherExtensionList.value = - bpmnElement.value.businessObject?.extensionElements?.values?.filter( + bpmnElement.businessObject?.extensionElements?.values?.filter( (ex: any) => ex.$type !== `${prefix}:TaskListener`, ) ?? []; updateElementExtensions( - bpmnElement.value, + bpmnElement, otherExtensionList.value?.concat(bpmnElementListeners.value), ); }; diff --git a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue index 09d53d377..beae93e1b 100644 --- a/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue +++ b/apps/web-antd/src/views/bpm/components/bpmn-process-designer/package/penal/properties/ElementProperties.vue @@ -1,5 +1,5 @@ + + + + diff --git a/apps/web-antd/src/views/iot/device/device/modules/components/device-table-select.vue b/apps/web-antd/src/views/iot/device/device/modules/components/device-table-select.vue deleted file mode 100644 index 8f8afc3e0..000000000 --- a/apps/web-antd/src/views/iot/device/device/modules/components/device-table-select.vue +++ /dev/null @@ -1,402 +0,0 @@ - - - - diff --git a/apps/web-antd/src/views/iot/device/device/modules/detail/index.vue b/apps/web-antd/src/views/iot/device/device/modules/detail/index.vue index d8bf6a095..ac1ede8cd 100644 --- a/apps/web-antd/src/views/iot/device/device/modules/detail/index.vue +++ b/apps/web-antd/src/views/iot/device/device/modules/detail/index.vue @@ -7,20 +7,21 @@ import { onMounted, ref } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import { Page } from '@vben/common-ui'; +import { DeviceTypeEnum } from '@vben/constants'; import { message, Tabs } from 'ant-design-vue'; import { getDevice } from '#/api/iot/device/device'; -import { DeviceTypeEnum, getProduct } from '#/api/iot/product/product'; +import { getProduct } from '#/api/iot/product/product'; import { getThingModelListByProductId } from '#/api/iot/thingmodel'; -import DeviceDetailConfig from './device-detail-config.vue'; -import DeviceDetailsHeader from './device-details-header.vue'; -import DeviceDetailsInfo from './device-details-info.vue'; -import DeviceDetailsMessage from './device-details-message.vue'; -import DeviceDetailsSimulator from './device-details-simulator.vue'; -import DeviceDetailsSubDevice from './device-details-sub-device.vue'; -import DeviceDetailsThingModel from './device-details-thing-model.vue'; +import DeviceDetailConfig from './modules/config.vue'; +import DeviceDetailsHeader from './modules/header.vue'; +import DeviceDetailsInfo from './modules/info.vue'; +import DeviceDetailsMessage from './modules/message.vue'; +import DeviceDetailsSimulator from './modules/simulator.vue'; +import DeviceDetailsSubDevice from './modules/sub-device.vue'; +import DeviceDetailsThingModel from './modules/thing-model.vue'; defineOptions({ name: 'IoTDeviceDetail' }); @@ -34,6 +35,8 @@ const device = ref({} as IotDeviceApi.Device); const activeTab = ref('info'); const thingModelList = ref([]); +// TODO @haohao:类似 device/detail/index.vue 挪出去哈。 + /** 获取设备详情 */ async function getDeviceData(deviceId: number) { loading.value = true; @@ -52,8 +55,8 @@ async function getDeviceData(deviceId: number) { async function getProductData(productId: number) { try { product.value = await getProduct(productId); - } catch (error) { - console.error('获取产品详情失败:', error); + } catch { + message.error('获取产品详情失败'); } } @@ -62,8 +65,8 @@ async function getThingModelList(productId: number) { try { const data = await getThingModelListByProductId(productId); thingModelList.value = data || []; - } catch (error) { - console.error('获取物模型列表失败:', error); + } catch { + message.error('获取物模型列表失败'); thingModelList.value = []; } } diff --git a/apps/web-antd/src/views/iot/device/device/modules/detail/device-detail-config.vue b/apps/web-antd/src/views/iot/device/device/modules/detail/modules/config.vue similarity index 92% rename from apps/web-antd/src/views/iot/device/device/modules/detail/device-detail-config.vue rename to apps/web-antd/src/views/iot/device/device/modules/detail/modules/config.vue index 6fa449022..f24fc0627 100644 --- a/apps/web-antd/src/views/iot/device/device/modules/detail/device-detail-config.vue +++ b/apps/web-antd/src/views/iot/device/device/modules/detail/modules/config.vue @@ -56,14 +56,14 @@ const hasConfigData = computed(() => { }); /** 启用编辑模式的函数 */ -function enableEdit() { +function handleEdit() { isEditing.value = true; // 重新同步编辑器内容 configString.value = JSON.stringify(config.value, null, 2); } /** 取消编辑的函数 */ -function cancelEdit() { +function handleCancelEdit() { try { config.value = props.device.config ? JSON.parse(props.device.config) : {}; configString.value = JSON.stringify(config.value, null, 2); @@ -84,29 +84,23 @@ async function saveConfig() { message.error({ content: 'JSON格式错误,请修正后再提交!' }); return; } - + // TODO @haohao:这里要不要做个类似下面的 pushLoading 避免重复提交; await updateDeviceConfig(); isEditing.value = false; } /** 配置推送处理函数 */ async function handleConfigPush() { + pushLoading.value = true; try { - pushLoading.value = true; - // 调用配置推送接口 await sendDeviceMessage({ deviceId: props.device.id!, method: IotDeviceMessageMethodEnum.CONFIG_PUSH.method, params: config.value, }); - + // 提示成功 message.success({ content: '配置推送成功!' }); - } catch (error) { - if (error !== 'cancel') { - message.error({ content: '配置推送失败!' }); - console.error('配置推送错误:', error); - } } finally { pushLoading.value = false; } @@ -124,8 +118,6 @@ async function updateDeviceConfig() { message.success({ content: '更新成功!' }); // 触发 success 事件 emit('success'); - } catch (error) { - console.error(error); } finally { loading.value = false; } @@ -143,8 +135,9 @@ async function updateDeviceConfig() { class="my-4" description="如需编辑文件,请点击下方编辑按钮" /> +
- + - +