Commit 3bf5203619839108a860a64453256cd2973c4db9
Merge branch 'main_dev' into 'main'
fix: 修复更改设备类型为网关子设备时关联网关设备组织关系 See merge request yunteng/thingskit-front!1121
Showing
6 changed files
with
81 additions
and
65 deletions
| @@ -49,6 +49,7 @@ enum DeviceUrl { | @@ -49,6 +49,7 @@ enum DeviceUrl { | ||
| 49 | GET_DEVICE_ATTRIBUTE = '/device/attributes', | 49 | GET_DEVICE_ATTRIBUTE = '/device/attributes', |
| 50 | GET_DEVICE = '/device/list', | 50 | GET_DEVICE = '/device/list', |
| 51 | GET_DEVICE_RELATION = '/device/device/relation', | 51 | GET_DEVICE_RELATION = '/device/device/relation', |
| 52 | + GET_GATEWAY_LIST = '/device/gateway/list', | ||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | /** | 55 | /** |
| @@ -240,6 +241,15 @@ export const sendCommandTwoway = (params: SendCommandParams) => { | @@ -240,6 +241,15 @@ export const sendCommandTwoway = (params: SendCommandParams) => { | ||
| 240 | ); | 241 | ); |
| 241 | }; | 242 | }; |
| 242 | 243 | ||
| 244 | +export const getMeetTheConditionsGatewayDevice = ( | ||
| 245 | + params?: Partial<Record<'organizationId' | 'transportType', string>> | ||
| 246 | +) => { | ||
| 247 | + return defHttp.get<DeviceRecord[]>({ | ||
| 248 | + url: DeviceUrl.GET_GATEWAY_LIST, | ||
| 249 | + params, | ||
| 250 | + }); | ||
| 251 | +}; | ||
| 252 | + | ||
| 243 | export const getDeviceRelation = (params: { deviceId: string; isSlave: boolean }) => { | 253 | export const getDeviceRelation = (params: { deviceId: string; isSlave: boolean }) => { |
| 244 | return defHttp.get<string>({ | 254 | return defHttp.get<string>({ |
| 245 | url: DeviceUrl.GET_DEVICE_RELATION, | 255 | url: DeviceUrl.GET_DEVICE_RELATION, |
| @@ -186,6 +186,7 @@ export interface DeviceRecord { | @@ -186,6 +186,7 @@ export interface DeviceRecord { | ||
| 186 | alias?: string; | 186 | alias?: string; |
| 187 | brand?: string; | 187 | brand?: string; |
| 188 | deviceProfileId: string; | 188 | deviceProfileId: string; |
| 189 | + organizationId: string; | ||
| 189 | deviceProfile: { | 190 | deviceProfile: { |
| 190 | default: boolean; | 191 | default: boolean; |
| 191 | name: string; | 192 | name: string; |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | import { ApiTreeSelect } from '/@/components/Form'; | 2 | import { ApiTreeSelect } from '/@/components/Form'; |
| 3 | import { Button } from 'ant-design-vue'; | 3 | import { Button } from 'ant-design-vue'; |
| 4 | import { getOrganizationList } from '/@/api/system/system'; | 4 | import { getOrganizationList } from '/@/api/system/system'; |
| 5 | - import { computed, ref, unref } from 'vue'; | 5 | + import { computed, ref, unref, watch } from 'vue'; |
| 6 | import OrganizationDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; | 6 | import OrganizationDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; |
| 7 | import { useDrawer } from '/@/components/Drawer'; | 7 | import { useDrawer } from '/@/components/Drawer'; |
| 8 | import { OrganizationListItem } from '/@/api/system/model/systemModel'; | 8 | import { OrganizationListItem } from '/@/api/system/model/systemModel'; |
| @@ -79,6 +79,11 @@ | @@ -79,6 +79,11 @@ | ||
| 79 | needReload.value = true; | 79 | needReload.value = true; |
| 80 | timespan.value = Date.now(); | 80 | timespan.value = Date.now(); |
| 81 | }; | 81 | }; |
| 82 | + | ||
| 83 | + watch( | ||
| 84 | + () => props.apiTreeSelectProps, | ||
| 85 | + () => handleReload() | ||
| 86 | + ); | ||
| 82 | </script> | 87 | </script> |
| 83 | 88 | ||
| 84 | <template> | 89 | <template> |
| @@ -4,10 +4,10 @@ import { getGatewayDevice, queryDeviceProfileBy } from '/@/api/device/deviceMana | @@ -4,10 +4,10 @@ import { getGatewayDevice, queryDeviceProfileBy } from '/@/api/device/deviceMana | ||
| 4 | import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const'; | 4 | import { TransportTypeEnum } from '../../profiles/components/TransportDescript/const'; |
| 5 | import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; | 5 | import { JSONEditorValidator } from '/@/components/CodeEditor/src/JSONEditor'; |
| 6 | import { JSONEditor } from '/@/components/CodeEditor'; | 6 | import { JSONEditor } from '/@/components/CodeEditor'; |
| 7 | -import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 7 | +import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
| 8 | import { getModelServices } from '/@/api/device/modelOfMatter'; | 8 | import { getModelServices } from '/@/api/device/modelOfMatter'; |
| 9 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | 9 | import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; |
| 10 | -import { h, nextTick, toRaw, unref } from 'vue'; | 10 | +import { h, toRaw, unref } from 'vue'; |
| 11 | import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; | 11 | import ObjectModelValidateForm from '/@/components/Form/src/externalCompns/components/ObjectModelValidateForm/ObjectModelValidateForm.vue'; |
| 12 | import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; | 12 | import { CommandDeliveryWayEnum, ServiceCallTypeEnum } from '/@/enums/toolEnum'; |
| 13 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 13 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
| @@ -15,9 +15,6 @@ import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInpu | @@ -15,9 +15,6 @@ import { AddressTypeEnum } from '/@/views/task/center/components/PollCommandInpu | ||
| 15 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | 15 | import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; |
| 16 | import { createImgPreview } from '/@/components/Preview'; | 16 | import { createImgPreview } from '/@/components/Preview'; |
| 17 | import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter'; | 17 | import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter'; |
| 18 | - | ||
| 19 | -import { getOrganizationList } from '/@/api/system/system'; | ||
| 20 | -import { copyTransFun } from '/@/utils/fnUtils'; | ||
| 21 | import LockControlGroup from '/@/components/Form/src/components/LockControlGroup.vue'; | 18 | import LockControlGroup from '/@/components/Form/src/components/LockControlGroup.vue'; |
| 22 | import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; | 19 | import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; |
| 23 | 20 | ||
| @@ -305,7 +302,7 @@ export const step1Schemas: FormSchema[] = [ | @@ -305,7 +302,7 @@ export const step1Schemas: FormSchema[] = [ | ||
| 305 | ifShow: ({ values }) => values.deviceType === 'SENSOR', | 302 | ifShow: ({ values }) => values.deviceType === 'SENSOR', |
| 306 | componentProps: ({ formModel, formActionType }) => { | 303 | componentProps: ({ formModel, formActionType }) => { |
| 307 | const { transportType } = formModel; | 304 | const { transportType } = formModel; |
| 308 | - const { validateFields } = formActionType; | 305 | + const { setFieldsValue } = formActionType; |
| 309 | if (!transportType) return {}; | 306 | if (!transportType) return {}; |
| 310 | return { | 307 | return { |
| 311 | api: async (params: Recordable) => { | 308 | api: async (params: Recordable) => { |
| @@ -320,22 +317,23 @@ export const step1Schemas: FormSchema[] = [ | @@ -320,22 +317,23 @@ export const step1Schemas: FormSchema[] = [ | ||
| 320 | params: { | 317 | params: { |
| 321 | transportType, | 318 | transportType, |
| 322 | }, | 319 | }, |
| 320 | + placeholder: '请选择网关设备', | ||
| 323 | valueField: 'tbDeviceId', | 321 | valueField: 'tbDeviceId', |
| 324 | labelField: 'alias', | 322 | labelField: 'alias', |
| 325 | - onChange: async (value, options) => { | ||
| 326 | - await nextTick(); | ||
| 327 | - if (value) { | ||
| 328 | - const data = await getOrganizationList({ organizationId: options?.organizationId }); | ||
| 329 | - copyTransFun(data as any as any[]); | ||
| 330 | - formModel.organizationList = data; | 323 | + onChange: async (_value: string, option: DeviceRecord) => { |
| 324 | + setFieldsValue({ sensorOrganizationId: option?.organizationId, organizationId: null }); | ||
| 325 | + }, | ||
| 326 | + onOptionsChange(options: (DeviceRecord & Record<'value', string>)[]) { | ||
| 327 | + if (formModel?.deviceType === DeviceTypeEnum.SENSOR && formModel?.gatewayId) { | ||
| 328 | + const result = options.find((item) => item.value === formModel?.gatewayId); | ||
| 329 | + result && setFieldsValue({ sensorOrganizationId: result?.organizationId }); | ||
| 331 | } | 330 | } |
| 332 | - validateFields(['gatewayId']); | ||
| 333 | }, | 331 | }, |
| 334 | }; | 332 | }; |
| 335 | }, | 333 | }, |
| 336 | }, | 334 | }, |
| 337 | { | 335 | { |
| 338 | - field: 'organizationList', | 336 | + field: 'sensorOrganizationId', |
| 339 | label: '依据网关设备请求的组织数组', | 337 | label: '依据网关设备请求的组织数组', |
| 340 | component: 'Input', | 338 | component: 'Input', |
| 341 | ifShow: false, | 339 | ifShow: false, |
| @@ -354,6 +352,13 @@ export const step1Schemas: FormSchema[] = [ | @@ -354,6 +352,13 @@ export const step1Schemas: FormSchema[] = [ | ||
| 354 | return { | 352 | return { |
| 355 | component: 'OrgTreeSelect', | 353 | component: 'OrgTreeSelect', |
| 356 | defaultLockStatus: !!formModel?.isUpdate, | 354 | defaultLockStatus: !!formModel?.isUpdate, |
| 355 | + componentProps: { | ||
| 356 | + apiTreeSelectProps: { | ||
| 357 | + params: { | ||
| 358 | + organizationId: formModel?.sensorOrganizationId, | ||
| 359 | + }, | ||
| 360 | + }, | ||
| 361 | + }, | ||
| 357 | }; | 362 | }; |
| 358 | }, | 363 | }, |
| 359 | }, | 364 | }, |
| 1 | import { Options } from './type'; | 1 | import { Options } from './type'; |
| 2 | -import { getMeetTheConditionsDevice } from '/@/api/dataBoard'; | 2 | +import { getMeetTheConditionsGatewayDevice } from '/@/api/dataBoard'; |
| 3 | import { queryDeviceProfileBy } from '/@/api/device/deviceManager'; | 3 | import { queryDeviceProfileBy } from '/@/api/device/deviceManager'; |
| 4 | import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 4 | import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
| 5 | import { findDictItemByCode } from '/@/api/system/dict'; | 5 | import { findDictItemByCode } from '/@/api/system/dict'; |
| 6 | -import { getOrganizationList } from '/@/api/system/system'; | ||
| 7 | -import { FormSchema } from '/@/components/Form'; | 6 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; |
| 8 | import { BasicColumn } from '/@/components/Table'; | 7 | import { BasicColumn } from '/@/components/Table'; |
| 9 | -import { copyTransFun } from '/@/utils/fnUtils'; | 8 | +import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; |
| 10 | import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; | 9 | import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const'; |
| 11 | import XLSX, { CellObject } from 'xlsx'; | 10 | import XLSX, { CellObject } from 'xlsx'; |
| 12 | 11 | ||
| 12 | +useComponentRegister('OrgTreeSelect', OrgTreeSelect); | ||
| 13 | + | ||
| 13 | export enum FieldsEnum { | 14 | export enum FieldsEnum { |
| 14 | ORGANIZATION_ID = 'organizationId', | 15 | ORGANIZATION_ID = 'organizationId', |
| 15 | DEVICE_TYPE = 'deviceTypeEnum', | 16 | DEVICE_TYPE = 'deviceTypeEnum', |
| @@ -23,6 +24,8 @@ export enum FieldsEnum { | @@ -23,6 +24,8 @@ export enum FieldsEnum { | ||
| 23 | IS_TCP_DEVICE_PROFILE = 'isTcpDeviceProfile', | 24 | IS_TCP_DEVICE_PROFILE = 'isTcpDeviceProfile', |
| 24 | TRANSPORT_TYPE = 'transportType', | 25 | TRANSPORT_TYPE = 'transportType', |
| 25 | PRODUCTION_NAME = 'productionName', | 26 | PRODUCTION_NAME = 'productionName', |
| 27 | + | ||
| 28 | + GATEWAY_ORGANIZATION_ID = 'gatewayOrganizationId', | ||
| 26 | } | 29 | } |
| 27 | 30 | ||
| 28 | export enum DelimiterEnum { | 31 | export enum DelimiterEnum { |
| @@ -108,30 +111,6 @@ export enum CredentialsNameEnum { | @@ -108,30 +111,6 @@ export enum CredentialsNameEnum { | ||
| 108 | 111 | ||
| 109 | export const basicInfoForm: FormSchema[] = [ | 112 | export const basicInfoForm: FormSchema[] = [ |
| 110 | { | 113 | { |
| 111 | - field: FieldsEnum.ORGANIZATION_ID, | ||
| 112 | - label: '所属组织', | ||
| 113 | - component: 'ApiTreeSelect', | ||
| 114 | - rules: [{ required: true, message: '所属组织为必填项' }], | ||
| 115 | - componentProps: ({ formModel, formActionType }) => { | ||
| 116 | - const { setFieldsValue } = formActionType; | ||
| 117 | - return { | ||
| 118 | - maxLength: 250, | ||
| 119 | - placeholder: '请选择所属组织', | ||
| 120 | - api: async () => { | ||
| 121 | - const data = (await getOrganizationList()) as unknown as Recordable[]; | ||
| 122 | - copyTransFun(data); | ||
| 123 | - return data; | ||
| 124 | - }, | ||
| 125 | - getPopupContainer: () => document.body, | ||
| 126 | - onChange(e) { | ||
| 127 | - if (e != formModel?.[FieldsEnum.ORGANIZATION_ID]) { | ||
| 128 | - setFieldsValue({ [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null }); | ||
| 129 | - } | ||
| 130 | - }, | ||
| 131 | - }; | ||
| 132 | - }, | ||
| 133 | - }, | ||
| 134 | - { | ||
| 135 | field: FieldsEnum.DEVICE_TYPE, | 114 | field: FieldsEnum.DEVICE_TYPE, |
| 136 | label: '设备类型', | 115 | label: '设备类型', |
| 137 | component: 'ApiSelect', | 116 | component: 'ApiSelect', |
| @@ -150,6 +129,7 @@ export const basicInfoForm: FormSchema[] = [ | @@ -150,6 +129,7 @@ export const basicInfoForm: FormSchema[] = [ | ||
| 150 | [FieldsEnum.DEVICE_TYPE_NAME]: value ? options.label : null, | 129 | [FieldsEnum.DEVICE_TYPE_NAME]: value ? options.label : null, |
| 151 | [FieldsEnum.TK_DEVICE_PROFILE_ID]: null, | 130 | [FieldsEnum.TK_DEVICE_PROFILE_ID]: null, |
| 152 | [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null, | 131 | [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null, |
| 132 | + [FieldsEnum.ORGANIZATION_ID]: null, | ||
| 153 | }); | 133 | }); |
| 154 | clearValidate(); | 134 | clearValidate(); |
| 155 | }, | 135 | }, |
| @@ -181,6 +161,7 @@ export const basicInfoForm: FormSchema[] = [ | @@ -181,6 +161,7 @@ export const basicInfoForm: FormSchema[] = [ | ||
| 181 | [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null, | 161 | [FieldsEnum.GATEWAY_TB_DEVICE_ID]: null, |
| 182 | [FieldsEnum.TRANSPORT_TYPE]: options?.transportType, | 162 | [FieldsEnum.TRANSPORT_TYPE]: options?.transportType, |
| 183 | [FieldsEnum.PRODUCTION_NAME]: options?.label, | 163 | [FieldsEnum.PRODUCTION_NAME]: options?.label, |
| 164 | + [FieldsEnum.ORGANIZATION_ID]: null, | ||
| 184 | }); | 165 | }); |
| 185 | }, | 166 | }, |
| 186 | showSearch: true, | 167 | showSearch: true, |
| @@ -203,30 +184,29 @@ export const basicInfoForm: FormSchema[] = [ | @@ -203,30 +184,29 @@ export const basicInfoForm: FormSchema[] = [ | ||
| 203 | show: false, | 184 | show: false, |
| 204 | }, | 185 | }, |
| 205 | { | 186 | { |
| 187 | + field: FieldsEnum.GATEWAY_ORGANIZATION_ID, | ||
| 188 | + label: '', | ||
| 189 | + component: 'Input', | ||
| 190 | + show: false, | ||
| 191 | + }, | ||
| 192 | + { | ||
| 206 | field: FieldsEnum.GATEWAY_TB_DEVICE_ID, | 193 | field: FieldsEnum.GATEWAY_TB_DEVICE_ID, |
| 207 | component: 'ApiSelect', | 194 | component: 'ApiSelect', |
| 208 | label: '网关设备', | 195 | label: '网关设备', |
| 209 | ifShow: ({ model }) => model[FieldsEnum.DEVICE_TYPE] === DeviceTypeEnum.SENSOR, | 196 | ifShow: ({ model }) => model[FieldsEnum.DEVICE_TYPE] === DeviceTypeEnum.SENSOR, |
| 210 | required: true, | 197 | required: true, |
| 211 | - componentProps: ({ formModel }) => { | ||
| 212 | - const organizationId = formModel[FieldsEnum.ORGANIZATION_ID]; | ||
| 213 | - const transportType = formModel[FieldsEnum.TRANSPORT_TYPE]; | 198 | + componentProps: ({ formModel, formActionType }) => { |
| 199 | + const transportType: string = formModel[FieldsEnum.TRANSPORT_TYPE]; | ||
| 214 | return { | 200 | return { |
| 215 | api: async () => { | 201 | api: async () => { |
| 216 | try { | 202 | try { |
| 217 | - if (!organizationId) return; | ||
| 218 | - const result = await getMeetTheConditionsDevice({ | ||
| 219 | - deviceType: DeviceTypeEnum.GATEWAY, | ||
| 220 | - organizationId, | 203 | + const result = await getMeetTheConditionsGatewayDevice({ transportType }); |
| 204 | + return result.map((item) => { | ||
| 205 | + return { | ||
| 206 | + ...item, | ||
| 207 | + name: item.alias || item.name, | ||
| 208 | + }; | ||
| 221 | }); | 209 | }); |
| 222 | - return result | ||
| 223 | - .map((item) => { | ||
| 224 | - return { | ||
| 225 | - ...item, | ||
| 226 | - name: item.alias || item.name, | ||
| 227 | - }; | ||
| 228 | - }) | ||
| 229 | - .filter((item) => item.transportType === transportType); | ||
| 230 | } catch (error) { | 210 | } catch (error) { |
| 231 | return []; | 211 | return []; |
| 232 | } | 212 | } |
| @@ -239,6 +219,28 @@ export const basicInfoForm: FormSchema[] = [ | @@ -239,6 +219,28 @@ export const basicInfoForm: FormSchema[] = [ | ||
| 239 | return options.label.includes(inputValue); | 219 | return options.label.includes(inputValue); |
| 240 | }, | 220 | }, |
| 241 | placeholder: '请选择网关设备', | 221 | placeholder: '请选择网关设备', |
| 222 | + onChange(_value: string, option: DeviceRecord) { | ||
| 223 | + const { setFieldsValue } = formActionType; | ||
| 224 | + setFieldsValue({ | ||
| 225 | + [FieldsEnum.GATEWAY_ORGANIZATION_ID]: option?.organizationId, | ||
| 226 | + [FieldsEnum.ORGANIZATION_ID]: null, | ||
| 227 | + }); | ||
| 228 | + }, | ||
| 229 | + }; | ||
| 230 | + }, | ||
| 231 | + }, | ||
| 232 | + { | ||
| 233 | + field: FieldsEnum.ORGANIZATION_ID, | ||
| 234 | + label: '所属组织', | ||
| 235 | + component: 'OrgTreeSelect', | ||
| 236 | + rules: [{ required: true, message: '所属组织为必填项' }], | ||
| 237 | + componentProps: ({ formModel }) => { | ||
| 238 | + return { | ||
| 239 | + apiTreeSelectProps: { | ||
| 240 | + params: { | ||
| 241 | + organizationId: formModel?.[FieldsEnum.GATEWAY_ORGANIZATION_ID], | ||
| 242 | + }, | ||
| 243 | + }, | ||
| 242 | }; | 244 | }; |
| 243 | }, | 245 | }, |
| 244 | }, | 246 | }, |
| @@ -201,13 +201,6 @@ | @@ -201,13 +201,6 @@ | ||
| 201 | slots: { customRender: 'action' }, | 201 | slots: { customRender: 'action' }, |
| 202 | fixed: 'right', | 202 | fixed: 'right', |
| 203 | }, | 203 | }, |
| 204 | - rowSelection: { | ||
| 205 | - getCheckboxProps: (record: ModelOfMatterItemRecordType) => { | ||
| 206 | - return { | ||
| 207 | - disabled: record.status === 1, | ||
| 208 | - }; | ||
| 209 | - }, | ||
| 210 | - }, | ||
| 211 | }); | 204 | }); |
| 212 | 205 | ||
| 213 | const getHasBatchDelete = computed(() => !getRowSelection().selectedRowKeys?.length); | 206 | const getHasBatchDelete = computed(() => !getRowSelection().selectedRowKeys?.length); |