Commit e6353bc8599d3372d2e5df0dd998ff9fc906fa37
1 parent
a27a5e41
perf: visual board implement map component data source bind
Showing
2 changed files
with
47 additions
and
42 deletions
1 | +<script lang="ts"> | |
2 | + export type OptionsItem = { label: string; value: string; disabled?: boolean }; | |
3 | + export interface OnChangeHookParams { | |
4 | + options: Ref<OptionsItem[]>; | |
5 | + } | |
6 | +</script> | |
7 | + | |
1 | 8 | <script lang="ts" setup> |
2 | - import { ref, watchEffect, computed, unref, watch } from 'vue'; | |
9 | + import { ref, watchEffect, computed, unref, watch, Ref } from 'vue'; | |
3 | 10 | import { Select } from 'ant-design-vue'; |
4 | 11 | import { isFunction } from '/@/utils/is'; |
5 | 12 | import { useRuleFormItem } from '/@/hooks/component/useFormItem'; |
... | ... | @@ -8,8 +15,6 @@ |
8 | 15 | import { LoadingOutlined } from '@ant-design/icons-vue'; |
9 | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
10 | 17 | |
11 | - type OptionsItem = { label: string; value: string; disabled?: boolean }; | |
12 | - | |
13 | 18 | const emit = defineEmits(['options-change', 'change']); |
14 | 19 | const props = withDefaults( |
15 | 20 | defineProps<{ |
... | ... | @@ -22,12 +27,16 @@ |
22 | 27 | labelField?: string; |
23 | 28 | valueField?: string; |
24 | 29 | immediate?: boolean; |
30 | + queryEmptyDataAgin?: boolean; | |
31 | + onChangeHook?: ({ options }: OnChangeHookParams) => void; | |
32 | + dropdownVisibleChangeHook?: ({ options }: OnChangeHookParams) => void; | |
25 | 33 | }>(), |
26 | 34 | { |
27 | 35 | resultField: '', |
28 | 36 | labelField: 'label', |
29 | 37 | valueField: 'value', |
30 | 38 | immediate: true, |
39 | + queryEmptyDataAgin: true, | |
31 | 40 | } |
32 | 41 | ); |
33 | 42 | const options = ref<OptionsItem[]>([]); |
... | ... | @@ -42,7 +51,6 @@ |
42 | 51 | |
43 | 52 | const getOptions = computed(() => { |
44 | 53 | const { labelField, valueField = 'value', numberToString } = props; |
45 | - | |
46 | 54 | return unref(options).reduce((prev, next: Recordable) => { |
47 | 55 | if (next) { |
48 | 56 | const value = next[valueField]; |
... | ... | @@ -92,24 +100,34 @@ |
92 | 100 | } |
93 | 101 | |
94 | 102 | async function handleFetch() { |
95 | - if (!props.immediate && unref(isFirstLoad)) { | |
103 | + const { immediate, dropdownVisibleChangeHook } = props; | |
104 | + if (!immediate && unref(isFirstLoad)) { | |
96 | 105 | await fetch(); |
97 | 106 | isFirstLoad.value = false; |
98 | 107 | } |
108 | + if (dropdownVisibleChangeHook && isFunction(dropdownVisibleChangeHook)) { | |
109 | + dropdownVisibleChangeHook({ options }); | |
110 | + } | |
99 | 111 | } |
100 | 112 | |
101 | 113 | function emitChange() { |
102 | 114 | emit('options-change', unref(getOptions)); |
103 | 115 | } |
104 | 116 | |
105 | - function handleChange(_, ...args) { | |
117 | + function handleChange(value: string, ...args) { | |
106 | 118 | emitData.value = args; |
107 | - if (!_) handleSearch(); | |
119 | + if (!value && props.queryEmptyDataAgin) handleSearch(); | |
120 | + const { onChangeHook } = props; | |
121 | + if (!onChangeHook && !isFunction(onChangeHook)) return; | |
122 | + onChangeHook({ options }); | |
108 | 123 | } |
109 | 124 | |
110 | 125 | async function handleSearch(params?: string) { |
111 | - const searchApi = props.searchApi; | |
112 | - if (!searchApi || !isFunction(searchApi)) return; | |
126 | + let { searchApi, api } = props; | |
127 | + if (!searchApi || !isFunction(searchApi)) { | |
128 | + if (!api || !isFunction(api)) return; | |
129 | + searchApi = api; | |
130 | + } | |
113 | 131 | options.value = []; |
114 | 132 | try { |
115 | 133 | loading.value = true; |
... | ... | @@ -135,6 +153,7 @@ |
135 | 153 | <Select |
136 | 154 | @dropdownVisibleChange="handleFetch" |
137 | 155 | v-bind="attrs" |
156 | + show-search | |
138 | 157 | @change="handleChange" |
139 | 158 | :options="getOptions" |
140 | 159 | @search="handleSearch" | ... | ... |
... | ... | @@ -2,6 +2,8 @@ import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/ |
2 | 2 | import { getOrganizationList } from '/@/api/system/system'; |
3 | 3 | import { FormSchema } from '/@/components/Form'; |
4 | 4 | import { copyTransFun } from '/@/utils/fnUtils'; |
5 | +import { OnChangeHookParams } from '/@/components/Form/src/components/ApiSearchSelect.vue'; | |
6 | +import { unref } from 'vue'; | |
5 | 7 | |
6 | 8 | export enum BasicConfigField { |
7 | 9 | NAME = 'name', |
... | ... | @@ -366,84 +368,68 @@ export const mapFormSchema: FormSchema[] = [ |
366 | 368 | }, |
367 | 369 | { |
368 | 370 | field: DataSourceField.LONGITUDE_ATTRIBUTE, |
369 | - component: 'ApiSelect', | |
371 | + component: 'ApiSearchSelect', | |
370 | 372 | label: '经度属性', |
371 | 373 | colProps: { span: 8 }, |
372 | 374 | rules: [{ required: true, message: '属性为必填项' }], |
373 | - componentProps({ formModel, formActionType }) { | |
374 | - const { updateSchema, setFieldsValue } = formActionType; | |
375 | + componentProps({ formModel }) { | |
375 | 376 | const organizationId = formModel[DataSourceField.ORIGINATION_ID]; |
376 | 377 | const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; |
377 | 378 | const deviceId = formModel[DataSourceField.DEVICE_ID]; |
378 | 379 | const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; |
379 | - | |
380 | - let attrs: Record<'label' | 'value', string>[] = []; | |
381 | 380 | return { |
382 | 381 | api: async () => { |
383 | 382 | if (organizationId && deviceId) { |
384 | 383 | try { |
385 | 384 | if (isGatewayDevice && slaveDeviceId) { |
386 | - return (attrs = await getDeviceAttribute(slaveDeviceId)); | |
385 | + return await getDeviceAttribute(slaveDeviceId); | |
387 | 386 | } |
388 | 387 | if (!isGatewayDevice) { |
389 | - return (attrs = await getDeviceAttribute(deviceId)); | |
388 | + return await getDeviceAttribute(deviceId); | |
390 | 389 | } |
391 | 390 | } catch (error) {} |
392 | 391 | } |
393 | 392 | return []; |
394 | 393 | }, |
395 | 394 | 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 | - }); | |
395 | + dropdownVisibleChangeHook: ({ options }: OnChangeHookParams) => { | |
396 | + options.value = unref(options).filter( | |
397 | + (item) => item.value !== formModel[DataSourceField.LATITUDE_ATTRIBUTE] | |
398 | + ); | |
406 | 399 | }, |
400 | + getPopupContainer: () => document.body, | |
407 | 401 | }; |
408 | 402 | }, |
409 | 403 | }, |
410 | 404 | { |
411 | 405 | field: DataSourceField.LATITUDE_ATTRIBUTE, |
412 | - component: 'ApiSelect', | |
406 | + component: 'ApiSearchSelect', | |
413 | 407 | label: '纬度属性', |
414 | 408 | colProps: { span: 8 }, |
415 | 409 | rules: [{ required: true, message: '属性为必填项' }], |
416 | - componentProps({ formModel, formActionType }) { | |
417 | - const { updateSchema, setFieldsValue } = formActionType; | |
410 | + componentProps({ formModel }) { | |
418 | 411 | const organizationId = formModel[DataSourceField.ORIGINATION_ID]; |
419 | 412 | const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; |
420 | 413 | const deviceId = formModel[DataSourceField.DEVICE_ID]; |
421 | 414 | const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; |
422 | - let attrs: Record<'label' | 'value', string>[] = []; | |
423 | - | |
424 | 415 | return { |
425 | 416 | api: async () => { |
426 | 417 | if (organizationId && deviceId) { |
427 | 418 | try { |
428 | 419 | if (isGatewayDevice && slaveDeviceId) { |
429 | - return (attrs = await getDeviceAttribute(slaveDeviceId)); | |
420 | + return getDeviceAttribute(slaveDeviceId); | |
430 | 421 | } |
431 | 422 | if (!isGatewayDevice) { |
432 | - return (attrs = await getDeviceAttribute(deviceId)); | |
423 | + return await getDeviceAttribute(deviceId); | |
433 | 424 | } |
434 | 425 | } catch (error) {} |
435 | 426 | } |
436 | 427 | return []; |
437 | 428 | }, |
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 | - }); | |
429 | + dropdownVisibleChangeHook: ({ options }: OnChangeHookParams) => { | |
430 | + options.value = unref(options).filter( | |
431 | + (item) => item.value !== formModel[DataSourceField.LONGITUDE_ATTRIBUTE] | |
432 | + ); | |
447 | 433 | }, |
448 | 434 | placeholder: '请选择纬度属性', |
449 | 435 | getPopupContainer: () => document.body, | ... | ... |