Commit ca118a71af2ff60c5dfe1762725b8741656b2d66
1 parent
356ba0a0
feat: ota page add permission control
Showing
10 changed files
with
324 additions
and
13 deletions
@@ -81,7 +81,13 @@ | @@ -81,7 +81,13 @@ | ||
81 | </script> | 81 | </script> |
82 | 82 | ||
83 | <template> | 83 | <template> |
84 | - <BasicModal title="包管理" destroy-on-close @register="registerModal" @ok="handleSubmit"> | 84 | + <BasicModal |
85 | + title="包管理" | ||
86 | + destroy-on-close | ||
87 | + :ok-button-props="{ loading }" | ||
88 | + @register="registerModal" | ||
89 | + @ok="handleSubmit" | ||
90 | + > | ||
85 | <BasicForm @register="registerForm" class="package-manage-form" /> | 91 | <BasicForm @register="registerForm" class="package-manage-form" /> |
86 | </BasicModal> | 92 | </BasicModal> |
87 | </template> | 93 | </template> |
@@ -15,6 +15,8 @@ | @@ -15,6 +15,8 @@ | ||
15 | } from '/@/api/ota'; | 15 | } from '/@/api/ota'; |
16 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; | 16 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
17 | import { useDownload } from '../hook/useDownload'; | 17 | import { useDownload } from '../hook/useDownload'; |
18 | + import { Authority } from '/@/components/Authority'; | ||
19 | + import { OtaPermissionKey } from '../config/config'; | ||
18 | // import DeviceDetailDrawer from '/@/views/device/list/cpns/modal/DeviceDetailDrawer.vue'; | 20 | // import DeviceDetailDrawer from '/@/views/device/list/cpns/modal/DeviceDetailDrawer.vue'; |
19 | 21 | ||
20 | const emit = defineEmits(['register', 'update:list']); | 22 | const emit = defineEmits(['register', 'update:list']); |
@@ -143,7 +145,9 @@ | @@ -143,7 +145,9 @@ | ||
143 | class="absolute right-0 bottom-0 w-full border-t bg-light-50 border-t-gray-100 py-2 px-4 text-right" | 145 | class="absolute right-0 bottom-0 w-full border-t bg-light-50 border-t-gray-100 py-2 px-4 text-right" |
144 | > | 146 | > |
145 | <Button class="mr-2" @click="closeDrawer">取消</Button> | 147 | <Button class="mr-2" @click="closeDrawer">取消</Button> |
146 | - <Button type="primary" :loading="loading" @click="handleSubmit">保存</Button> | 148 | + <Authority :value="OtaPermissionKey.UPDATE"> |
149 | + <Button type="primary" :loading="loading" @click="handleSubmit">保存</Button> | ||
150 | + </Authority> | ||
147 | </div> | 151 | </div> |
148 | </template> | 152 | </template> |
149 | <!-- <DeviceDetailDrawer @register="registerTBDrawer" /> --> | 153 | <!-- <DeviceDetailDrawer @register="registerTBDrawer" /> --> |
@@ -8,6 +8,13 @@ export interface ModalPassRecord { | @@ -8,6 +8,13 @@ export interface ModalPassRecord { | ||
8 | record?: Recordable; | 8 | record?: Recordable; |
9 | } | 9 | } |
10 | 10 | ||
11 | +export enum OtaPermissionKey { | ||
12 | + CREATE = 'api:operation:ota:post', | ||
13 | + UPDATE = 'api:operation:ota:update', | ||
14 | + DELETE = 'api:operation:ota:delete', | ||
15 | + DOWNLOAD = 'api:operation:ota:download', | ||
16 | +} | ||
17 | + | ||
11 | export const columns: BasicColumn[] = [ | 18 | export const columns: BasicColumn[] = [ |
12 | { | 19 | { |
13 | title: '创建时间', | 20 | title: '创建时间', |
@@ -45,14 +45,29 @@ export enum ALG { | @@ -45,14 +45,29 @@ export enum ALG { | ||
45 | MURMUR3_128 = 'MURMUR3128', | 45 | MURMUR3_128 = 'MURMUR3128', |
46 | } | 46 | } |
47 | 47 | ||
48 | +const getVersionTag = (title: string, version: string) => { | ||
49 | + return `${title ?? ''} ${version ?? ''}`; | ||
50 | +}; | ||
51 | + | ||
48 | export const formSchema: FormSchema[] = [ | 52 | export const formSchema: FormSchema[] = [ |
49 | { | 53 | { |
50 | field: PackageField.TITLE, | 54 | field: PackageField.TITLE, |
51 | label: '标题', | 55 | label: '标题', |
52 | component: 'Input', | 56 | component: 'Input', |
53 | rules: [{ required: true, message: '标题为必填项' }], | 57 | rules: [{ required: true, message: '标题为必填项' }], |
54 | - componentProps: { | ||
55 | - placeholder: '请输入标题', | 58 | + componentProps: ({ formActionType, formModel }) => { |
59 | + const { setFieldsValue } = formActionType; | ||
60 | + return { | ||
61 | + placeholder: '请输入标题', | ||
62 | + onChange: (value: Event) => { | ||
63 | + setFieldsValue({ | ||
64 | + [PackageField.VERSION_TAG]: getVersionTag( | ||
65 | + (value.target as HTMLInputElement).value, | ||
66 | + formModel[PackageField.VERSION] | ||
67 | + ), | ||
68 | + }); | ||
69 | + }, | ||
70 | + }; | ||
56 | }, | 71 | }, |
57 | }, | 72 | }, |
58 | { | 73 | { |
@@ -60,8 +75,19 @@ export const formSchema: FormSchema[] = [ | @@ -60,8 +75,19 @@ export const formSchema: FormSchema[] = [ | ||
60 | label: '版本', | 75 | label: '版本', |
61 | component: 'Input', | 76 | component: 'Input', |
62 | rules: [{ required: true, message: '版本为必填项' }], | 77 | rules: [{ required: true, message: '版本为必填项' }], |
63 | - componentProps: { | ||
64 | - placeholder: '请输入版本', | 78 | + componentProps: ({ formActionType, formModel }) => { |
79 | + const { setFieldsValue } = formActionType; | ||
80 | + return { | ||
81 | + placeholder: '请输入版本', | ||
82 | + onChange: (value: Event) => { | ||
83 | + setFieldsValue({ | ||
84 | + [PackageField.VERSION_TAG]: getVersionTag( | ||
85 | + formModel[PackageField.TITLE], | ||
86 | + (value.target as HTMLInputElement).value | ||
87 | + ), | ||
88 | + }); | ||
89 | + }, | ||
90 | + }; | ||
65 | }, | 91 | }, |
66 | }, | 92 | }, |
67 | { | 93 | { |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | import { Button } from 'ant-design-vue'; | 2 | import { Button } from 'ant-design-vue'; |
3 | - import { columns, ModalPassRecord, searchFormSchema } from './config/config'; | 3 | + import { columns, ModalPassRecord, OtaPermissionKey, searchFormSchema } from './config/config'; |
4 | import { PageWrapper } from '/@/components/Page'; | 4 | import { PageWrapper } from '/@/components/Page'; |
5 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 5 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
6 | import PackageDetailModal from './components/PackageDetailModal.vue'; | 6 | import PackageDetailModal from './components/PackageDetailModal.vue'; |
@@ -13,6 +13,7 @@ | @@ -13,6 +13,7 @@ | ||
13 | import { useDownload } from './hook/useDownload'; | 13 | import { useDownload } from './hook/useDownload'; |
14 | import { computed } from 'vue'; | 14 | import { computed } from 'vue'; |
15 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; | 15 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; |
16 | + import { Authority } from '/@/components/Authority'; | ||
16 | 17 | ||
17 | const [register, { reload, getSelectRowKeys, getRowSelection, setSelectedRowKeys }] = useTable({ | 18 | const [register, { reload, getSelectRowKeys, getRowSelection, setSelectedRowKeys }] = useTable({ |
18 | columns, | 19 | columns, |
@@ -102,10 +103,14 @@ | @@ -102,10 +103,14 @@ | ||
102 | <PageWrapper dense contentFullHeight contentClass="flex flex-col"> | 103 | <PageWrapper dense contentFullHeight contentClass="flex flex-col"> |
103 | <BasicTable @register="register" @row-click="handleOpenDetailDrawer" class="ota-list"> | 104 | <BasicTable @register="register" @row-click="handleOpenDetailDrawer" class="ota-list"> |
104 | <template #toolbar> | 105 | <template #toolbar> |
105 | - <Button @click="handleCreatePackage" type="primary">新增包</Button> | ||
106 | - <Button @click="handleBatchDelete" :disabled="canDelete" type="primary" danger> | ||
107 | - 批量删除 | ||
108 | - </Button> | 106 | + <Authority :value="OtaPermissionKey.CREATE"> |
107 | + <Button @click="handleCreatePackage" type="primary">新增包</Button> | ||
108 | + </Authority> | ||
109 | + <Authority :value="OtaPermissionKey.DELETE"> | ||
110 | + <Button @click="handleBatchDelete" :disabled="canDelete" type="primary" danger> | ||
111 | + 批量删除 | ||
112 | + </Button> | ||
113 | + </Authority> | ||
109 | </template> | 114 | </template> |
110 | <template #action="{ record }"> | 115 | <template #action="{ record }"> |
111 | <TableAction | 116 | <TableAction |
@@ -114,12 +119,14 @@ | @@ -114,12 +119,14 @@ | ||
114 | { | 119 | { |
115 | label: '下载', | 120 | label: '下载', |
116 | icon: 'ant-design:download-outlined', | 121 | icon: 'ant-design:download-outlined', |
122 | + auth: OtaPermissionKey.DOWNLOAD, | ||
117 | onClick: downloadFile.bind(null, record), | 123 | onClick: downloadFile.bind(null, record), |
118 | }, | 124 | }, |
119 | { | 125 | { |
120 | label: '删除', | 126 | label: '删除', |
121 | icon: 'ant-design:delete-outlined', | 127 | icon: 'ant-design:delete-outlined', |
122 | color: 'error', | 128 | color: 'error', |
129 | + auth: OtaPermissionKey.DELETE, | ||
123 | popConfirm: { | 130 | popConfirm: { |
124 | title: '是否确认删除', | 131 | title: '是否确认删除', |
125 | confirm: deletePackage.bind(null, record), | 132 | confirm: deletePackage.bind(null, record), |
1 | +<script lang="ts" setup> | ||
2 | + import { ref, unref } from 'vue'; | ||
3 | + import { BasicForm, FormActionType } from '/@/components/Form'; | ||
4 | + import { mapFormSchema } from '../../config/basicConfiguration'; | ||
5 | + | ||
6 | + const formEl = ref<Nullable<FormActionType>>(); | ||
7 | + | ||
8 | + const setFormEl = (el: any) => { | ||
9 | + formEl.value = el; | ||
10 | + }; | ||
11 | + | ||
12 | + const getFieldsValue = () => { | ||
13 | + return unref(formEl)!.getFieldsValue(); | ||
14 | + }; | ||
15 | + | ||
16 | + const validate = async () => { | ||
17 | + await unref(formEl)!.validate(); | ||
18 | + }; | ||
19 | + | ||
20 | + const setFieldsValue = async (record: Recordable) => { | ||
21 | + await unref(formEl)!.setFieldsValue(record); | ||
22 | + }; | ||
23 | + | ||
24 | + const clearValidate = async (name?: string | string[]) => { | ||
25 | + await unref(formEl)!.clearValidate(name); | ||
26 | + }; | ||
27 | + defineExpose({ | ||
28 | + formActionType: { getFieldsValue, validate, setFieldsValue, clearValidate }, | ||
29 | + }); | ||
30 | +</script> | ||
31 | + | ||
32 | +<template> | ||
33 | + <div class="w-full flex-1"> | ||
34 | + <BasicForm | ||
35 | + :ref="(el) => setFormEl(el)" | ||
36 | + :schemas="mapFormSchema" | ||
37 | + class="w-full flex-1 data-source-form" | ||
38 | + :show-action-button-group="false" | ||
39 | + :row-props="{ | ||
40 | + gutter: 10, | ||
41 | + }" | ||
42 | + layout="horizontal" | ||
43 | + :label-col="{ span: 0 }" | ||
44 | + /> | ||
45 | + </div> | ||
46 | +</template> |
@@ -2,10 +2,12 @@ import { Component } from 'vue'; | @@ -2,10 +2,12 @@ import { Component } from 'vue'; | ||
2 | import { FrontComponent } from '../../../const/const'; | 2 | import { FrontComponent } from '../../../const/const'; |
3 | import BasicDataSourceForm from './BasicDataSourceForm.vue'; | 3 | import BasicDataSourceForm from './BasicDataSourceForm.vue'; |
4 | import ControlDataSourceForm from './ControlDataSourceForm.vue'; | 4 | import ControlDataSourceForm from './ControlDataSourceForm.vue'; |
5 | +import MapDataSourceForm from './MapDataSourceForm.vue'; | ||
5 | 6 | ||
6 | const dataSourceComponentMap = new Map<FrontComponent, Component>(); | 7 | const dataSourceComponentMap = new Map<FrontComponent, Component>(); |
7 | 8 | ||
8 | dataSourceComponentMap.set(FrontComponent.CONTROL_COMPONENT_TOGGLE_SWITCH, ControlDataSourceForm); | 9 | dataSourceComponentMap.set(FrontComponent.CONTROL_COMPONENT_TOGGLE_SWITCH, ControlDataSourceForm); |
10 | +dataSourceComponentMap.set(FrontComponent.MAP_COMPONENT_TRACK, MapDataSourceForm); | ||
9 | 11 | ||
10 | export const getDataSourceComponent = (frontId: FrontComponent) => { | 12 | export const getDataSourceComponent = (frontId: FrontComponent) => { |
11 | if (dataSourceComponentMap.has(frontId)) return dataSourceComponentMap.get(frontId)!; | 13 | if (dataSourceComponentMap.has(frontId)) return dataSourceComponentMap.get(frontId)!; |
@@ -25,6 +25,8 @@ export enum DataSourceField { | @@ -25,6 +25,8 @@ export enum DataSourceField { | ||
25 | ATTRIBUTE_RENAME = 'attributeRename', | 25 | ATTRIBUTE_RENAME = 'attributeRename', |
26 | DEVICE_NAME = 'deviceName', | 26 | DEVICE_NAME = 'deviceName', |
27 | DEVICE_RENAME = 'deviceRename', | 27 | DEVICE_RENAME = 'deviceRename', |
28 | + LONGITUDE_ATTRIBUTE = 'longitudeAttribute', | ||
29 | + LATITUDE_ATTRIBUTE = 'latitudeAttribute', | ||
28 | } | 30 | } |
29 | 31 | ||
30 | export const basicSchema: FormSchema[] = [ | 32 | export const basicSchema: FormSchema[] = [ |
@@ -238,3 +240,214 @@ export const controlFormSchema: FormSchema[] = [ | @@ -238,3 +240,214 @@ export const controlFormSchema: FormSchema[] = [ | ||
238 | }, | 240 | }, |
239 | }, | 241 | }, |
240 | ]; | 242 | ]; |
243 | + | ||
244 | +export const mapFormSchema: FormSchema[] = [ | ||
245 | + { | ||
246 | + field: DataSourceField.IS_GATEWAY_DEVICE, | ||
247 | + component: 'Switch', | ||
248 | + label: '是否是网关设备', | ||
249 | + show: false, | ||
250 | + }, | ||
251 | + { | ||
252 | + field: DataSourceField.DEVICE_NAME, | ||
253 | + component: 'Input', | ||
254 | + label: '设备名', | ||
255 | + show: false, | ||
256 | + }, | ||
257 | + { | ||
258 | + field: DataSourceField.ORIGINATION_ID, | ||
259 | + component: 'ApiTreeSelect', | ||
260 | + label: '组织', | ||
261 | + colProps: { span: 8 }, | ||
262 | + rules: [{ required: true, message: '组织为必填项' }], | ||
263 | + componentProps({ formActionType }) { | ||
264 | + const { setFieldsValue } = formActionType; | ||
265 | + return { | ||
266 | + placeholder: '请选择组织', | ||
267 | + api: async () => { | ||
268 | + const data = await getOrganizationList(); | ||
269 | + copyTransFun(data as any as any[]); | ||
270 | + return data; | ||
271 | + }, | ||
272 | + onChange() { | ||
273 | + setFieldsValue({ | ||
274 | + [DataSourceField.DEVICE_ID]: null, | ||
275 | + [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
276 | + [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
277 | + [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
278 | + [DataSourceField.IS_GATEWAY_DEVICE]: false, | ||
279 | + }); | ||
280 | + }, | ||
281 | + getPopupContainer: () => document.body, | ||
282 | + }; | ||
283 | + }, | ||
284 | + }, | ||
285 | + { | ||
286 | + field: DataSourceField.DEVICE_ID, | ||
287 | + component: 'ApiSelect', | ||
288 | + label: '设备', | ||
289 | + colProps: { span: 8 }, | ||
290 | + rules: [{ required: true, message: '设备名称为必填项' }], | ||
291 | + componentProps({ formModel, formActionType }) { | ||
292 | + const { setFieldsValue } = formActionType; | ||
293 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
294 | + return { | ||
295 | + api: async () => { | ||
296 | + if (organizationId) { | ||
297 | + try { | ||
298 | + const data = await getAllDeviceByOrg(organizationId); | ||
299 | + if (data) | ||
300 | + return data.map((item) => ({ | ||
301 | + label: item.name, | ||
302 | + value: item.id, | ||
303 | + deviceType: item.deviceType, | ||
304 | + })); | ||
305 | + } catch (error) {} | ||
306 | + } | ||
307 | + return []; | ||
308 | + }, | ||
309 | + onChange(_value, record: Record<'value' | 'label' | 'deviceType', string>) { | ||
310 | + setFieldsValue({ | ||
311 | + [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
312 | + [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
313 | + [DataSourceField.IS_GATEWAY_DEVICE]: record?.deviceType === 'GATEWAY', | ||
314 | + [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
315 | + [DataSourceField.DEVICE_NAME]: record?.label, | ||
316 | + }); | ||
317 | + }, | ||
318 | + placeholder: '请选择设备', | ||
319 | + getPopupContainer: () => document.body, | ||
320 | + }; | ||
321 | + }, | ||
322 | + }, | ||
323 | + { | ||
324 | + field: DataSourceField.SLAVE_DEVICE_ID, | ||
325 | + label: '网关子设备', | ||
326 | + component: 'ApiSelect', | ||
327 | + colProps: { span: 8 }, | ||
328 | + rules: [{ required: true, message: '网关子设备为必填项' }], | ||
329 | + ifShow({ model }) { | ||
330 | + return model[DataSourceField.IS_GATEWAY_DEVICE]; | ||
331 | + }, | ||
332 | + dynamicRules({ model }) { | ||
333 | + return [{ required: model[DataSourceField.IS_GATEWAY_DEVICE], message: '请选择网关子设备' }]; | ||
334 | + }, | ||
335 | + componentProps({ formModel, formActionType }) { | ||
336 | + const { setFieldsValue } = formActionType; | ||
337 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
338 | + const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
339 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
340 | + return { | ||
341 | + api: async () => { | ||
342 | + if (organizationId && isGatewayDevice) { | ||
343 | + try { | ||
344 | + const data = await getGatewaySlaveDevice({ organizationId, masterId: deviceId }); | ||
345 | + if (data) | ||
346 | + return data.map((item) => ({ | ||
347 | + label: item.name, | ||
348 | + value: item.id, | ||
349 | + deviceType: item.deviceType, | ||
350 | + })); | ||
351 | + } catch (error) {} | ||
352 | + } | ||
353 | + return []; | ||
354 | + }, | ||
355 | + onChange(_value, record: Record<'value' | 'label' | 'deviceType', string>) { | ||
356 | + setFieldsValue({ | ||
357 | + [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
358 | + [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
359 | + [DataSourceField.DEVICE_NAME]: record?.label, | ||
360 | + }); | ||
361 | + }, | ||
362 | + placeholder: '请选择网关子设备', | ||
363 | + getPopupContainer: () => document.body, | ||
364 | + }; | ||
365 | + }, | ||
366 | + }, | ||
367 | + { | ||
368 | + field: DataSourceField.LONGITUDE_ATTRIBUTE, | ||
369 | + component: 'ApiSelect', | ||
370 | + label: '经度属性', | ||
371 | + colProps: { span: 8 }, | ||
372 | + rules: [{ required: true, message: '属性为必填项' }], | ||
373 | + componentProps({ formModel, formActionType }) { | ||
374 | + const { updateSchema, setFieldsValue } = formActionType; | ||
375 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
376 | + const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
377 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
378 | + const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
379 | + | ||
380 | + let attrs: Record<'label' | 'value', string>[] = []; | ||
381 | + return { | ||
382 | + api: async () => { | ||
383 | + if (organizationId && deviceId) { | ||
384 | + try { | ||
385 | + if (isGatewayDevice && slaveDeviceId) { | ||
386 | + return (attrs = await getDeviceAttribute(slaveDeviceId)); | ||
387 | + } | ||
388 | + if (!isGatewayDevice) { | ||
389 | + return (attrs = await getDeviceAttribute(deviceId)); | ||
390 | + } | ||
391 | + } catch (error) {} | ||
392 | + } | ||
393 | + return []; | ||
394 | + }, | ||
395 | + placeholder: '请选择经度属性', | ||
396 | + getPopupContainer: () => document.body, | ||
397 | + onChange: (value: string) => { | ||
398 | + if (!value) return; | ||
399 | + setFieldsValue({ [DataSourceField.LATITUDE_ATTRIBUTE]: null }); | ||
400 | + updateSchema({ | ||
401 | + field: DataSourceField.LATITUDE_ATTRIBUTE, | ||
402 | + componentProps: { | ||
403 | + options: attrs.filter((item) => item.value !== value), | ||
404 | + }, | ||
405 | + }); | ||
406 | + }, | ||
407 | + }; | ||
408 | + }, | ||
409 | + }, | ||
410 | + { | ||
411 | + field: DataSourceField.LATITUDE_ATTRIBUTE, | ||
412 | + component: 'ApiSelect', | ||
413 | + label: '纬度属性', | ||
414 | + colProps: { span: 8 }, | ||
415 | + rules: [{ required: true, message: '属性为必填项' }], | ||
416 | + componentProps({ formModel, formActionType }) { | ||
417 | + const { updateSchema, setFieldsValue } = formActionType; | ||
418 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
419 | + const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
420 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
421 | + const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
422 | + let attrs: Record<'label' | 'value', string>[] = []; | ||
423 | + | ||
424 | + return { | ||
425 | + api: async () => { | ||
426 | + if (organizationId && deviceId) { | ||
427 | + try { | ||
428 | + if (isGatewayDevice && slaveDeviceId) { | ||
429 | + return (attrs = await getDeviceAttribute(slaveDeviceId)); | ||
430 | + } | ||
431 | + if (!isGatewayDevice) { | ||
432 | + return (attrs = await getDeviceAttribute(deviceId)); | ||
433 | + } | ||
434 | + } catch (error) {} | ||
435 | + } | ||
436 | + return []; | ||
437 | + }, | ||
438 | + onChange: (value: string) => { | ||
439 | + if (!value) return; | ||
440 | + setFieldsValue({ [DataSourceField.LONGITUDE_ATTRIBUTE]: null }); | ||
441 | + updateSchema({ | ||
442 | + field: DataSourceField.LATITUDE_ATTRIBUTE, | ||
443 | + componentProps: { | ||
444 | + options: attrs.filter((item) => item.value !== value), | ||
445 | + }, | ||
446 | + }); | ||
447 | + }, | ||
448 | + placeholder: '请输入纬度属性', | ||
449 | + getPopupContainer: () => document.body, | ||
450 | + }; | ||
451 | + }, | ||
452 | + }, | ||
453 | +]; |