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 | +]; |