Commit 6a2b472b3267a342c59a79544895afcfe19fd6bc

Authored by ww
1 parent 355a19bb

fix: 重构数据流转设备穿梭表格

1   -<script lang="ts" setup>
2   - import { Button, Tabs, Badge, ButtonProps, Tag } from 'ant-design-vue';
3   - import { get, isFunction, set, uniqBy } from 'lodash-es';
4   - import { ExtractPropTypes, computed, unref, ref, nextTick, onMounted, watch } from 'vue';
5   - import { DynamicProps } from '/#/utils';
6   - import { BasicModal, useModal } from '/@/components/Modal';
7   - import { BasicTable, BasicTableProps, TableRowSelection, useTable } from '/@/components/Table';
8   - import { FETCH_SETTING } from '/@/components/Table/src/const';
9   - import { useDesign } from '/@/hooks/web/useDesign';
10   -
11   - interface Options extends Recordable {
12   - primaryKey?: string;
13   - disabled?: boolean;
14   - }
15   -
16   - enum Active {
17   - PENDING = 'pending',
18   - SELECTED = 'selected',
19   - }
20   -
21   - interface ActionType {
22   - setSelectedOptions: (options: Recordable[]) => void;
23   - }
24   -
25   - const emit = defineEmits(['change', 'update:value']);
26   -
27   - const props = withDefaults(
28   - defineProps<{
29   - value?: string[];
30   - labelField?: string;
31   - valueField?: string;
32   - primaryKey?: string;
33   - params?: Recordable;
34   - buttonName?: string;
35   - pendingTableProps?: BasicTableProps;
36   - selectedTableProps?: BasicTableProps;
37   - maxTagLength?: number;
38   - modalProps?: ExtractPropTypes<InstanceType<typeof BasicModal>['$props']>;
39   - buttonProps?: ExtractPropTypes<InstanceType<typeof Button>['$props']>;
40   - initSelectedOptions?: (actionType: ActionType) => Promise<Recordable[]>;
41   - transformValue?: (selectedRowKeys: string[], selectedRows: Options[]) => any[];
42   - onValueChange?: (selectedRowkeys: string[]) => any[];
43   - onRemoveAfter?: (actionType: ActionType) => Promise<any>;
44   - onSelectedAfter?: (actionType: ActionType) => Promise<any>;
45   - }>(),
46   - {
47   - buttonName: '选择设备',
48   - primaryKey: 'id',
49   - maxTagLength: 2,
50   - labelField: 'label',
51   - valueField: 'value',
52   - }
53   - );
54   -
55   - const { prefixCls } = useDesign('transfer-table-modal');
56   -
57   - const activeKey = ref<Active>(Active.PENDING);
58   -
59   - const selectedRows = ref<Options[]>([]);
60   -
61   - const selectedRowKeys = ref<string[]>(props.value || []);
62   -
63   - const pendingOptions = ref<Options[]>([]);
64   -
65   - const selectedConfirmQueue = ref<Options[]>([]);
66   -
67   - const pendingConfirmQueue = ref<Options[]>([]);
68   -
69   - const selectedTotal = ref(0);
70   -
71   - const pendingTotal = ref(0);
72   -
73   - const getFetchSetting = computed(() => {
74   - const { pendingTableProps } = props;
75   - return pendingTableProps?.fetchSetting || FETCH_SETTING;
76   - });
77   -
78   - const getPendingRowSelection = computed<TableRowSelection>(() => {
79   - const rowKeys = unref(selectedRowKeys);
80   - return {
81   - type: 'checkbox',
82   - getCheckboxProps: (record: Recordable) => {
83   - const { primaryKey } = props;
84   - return {
85   - ...record,
86   - disabled: rowKeys.includes(record[primaryKey]),
87   - };
88   - },
89   - onSelect: (_record: Recordable, _selected: boolean, selectedRows: Object[]) => {
90   - pendingConfirmQueue.value = selectedRows;
91   - },
92   - onSelectAll: (_selected: boolean, selectedRows: Recordable[]) => {
93   - pendingConfirmQueue.value = selectedRows;
94   - },
95   - };
96   - });
97   -
98   - const getPendingTableBindProps = computed<Partial<DynamicProps<BasicTableProps>>>(() => {
99   - const { pendingTableProps, primaryKey } = props;
100   - return {
101   - ...pendingTableProps,
102   - rowKey: primaryKey,
103   - api: handlePendingApiIntercept,
104   - clickToRowSelect: false,
105   - rowSelection: getPendingRowSelection,
106   - };
107   - });
108   -
109   - const getSelectedTableBindProps = computed<Partial<DynamicProps<BasicTableProps>>>(() => {
110   - const { selectedTableProps, primaryKey } = props;
111   - return {
112   - ...selectedTableProps,
113   - dataSource: selectedRows,
114   - clickToRowSelect: false,
115   - rowKey: primaryKey,
116   - api: selectedTableProps!.api ? handleSelectedApiIntercept : undefined,
117   - rowSelection: {
118   - type: 'checkbox',
119   - onSelect: (_record: Recordable, _selected: boolean, selectedRows: Object[]) => {
120   - selectedConfirmQueue.value = selectedRows;
121   - },
122   - onSelectAll: (_selected: boolean, selectedRows: Recordable[]) => {
123   - selectedConfirmQueue.value = selectedRows;
124   - },
125   - },
126   - };
127   - });
128   -
129   - const getModalBindProps = computed(() => {
130   - const { modalProps = {} } = props;
131   - return {
132   - width: '60%',
133   - title: '穿梭表格',
134   - wrapClassName: prefixCls,
135   - ...modalProps,
136   - showOkBtn: false,
137   - };
138   - });
139   -
140   - const getBindButtonProps = computed<ButtonProps>(() => {
141   - const { buttonProps = {} } = props;
142   - return {
143   - type: 'link',
144   - ...buttonProps,
145   - };
146   - });
147   -
148   - const getShowTagOptions = computed(() => {
149   - const { maxTagLength } = props;
150   - return unref(selectedRows).slice(0, maxTagLength);
151   - });
152   -
153   - const getSurplusOptionsLength = computed(() => {
154   - const { maxTagLength } = props;
155   - const surplusValue = unref(selectedRows).length - maxTagLength;
156   - return surplusValue < 0 ? 0 : surplusValue;
157   - });
158   -
159   - const [registerModal, { openModal }] = useModal();
160   -
161   - const [
162   - regsterPendingTable,
163   - {
164   - getSelectRows: getPendingSelectRows,
165   - getSelectRowKeys: getPendingSelectRowKeys,
166   - reload: reloadPending,
167   - clearSelectedRowKeys: clearPendingSelectedRowKeys,
168   - },
169   - ] = useTable(unref(getPendingTableBindProps));
170   -
171   - const [
172   - registerSelectedTable,
173   - { getSelectRowKeys, setProps, clearSelectedRowKeys, reload: reloadSelected },
174   - ] = useTable(unref(getSelectedTableBindProps));
175   -
176   - async function handlePendingApiIntercept(params?: Recordable) {
177   - try {
178   - const { api } = props.pendingTableProps || {};
179   - if (api && isFunction(api)) {
180   - let options = await api(params);
181   - pendingOptions.value = options;
182   - const { totalField, listField } = unref(getFetchSetting);
183   - const total = get(options, totalField!);
184   - if (unref(selectedTotal) + unref(pendingTotal) !== total) {
185   - pendingTotal.value = total;
186   - }
187   - let list: Recordable[] = get(options, listField!);
188   - list = getSelectedRows(list);
189   - options = set(options, listField!, list);
190   - return options;
191   - }
192   - } catch (error) {
193   - console.error(error);
194   - return [];
195   - }
196   - return [];
197   - }
198   -
199   - async function handleSelectedApiIntercept(params?: Recordable) {
200   - try {
201   - const { api } = props.selectedTableProps || {};
202   - if (api && isFunction(api)) {
203   - let options = await api(params);
204   - pendingOptions.value = options;
205   - const { totalField, listField } = unref(getFetchSetting);
206   - selectedTotal.value = get(options, totalField!);
207   - let list: Recordable[] = get(options, listField!);
208   - list = getSelectedRows(list);
209   - options = set(options, listField!, list);
210   - return options;
211   - }
212   - } catch (error) {
213   - console.error(error);
214   - return [];
215   - }
216   - return [];
217   - }
218   -
219   - const handleOpenModal = async () => {
220   - openModal(true);
221   - await nextTick();
222   - if (props.value && !props.value.length) {
223   - activeKey.value = Active.PENDING;
224   - reloadPending();
225   - }
226   - };
227   -
228   - const handleTriggerEmit = (selectedRowKeys: string[], selectedRows: Options[]) => {
229   - const { transformValue } = props;
230   - let value = selectedRowKeys;
231   - if (transformValue && isFunction(transformValue)) {
232   - value = transformValue(selectedRowKeys, selectedRows);
233   - }
234   - emit('change', unref(selectedRowKeys), unref(selectedRows));
235   - emit('update:value', unref(value));
236   - };
237   -
238   - const handleSelected = async () => {
239   - const { onSelectedAfter } = props;
240   - const currentPageSelectRows = getPendingSelectRows();
241   - const currentPageSelectRowKeys = getPendingSelectRowKeys();
242   - const { primaryKey } = props;
243   - selectedRows.value = uniqBy([...unref(selectedRows), ...currentPageSelectRows], primaryKey);
244   - selectedRowKeys.value = [...new Set([...unref(selectedRowKeys), ...currentPageSelectRowKeys])];
245   - pendingConfirmQueue.value = [];
246   - // selectedTotal.value = unref(selectedRowKeys).length;
247   - pendingTotal.value = unref(pendingTotal) - currentPageSelectRows.length;
248   - selectedTotal.value = unref(selectedTotal) + currentPageSelectRows.length;
249   -
250   - clearPendingSelectedRowKeys();
251   - handleTriggerEmit(unref(selectedRowKeys), unref(selectedRows));
252   -
253   - if (onSelectedAfter && isFunction(onSelectedAfter)) {
254   - await onSelectedAfter(actionType);
255   - }
256   - reloadPending();
257   - };
258   -
259   - const handleRemoveSelected = async () => {
260   - const { onRemoveAfter } = props;
261   - const removeRowKeys = getSelectRowKeys();
262   - selectedRowKeys.value = unref(selectedRowKeys).filter((key) => !removeRowKeys.includes(key));
263   - selectedRows.value = unref(selectedRows).filter((item) => {
264   - const { primaryKey } = props;
265   - return unref(selectedRowKeys).includes(item[primaryKey]);
266   - });
267   - pendingTotal.value = unref(pendingTotal) + removeRowKeys.length;
268   - selectedTotal.value = unref(selectedTotal) - removeRowKeys.length;
269   -
270   - clearSelectedRowKeys();
271   - selectedConfirmQueue.value = [];
272   - setProps({ dataSource: unref(selectedRows) });
273   - handleTriggerEmit(unref(selectedRowKeys), unref(selectedRows));
274   -
275   - if (onRemoveAfter && isFunction(onRemoveAfter)) {
276   - await onRemoveAfter(actionType);
277   - }
278   - };
279   -
280   - const actionType = {
281   - setSelectedOptions,
282   - setSelectedTotal,
283   - reloadPending,
284   - reloadSelected,
285   - };
286   -
287   - const getSelectedRows = (options: Recordable[]) => {
288   - const { labelField, valueField } = props;
289   - return options.map((item) => ({ ...item, label: item[labelField], value: item[valueField] }));
290   - };
291   -
292   - const getSelectedKeys = (options: Recordable[]) => {
293   - const { primaryKey } = props;
294   - return options.map((item) => item[primaryKey]);
295   - };
296   -
297   - function setSelectedOptions(options: Recordable[]) {
298   - selectedRows.value = getSelectedRows(options);
299   - selectedRowKeys.value = getSelectedKeys(options);
300   - }
301   -
302   - function setSelectedTotal(number: number) {
303   - selectedTotal.value = number;
304   - }
305   -
306   - const handleCheckoutPanel = async (keys: Active) => {
307   - await nextTick();
308   - if (keys === Active.PENDING) {
309   - reloadPending();
310   - } else {
311   - reloadSelected();
312   - setProps({
313   - dataSource: unref(selectedRows),
314   - });
315   - }
316   - };
317   -
318   - watch(
319   - () => props.value,
320   - () => {
321   - if (props.value && !props.value.length) {
322   - selectedRowKeys.value = [];
323   - selectedRows.value = [];
324   - // pendingTotal.value = 0;
325   - selectedTotal.value = 0;
326   - }
327   - }
328   - );
329   -
330   - onMounted(async () => {
331   - const { initSelectedOptions } = props;
332   - if (initSelectedOptions && isFunction(initSelectedOptions)) {
333   - const options = await initSelectedOptions(actionType);
334   - setSelectedOptions(options);
335   - }
336   - });
337   -</script>
338   -
339   -<template>
340   - <section>
341   - <BasicModal @register="registerModal" v-bind="getModalBindProps">
342   - <section class="bg-gray-100">
343   - <Tabs v-model:active-key="activeKey" type="card" @change="handleCheckoutPanel">
344   - <Tabs.TabPane :key="Active.PENDING">
345   - <template #tab>
346   - <div class="flex items-center justify-center">
347   - <span>待选设备</span>
348   - <Badge show-zero :count="pendingTotal" />
349   - </div>
350   - </template>
351   - <BasicTable @register="regsterPendingTable">
352   - <template #toolbar>
353   - <section class="flex w-full justify-end items-center">
354   - <!-- <Button type="primary">全选</Button> -->
355   - <div class="text-blue-400">
356   - <span class="mr-2">选择设备:</span>
357   - <span>{{ pendingConfirmQueue.length }}</span>
358   - </div>
359   - </section>
360   - </template>
361   - </BasicTable>
362   - <section class="flex justify-end px-4 pb-4">
363   - <Button
364   - type="primary"
365   - @click="handleSelected"
366   - :disabled="!pendingConfirmQueue.length"
367   - >
368   - <span>确定已选</span>
369   - </Button>
370   - </section>
371   - </Tabs.TabPane>
372   - <Tabs.TabPane :key="Active.SELECTED">
373   - <template #tab>
374   - <div class="flex items-center justify-center">
375   - <span>已选设备</span>
376   - <Badge show-zero :count="selectedTotal" />
377   - </div>
378   - </template>
379   - <BasicTable @register="registerSelectedTable">
380   - <template #toolbar>
381   - <section class="flex w-full justify-end items-center">
382   - <!-- <Button type="primary">全选</Button> -->
383   - <div class="text-blue-400">
384   - <span class="mr-2">选择设备:</span>
385   - <span>{{ selectedConfirmQueue.length }}</span>
386   - </div>
387   - </section>
388   - </template>
389   - </BasicTable>
390   - <section class="flex justify-end px-4 pb-4">
391   - <Button
392   - type="primary"
393   - :disabled="!selectedConfirmQueue.length"
394   - @click="handleRemoveSelected"
395   - >
396   - <span>移除已选</span>
397   - </Button>
398   - </section>
399   - </Tabs.TabPane>
400   - </Tabs>
401   - </section>
402   - </BasicModal>
403   - <Button @click="handleOpenModal" v-bind="getBindButtonProps">
404   - <span v-if="!selectedRowKeys.length">选择设备</span>
405   - <div v-if="selectedRowKeys.length">
406   - <Tag
407   - class="!px-2 !py-1 !bg-gray-50 !border-gray-100"
408   - v-for="item in getShowTagOptions"
409   - :key="item.value"
410   - >
411   - <span>
412   - {{ item.alias || item.name }}
413   - </span>
414   - </Tag>
415   - <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength">
416   - <span> +{{ getSurplusOptionsLength }}... </span>
417   - </Tag>
418   - </div>
419   - </Button>
420   - </section>
421   -</template>
422   -
423   -<style lang="less">
424   - @prefix-cls: ~'@{namespace}-transfer-table-modal';
425   -
426   - .@{prefix-cls} {
427   - .vben-basic-table {
428   - padding-top: 0;
429   - }
430   -
431   - .vben-basic-form > .ant-row {
432   - width: 100%;
433   - }
434   -
435   - .ant-tabs-top-bar {
436   - background-color: #fff;
437   - }
438   - }
439   -</style>
... ... @@ -61,7 +61,6 @@
61 61 //input动态数据
62 62 const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
63 63
64   - console.log(dynamicInput, 'dynamicInput');
65 64 //删除Input
66 65 const remove = (item: Params) => {
67 66 let index = dynamicInput.params.indexOf(item);
... ...
... ... @@ -37,7 +37,7 @@
37 37 import { BasicModal, useModalInner } from '/@/components/Modal';
38 38 import { add } from '/@/components/Form/src/componentMap';
39 39 import TransferModal from '/@/components/Form/src/components/TransferModal.vue';
40   - import TransferTableModal from '/@/components/Form/src/components/TransferTableModal.vue';
  40 + import TransferTableModal from './TransferTableModal.vue';
41 41 import { DataFlowMethod, DataFlowParams } from './index';
42 42 import { stepConfig, removeFieldByModeForm } from './config';
43 43 import { postAddConvertApi } from '/@/api/datamanager/dataManagerApi';
... ...
  1 +import { h, unref } from 'vue';
  2 +import { findDictItemByCode } from '/@/api/system/dict';
  3 +import { FETCH_SETTING } from '/@/components/Table/src/const';
  4 +import { DeviceStatusEnum, DeviceStatusNameEnum, DeviceTypeNameEnum } from './enum';
  5 +import { Tag } from 'ant-design-vue';
  6 +import { BasicColumn, BasicTableProps, FormSchema } from '/@/components/Table';
  7 +import { useClipboard } from '@vueuse/core';
  8 +import { useMessage } from '/@/hooks/web/useMessage';
  9 +
  10 +export const deviceTableFormSchema: FormSchema[] = [
  11 + {
  12 + field: 'name',
  13 + label: '设备名称',
  14 + component: 'Input',
  15 + colProps: { span: 9 },
  16 + componentProps: {
  17 + placeholder: '请输入设备名称',
  18 + },
  19 + },
  20 + {
  21 + field: 'deviceType',
  22 + label: '设备类型',
  23 + component: 'ApiSelect',
  24 + colProps: { span: 9 },
  25 + componentProps: {
  26 + placeholder: '请选择设备类型',
  27 + api: findDictItemByCode,
  28 + params: {
  29 + dictCode: 'device_type',
  30 + },
  31 + labelField: 'itemText',
  32 + valueField: 'itemValue',
  33 + },
  34 + },
  35 +];
  36 +
  37 +const { copied, copy } = useClipboard({ legacy: true });
  38 +
  39 +const { createMessage } = useMessage();
  40 +
  41 +export const deviceTableColumn: BasicColumn[] = [
  42 + {
  43 + title: '状态',
  44 + dataIndex: 'deviceState',
  45 + customRender: ({ text }) => {
  46 + return h(
  47 + Tag,
  48 + {
  49 + color:
  50 + text === DeviceStatusEnum.INACTIVE
  51 + ? 'warning'
  52 + : text === DeviceStatusEnum.OFFLINE
  53 + ? 'error'
  54 + : 'success',
  55 + },
  56 + () => DeviceStatusNameEnum[text]
  57 + );
  58 + },
  59 + },
  60 + {
  61 + title: '别名/设备名称',
  62 + dataIndex: 'name',
  63 + customRender: ({ record }) => {
  64 + return h('div', [
  65 + h(
  66 + 'div',
  67 + {
  68 + class: 'cursor-pointer',
  69 + onClick: async () => {
  70 + await copy(record.name);
  71 + if (unref(copied)) createMessage.success('复制成功~');
  72 + },
  73 + },
  74 + [
  75 + record.alias && h('div', { class: 'truncate' }, record.alias),
  76 + h('div', { class: 'text-blue-400 truncate' }, record.name),
  77 + ]
  78 + ),
  79 + ]);
  80 + },
  81 + },
  82 + {
  83 + title: '设备类型',
  84 + dataIndex: 'deviceType',
  85 + customRender: ({ text }) => {
  86 + return h(Tag, { color: 'success' }, () => DeviceTypeNameEnum[text]);
  87 + },
  88 + },
  89 + {
  90 + title: '所属产品',
  91 + dataIndex: 'deviceProfile.name',
  92 + },
  93 + {
  94 + title: '所属组织',
  95 + dataIndex: 'organizationDTO.name',
  96 + },
  97 +];
  98 +
  99 +export const TransferTableProps: BasicTableProps = {
  100 + formConfig: {
  101 + layout: 'inline',
  102 + labelWidth: 80,
  103 + schemas: deviceTableFormSchema,
  104 + actionColOptions: { span: 6 },
  105 + },
  106 + size: 'small',
  107 + maxHeight: 240,
  108 + useSearchForm: true,
  109 + columns: deviceTableColumn,
  110 + showIndexColumn: false,
  111 + fetchSetting: FETCH_SETTING,
  112 +} as BasicTableProps;
... ...
  1 +<script lang="ts" setup>
  2 + import { Button, Tabs, Tag } from 'ant-design-vue';
  3 + import { remove, uniqBy, cloneDeep } from 'lodash';
  4 + import { computed, nextTick, onMounted, ref, unref, toRaw } from 'vue';
  5 + import {
  6 + deviceTableColumn,
  7 + deviceTableFormSchema,
  8 + TransferTableProps,
  9 + } from './TransferTableModal.config';
  10 + import { devicePage } from '/@/api/device/deviceManager';
  11 + import { DeviceModel as RawDeviceModal } from '/@/api/device/model/deviceModel';
  12 + import { BasicModal, useModal } from '/@/components/Modal';
  13 + import { BasicTable, useTable } from '/@/components/Table';
  14 + import { FETCH_SETTING } from '/@/components/Table/src/const';
  15 + import { useDesign } from '/@/hooks/web/useDesign';
  16 + import { isFunction } from '/@/utils/is';
  17 +
  18 + interface DeviceModel extends RawDeviceModal {
  19 + disabled?: boolean;
  20 + }
  21 +
  22 + const props = withDefaults(
  23 + defineProps<{
  24 + getPendingTableParams: (params: Recordable) => any;
  25 + getSelectedTableParams: (params: Recordable) => any;
  26 + value?: (Recordable & DeviceModel)[];
  27 + maxTagLength?: number;
  28 + openModalValidate?: () => boolean;
  29 + primaryKey?: string;
  30 + transformValue?: (list: Recordable[]) => any;
  31 + }>(),
  32 + {
  33 + value: () => [],
  34 + maxTagLength: 2,
  35 + primaryKey: 'tbDeviceId',
  36 + }
  37 + );
  38 +
  39 + const emit = defineEmits(['update:value']);
  40 +
  41 + enum Active {
  42 + PENDING = 'pending',
  43 + SELECTED = 'selected',
  44 + }
  45 +
  46 + const activeKey = ref(Active.PENDING);
  47 +
  48 + const { prefixCls } = useDesign('transfer-table-modal');
  49 +
  50 + const pendingTotalList = ref<DeviceModel[]>([]);
  51 +
  52 + const pendingConfirmQueue = ref<DeviceModel[]>([]);
  53 +
  54 + const selectedTotalList = ref<DeviceModel[]>([]);
  55 +
  56 + const selectedConfirmQueue = ref<DeviceModel[]>([]);
  57 +
  58 + const getShowTagOptions = computed(() => {
  59 + const { maxTagLength } = props;
  60 + return unref(selectedTotalList).slice(0, maxTagLength);
  61 + });
  62 +
  63 + const getSurplusOptionsLength = computed(() => {
  64 + const { maxTagLength } = props;
  65 + const surplusValue = unref(selectedTotalList).length - maxTagLength;
  66 + return surplusValue < 0 ? 0 : surplusValue;
  67 + });
  68 +
  69 + // const pendingListCount = computed(() => {
  70 + // const { value } = props;
  71 + // const selectedList = unref(pendingTotalList).filter((item) => value.includes(item.id));
  72 + // return unref(pendingTotalList).length - selectedList.length;
  73 + // });
  74 +
  75 + const [registerModal, { openModal }] = useModal();
  76 +
  77 + const [regsterPendingTable, pendingTableActionType] = useTable({
  78 + ...TransferTableProps,
  79 + rowKey: props.primaryKey,
  80 + api: devicePage,
  81 + immediate: false,
  82 + clickToRowSelect: false,
  83 + beforeFetch: (params) => {
  84 + const { getPendingTableParams } = props;
  85 + const data = getPendingTableParams?.(params) || {};
  86 + Object.assign(params, { ...data, selected: false });
  87 + return params;
  88 + },
  89 + afterFetch: (list: DeviceModel[]) => {
  90 + pendingTotalList.value = list;
  91 + return unref(pendingTotalList);
  92 + },
  93 + rowSelection: {
  94 + type: 'checkbox',
  95 + getCheckboxProps: (record: DeviceModel) => {
  96 + const { primaryKey } = props;
  97 + const checked = unref(selectedTotalList).map((item) => item[primaryKey]);
  98 + return {
  99 + disabled: checked.includes(record[props.primaryKey]!),
  100 + };
  101 + },
  102 + onSelect: (_record: Recordable, _selected: boolean, selectedRows: DeviceModel[]) => {
  103 + const { primaryKey } = props;
  104 + const checked = unref(selectedTotalList).map((item) => item[primaryKey]);
  105 + pendingConfirmQueue.value = selectedRows.filter(
  106 + (item) => !checked.includes(item[primaryKey]!)
  107 + );
  108 + },
  109 + onSelectAll: (_selected: boolean, selectedRows: DeviceModel[]) => {
  110 + const { primaryKey } = props;
  111 + const checked = unref(selectedTotalList).map((item) => item[primaryKey]);
  112 + pendingConfirmQueue.value = selectedRows.filter(
  113 + (item) => !checked.includes(item[primaryKey]!)
  114 + );
  115 + },
  116 + },
  117 + });
  118 +
  119 + const [registerSelectedTable, selectedTableActionType] = useTable({
  120 + formConfig: {
  121 + layout: 'inline',
  122 + labelWidth: 80,
  123 + schemas: deviceTableFormSchema,
  124 + actionColOptions: { span: 6 },
  125 + },
  126 + size: 'small',
  127 + maxHeight: 240,
  128 + useSearchForm: true,
  129 + columns: deviceTableColumn,
  130 + api: async (params) => {
  131 + const { name = '', deviceType = '' } = params || {};
  132 + const items = unref(selectedTotalList).filter((item) => {
  133 + return (
  134 + item.name.toUpperCase().includes(name.toUpperCase()) &&
  135 + item.deviceType.toUpperCase().includes(deviceType.toUpperCase())
  136 + );
  137 + });
  138 + return {
  139 + items,
  140 + total: items.length,
  141 + };
  142 + },
  143 + showIndexColumn: false,
  144 + pagination: { hideOnSinglePage: false },
  145 + fetchSetting: FETCH_SETTING,
  146 + rowKey: props.primaryKey,
  147 + dataSource: selectedTotalList,
  148 + clickToRowSelect: false,
  149 + beforeFetch: (params) => {
  150 + const { getSelectedTableParams } = props;
  151 + const data = getSelectedTableParams?.(params) || {};
  152 + Object.assign(params, { ...data, selected: false });
  153 + return params;
  154 + },
  155 + rowSelection: {
  156 + type: 'checkbox',
  157 + onSelect: (_record: Recordable, _selected: boolean, selectedRows: DeviceModel[]) => {
  158 + selectedConfirmQueue.value = selectedRows;
  159 + },
  160 + onSelectAll: (_selected: boolean, selectedRows: DeviceModel[]) => {
  161 + selectedConfirmQueue.value = selectedRows;
  162 + },
  163 + },
  164 + });
  165 +
  166 + const handleTriggerUpdateValue = () => {
  167 + let list: Recordable[] = cloneDeep(toRaw(unref(selectedTotalList)));
  168 + const { transformValue } = props;
  169 + if (transformValue && isFunction(transformValue)) list = transformValue(list);
  170 +
  171 + emit('update:value', list);
  172 + };
  173 +
  174 + const handleSelected = () => {
  175 + const { primaryKey } = props;
  176 + const _list = [...unref(selectedTotalList), ...unref(pendingConfirmQueue)];
  177 + selectedTotalList.value = uniqBy(_list, primaryKey);
  178 + pendingConfirmQueue.value = [];
  179 +
  180 + handleTriggerUpdateValue();
  181 + pendingTableActionType.setTableData([]);
  182 + nextTick(() => pendingTableActionType.setTableData(unref(pendingTotalList)));
  183 + };
  184 +
  185 + const handleRemoveSelected = () => {
  186 + const { primaryKey } = props;
  187 + const selectedIds = unref(selectedConfirmQueue).map((selected) => selected[primaryKey]);
  188 + remove(unref(selectedTotalList), (item) => selectedIds.includes(item[primaryKey]));
  189 +
  190 + handleTriggerUpdateValue();
  191 +
  192 + selectedTableActionType.clearSelectedRowKeys();
  193 + selectedConfirmQueue.value = [];
  194 + selectedTableActionType.reload();
  195 + };
  196 +
  197 + const handleCheckoutPanel = async () => {
  198 + await nextTick();
  199 + selectedTableActionType.reload();
  200 + };
  201 +
  202 + const handleOpenModal = async () => {
  203 + const { openModalValidate } = props;
  204 +
  205 + if (openModalValidate && isFunction(openModalValidate) && !openModalValidate()) return;
  206 +
  207 + openModal(true);
  208 + await nextTick();
  209 + pendingTableActionType.reload();
  210 + };
  211 +
  212 + onMounted(async () => {
  213 + const { getSelectedTableParams } = props;
  214 + const data = getSelectedTableParams?.({}) || {};
  215 + if (!data?.convertConfigId || !data?.deviceProfileIds) {
  216 + return;
  217 + }
  218 + const { items } = await devicePage({ page: 1, pageSize: 10, ...data, selected: true });
  219 + selectedTotalList.value = items;
  220 + });
  221 +</script>
  222 +
  223 +<template>
  224 + <section>
  225 + <BasicModal
  226 + @register="registerModal"
  227 + title="穿梭表格"
  228 + width="60%"
  229 + :wrapClassName="prefixCls"
  230 + :showOkBtn="false"
  231 + cancelText="关闭"
  232 + >
  233 + <section class="bg-gray-100">
  234 + <Tabs v-model:active-key="activeKey" type="card" @change="handleCheckoutPanel">
  235 + <Tabs.TabPane :key="Active.PENDING">
  236 + <template #tab>
  237 + <div class="flex items-center justify-center">
  238 + <span>待选设备</span>
  239 + <!-- <Badge show-zero :count="pendingListCount" /> -->
  240 + </div>
  241 + </template>
  242 + <BasicTable @register="regsterPendingTable">
  243 + <template #toolbar>
  244 + <section class="flex w-full justify-end items-center">
  245 + <!-- <Button type="primary">全选</Button> -->
  246 + <div class="text-blue-400">
  247 + <span class="mr-2">选择设备:</span>
  248 + <span>{{ pendingConfirmQueue.length }}</span>
  249 + </div>
  250 + </section>
  251 + </template>
  252 + </BasicTable>
  253 + <section class="flex justify-end px-4 pb-4">
  254 + <Button
  255 + type="primary"
  256 + @click="handleSelected"
  257 + :disabled="!pendingConfirmQueue.length"
  258 + >
  259 + <span>确定已选</span>
  260 + </Button>
  261 + </section>
  262 + </Tabs.TabPane>
  263 + <Tabs.TabPane :key="Active.SELECTED">
  264 + <template #tab>
  265 + <div class="flex items-center justify-center">
  266 + <span>已选设备</span>
  267 + <!-- <Badge show-zero :count="selectedTotalList.length" /> -->
  268 + </div>
  269 + </template>
  270 + <BasicTable @register="registerSelectedTable">
  271 + <template #toolbar>
  272 + <section class="flex w-full justify-end items-center">
  273 + <div class="text-blue-400">
  274 + <span class="mr-2">选择设备:</span>
  275 + <span>{{ selectedConfirmQueue.length }}</span>
  276 + </div>
  277 + </section>
  278 + </template>
  279 + </BasicTable>
  280 + <section class="flex justify-end px-4 pb-4">
  281 + <Button
  282 + type="primary"
  283 + :disabled="!selectedConfirmQueue.length"
  284 + @click="handleRemoveSelected"
  285 + >
  286 + <span>移除已选</span>
  287 + </Button>
  288 + </section>
  289 + </Tabs.TabPane>
  290 + </Tabs>
  291 + </section>
  292 + </BasicModal>
  293 + <Button @click="handleOpenModal" type="link">
  294 + <span v-if="!selectedTotalList.length">选择设备</span>
  295 + <div v-if="selectedTotalList.length">
  296 + <Tag
  297 + class="!px-2 !py-1 !bg-gray-50 !border-gray-100"
  298 + v-for="item in getShowTagOptions"
  299 + :key="item[primaryKey]"
  300 + >
  301 + <span>
  302 + {{ item.alias || item.name }}
  303 + </span>
  304 + </Tag>
  305 + <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength">
  306 + <span> +{{ getSurplusOptionsLength }}... </span>
  307 + </Tag>
  308 + </div>
  309 + </Button>
  310 + </section>
  311 +</template>
  312 +
  313 +<style lang="less">
  314 + @prefix-cls: ~'@{namespace}-transfer-table-modal';
  315 +
  316 + .@{prefix-cls} {
  317 + .vben-basic-table {
  318 + padding-top: 0;
  319 + }
  320 +
  321 + .vben-basic-form > .ant-row {
  322 + width: 100%;
  323 + }
  324 +
  325 + .ant-tabs-top-bar {
  326 + background-color: #fff;
  327 + }
  328 +
  329 + .transfer-table-disabled-row {
  330 + :deep(.ant-checkbox) {
  331 + cursor: not-allowed;
  332 +
  333 + .ant-checkbox-inner {
  334 + background-color: #f5f5f5;
  335 + border-color: #d9d9d9 !important;
  336 + }
  337 + }
  338 + }
  339 + }
  340 +</style>
... ...
1 1 import { FormSchema } from '/@/components/Form';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3   -import { h, unref } from 'vue';
4 3 import { getDeviceProfile } from '/@/api/alarm/position';
5   -import { BasicColumn, BasicTableProps } from '/@/components/Table';
6   -import { devicePage } from '/@/api/device/deviceManager';
7   -import { Tag } from 'ant-design-vue';
  4 +import { BasicInfoFormField, DataSourceType } from '../enum';
8 5 import { DeviceRecord } from '/@/api/device/model/deviceModel';
9   -import { FETCH_SETTING } from '/@/components/Table/src/const';
10   -import { useMessage } from '/@/hooks/web/useMessage';
11   -import {
12   - BasicInfoFormField,
13   - DataSourceType,
14   - DeviceStatusEnum,
15   - DeviceStatusNameEnum,
16   - DeviceTypeNameEnum,
17   -} from '../enum';
18   -import { useClipboard } from '@vueuse/core';
19 6
20 7 export const stepConfig = ['选择流转方式', '完善配置参数'];
21 8
22 9 export const removeFieldByModeForm = ['name', 'description'];
23 10
24   -//表单通用配置
25   -export const modelFormPublicConfig = {
26   - labelWidth: 120,
27   - actionColOptions: {
28   - span: 14,
29   - },
30   - showResetButton: false,
31   - showSubmitButton: false,
32   -};
33   -
34 11 const handleGroupDevice = (options: DeviceRecord[]) => {
35 12 const map = new Map<string, string[]>();
36 13 options.forEach((item) => {
... ... @@ -46,111 +23,17 @@ const handleGroupDevice = (options: DeviceRecord[]) => {
46 23 return value;
47 24 };
48 25
49   -const deviceTableFormSchema: FormSchema[] = [
50   - {
51   - field: 'name',
52   - label: '设备名称',
53   - component: 'Input',
54   - colProps: { span: 9 },
55   - componentProps: {
56   - placeholder: '请输入设备名称',
57   - },
58   - },
59   - {
60   - field: 'deviceType',
61   - label: '设备类型',
62   - component: 'ApiSelect',
63   - colProps: { span: 9 },
64   - componentProps: {
65   - placeholder: '请选择设备类型',
66   - api: findDictItemByCode,
67   - params: {
68   - dictCode: 'device_type',
69   - },
70   - labelField: 'itemText',
71   - valueField: 'itemValue',
72   - },
73   - },
74   -];
75   -
76   -const { copied, copy } = useClipboard({ legacy: true });
77   -
78   -const { createMessage } = useMessage();
79   -
80   -const deviceTableColumn: BasicColumn[] = [
81   - {
82   - title: '状态',
83   - dataIndex: 'deviceState',
84   - customRender: ({ text }) => {
85   - return h(
86   - Tag,
87   - {
88   - color:
89   - text === DeviceStatusEnum.INACTIVE
90   - ? 'warning'
91   - : text === DeviceStatusEnum.OFFLINE
92   - ? 'error'
93   - : 'success',
94   - },
95   - () => DeviceStatusNameEnum[text]
96   - );
97   - },
98   - },
99   - {
100   - title: '别名/设备名称',
101   - dataIndex: 'name',
102   - customRender: ({ record }) => {
103   - return h('div', [
104   - h(
105   - 'div',
106   - {
107   - class: 'cursor-pointer',
108   - onClick: async () => {
109   - await copy(record.name);
110   - if (unref(copied)) createMessage.success('复制成功~');
111   - },
112   - },
113   - [
114   - record.alias && h('div', { class: 'truncate' }, record.alias),
115   - h('div', { class: 'text-blue-400 truncate' }, record.name),
116   - ]
117   - ),
118   - ]);
119   - },
120   - },
121   - {
122   - title: '设备类型',
123   - dataIndex: 'deviceType',
124   - customRender: ({ text }) => {
125   - return h(Tag, { color: 'success' }, () => DeviceTypeNameEnum[text]);
126   - },
127   - },
128   - {
129   - title: '所属产品',
130   - dataIndex: 'deviceProfile.name',
131   - },
132   - {
133   - title: '所属组织',
134   - dataIndex: 'organizationDTO.name',
135   - },
136   -];
137   -
138   -const TransferTableProps: BasicTableProps = {
139   - formConfig: {
140   - layout: 'inline',
141   - labelWidth: 80,
142   - schemas: deviceTableFormSchema,
143   - actionColOptions: { span: 6 },
  26 +//表单通用配置
  27 +export const modelFormPublicConfig = {
  28 + labelWidth: 120,
  29 + actionColOptions: {
  30 + span: 14,
144 31 },
145   - size: 'small',
146   - maxHeight: 240,
147   - useSearchForm: true,
148   - columns: deviceTableColumn,
149   - showIndexColumn: false,
150   - fetchSetting: FETCH_SETTING,
151   -} as BasicTableProps;
  32 + showResetButton: false,
  33 + showSubmitButton: false,
  34 +};
152 35
153   -export const modeForm = (submitFn?: Function): FormSchema[] => {
  36 +export const modeForm = (): FormSchema[] => {
154 37 return [
155 38 {
156 39 field: BasicInfoFormField.CONVERT_CONFIG_ID,
... ... @@ -214,69 +97,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => {
214 97 rules: [{ required: true, message: '数据源设备为必选项', type: 'array' }],
215 98 componentProps: ({ formActionType }) => {
216 99 const { getFieldsValue } = formActionType;
217   - const values = getFieldsValue();
218   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
219   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
220   -
221 100 return {
222   - labelField: 'name',
223   - valueField: 'tbDeviceId',
224   - primaryKey: 'tbDeviceId',
225   - pendingTableProps: {
226   - ...TransferTableProps,
227   - api: devicePage,
228   - beforeFetch: (params) => {
229   - const values = getFieldsValue();
230   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
231   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
232   - if (convertConfigId) {
233   - Object.assign(params, { convertConfigId, selected: false });
234   - }
235   - return { ...params, deviceProfileIds };
236   - },
237   - } as BasicTableProps,
238   - selectedTableProps: {
239   - ...TransferTableProps,
240   - // api
241   - api: !!(convertConfigId && devices) ? devicePage : undefined,
242   - beforeFetch: (params) => {
243   - const values = getFieldsValue();
244   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
245   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
246   - if (convertConfigId) {
247   - Object.assign(params, { convertConfigId, selected: true });
248   - }
249   - return { ...params, deviceProfileIds };
250   - },
251   - } as BasicTableProps,
252   - initSelectedOptions: async ({ setSelectedTotal }) => {
  101 + getPendingTableParams: () => {
253 102 const values = getFieldsValue();
254 103 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
255 104 const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
256   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
257   - if (convertConfigId && devices) {
258   - const { items, total } = await devicePage({
259   - page: 1,
260   - pageSize: 10,
261   - convertConfigId: values[BasicInfoFormField.CONVERT_CONFIG_ID],
262   - deviceProfileIds,
263   - selected: true,
264   - });
265   - setSelectedTotal(total);
266   - return items;
267   - }
268   - return [];
  105 + return { convertConfigId, deviceProfileIds };
269 106 },
270   - onSelectedAfter: async () => {
271   - submitFn && (await submitFn(false));
272   - },
273   - onRemoveAfter: async ({ reloadSelected }) => {
274   - submitFn && (await submitFn(false));
275   - reloadSelected();
276   - },
277   - transformValue: (_selectedRowKeys: string[], selectedRows: DeviceRecord[]) => {
278   - return handleGroupDevice(selectedRows);
  107 + getSelectedTableParams: () => {
  108 + const values = getFieldsValue();
  109 + const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
  110 + const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
  111 + return { convertConfigId, deviceProfileIds };
279 112 },
  113 + transformValue: handleGroupDevice,
280 114 };
281 115 },
282 116 },
... ...
1 1 import { FormSchema } from '/@/components/Form';
2 2 import { findDictItemByCode } from '/@/api/system/dict';
3   -import { h, ref, unref } from 'vue';
  3 +import { ref } from 'vue';
4 4 import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi';
5 5 import { getDeviceProfile } from '/@/api/alarm/position';
6   -import { BasicColumn, BasicTableProps } from '/@/components/Table';
7   -import { devicePage } from '/@/api/device/deviceManager';
8   -import { Tag } from 'ant-design-vue';
9 6 import { DeviceRecord } from '/@/api/device/model/deviceModel';
10   -import { FETCH_SETTING } from '/@/components/Table/src/const';
11   -import { useClipboard } from '@vueuse/core';
12   -import { useMessage } from '/@/hooks/web/useMessage';
13 7
14 8 const typeValue = ref('');
15 9 export enum CredentialsEnum {
... ... @@ -76,108 +70,7 @@ const handleGroupDevice = (options: DeviceRecord[]) => {
76 70 return value;
77 71 };
78 72
79   -const deviceTableFormSchema: FormSchema[] = [
80   - {
81   - field: 'name',
82   - label: '设备名称',
83   - component: 'Input',
84   - colProps: { span: 9 },
85   - componentProps: {
86   - placeholder: '请输入设备名称',
87   - },
88   - },
89   - {
90   - field: 'deviceType',
91   - label: '设备类型',
92   - component: 'ApiSelect',
93   - colProps: { span: 9 },
94   - componentProps: {
95   - placeholder: '请选择设备类型',
96   - api: findDictItemByCode,
97   - params: {
98   - dictCode: 'device_type',
99   - },
100   - labelField: 'itemText',
101   - valueField: 'itemValue',
102   - },
103   - },
104   -];
105   -const { copied, copy } = useClipboard({ legacy: true });
106   -const { createMessage } = useMessage();
107   -const deviceTableColumn: BasicColumn[] = [
108   - {
109   - title: '状态',
110   - dataIndex: 'deviceState',
111   - customRender: ({ text }) => {
112   - return h(
113   - Tag,
114   - {
115   - color:
116   - text === DeviceStatusEnum.INACTIVE
117   - ? 'warning'
118   - : text === DeviceStatusEnum.OFFLINE
119   - ? 'error'
120   - : 'success',
121   - },
122   - () => DeviceStatusNameEnum[text]
123   - );
124   - },
125   - },
126   - {
127   - title: '别名/设备名称',
128   - dataIndex: 'name',
129   - customRender: ({ record }) => {
130   - return h('div', [
131   - h(
132   - 'div',
133   - {
134   - class: 'cursor-pointer',
135   - onClick: async () => {
136   - await copy(record.name);
137   - if (unref(copied)) createMessage.success('复制成功~');
138   - },
139   - },
140   - [
141   - record.alias && h('div', { class: 'truncate' }, record.alias),
142   - h('div', { class: 'text-blue-400 truncate' }, record.name),
143   - ]
144   - ),
145   - ]);
146   - },
147   - },
148   - {
149   - title: '设备类型',
150   - dataIndex: 'deviceType',
151   - customRender: ({ text }) => {
152   - return h(Tag, { color: 'success' }, () => DeviceTypeNameEnum[text]);
153   - },
154   - },
155   - {
156   - title: '所属产品',
157   - dataIndex: 'deviceProfile.name',
158   - },
159   - {
160   - title: '所属组织',
161   - dataIndex: 'organizationDTO.name',
162   - },
163   -];
164   -
165   -const TransferTableProps: BasicTableProps = {
166   - formConfig: {
167   - layout: 'inline',
168   - labelWidth: 80,
169   - schemas: deviceTableFormSchema,
170   - actionColOptions: { span: 6 },
171   - },
172   - size: 'small',
173   - maxHeight: 240,
174   - useSearchForm: true,
175   - columns: deviceTableColumn,
176   - showIndexColumn: false,
177   - fetchSetting: FETCH_SETTING,
178   -} as BasicTableProps;
179   -
180   -export const modeForm = (submitFn?: Function): FormSchema[] => {
  73 +export const modeForm = (): FormSchema[] => {
181 74 return [
182 75 {
183 76 field: BasicInfoFormField.CONVERT_CONFIG_ID,
... ... @@ -239,69 +132,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => {
239 132 changeEvent: 'update:value',
240 133 componentProps: ({ formActionType }) => {
241 134 const { getFieldsValue } = formActionType;
242   - const values = getFieldsValue();
243   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
244   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
245   -
246 135 return {
247   - labelField: 'name',
248   - valueField: 'tbDeviceId',
249   - primaryKey: 'tbDeviceId',
250   - pendingTableProps: {
251   - ...TransferTableProps,
252   - api: devicePage,
253   - beforeFetch: (params) => {
254   - const values = getFieldsValue();
255   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
256   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
257   - if (convertConfigId) {
258   - Object.assign(params, { convertConfigId, selected: false });
259   - }
260   - return { ...params, deviceProfileIds };
261   - },
262   - } as BasicTableProps,
263   - selectedTableProps: {
264   - ...TransferTableProps,
265   - // api
266   - api: !!(convertConfigId && devices) ? devicePage : undefined,
267   - beforeFetch: (params) => {
268   - const values = getFieldsValue();
269   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
270   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
271   - if (convertConfigId) {
272   - Object.assign(params, { convertConfigId, selected: true });
273   - }
274   - return { ...params, deviceProfileIds };
275   - },
276   - } as BasicTableProps,
277   - initSelectedOptions: async ({ setSelectedTotal }) => {
  136 + getPendingTableParams: () => {
278 137 const values = getFieldsValue();
279 138 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
280 139 const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
281   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
282   - if (convertConfigId && devices) {
283   - const { items, total } = await devicePage({
284   - page: 1,
285   - pageSize: 10,
286   - convertConfigId: values[BasicInfoFormField.CONVERT_CONFIG_ID],
287   - deviceProfileIds,
288   - selected: true,
289   - });
290   - setSelectedTotal(total);
291   - return items;
292   - }
293   - return [];
294   - },
295   - onSelectedAfter: async () => {
296   - submitFn && (await submitFn(false));
  140 + return { convertConfigId, deviceProfileIds };
297 141 },
298   - onRemoveAfter: async ({ reloadSelected }) => {
299   - submitFn && (await submitFn(false));
300   - reloadSelected();
301   - },
302   - transformValue: (_selectedRowKeys: string[], selectedRows: DeviceRecord[]) => {
303   - return handleGroupDevice(selectedRows);
  142 + getSelectedTableParams: () => {
  143 + const values = getFieldsValue();
  144 + const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
  145 + const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
  146 + return { convertConfigId, deviceProfileIds };
304 147 },
  148 + transformValue: handleGroupDevice,
305 149 };
306 150 },
307 151 },
... ...