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,7 +61,6 @@
61 //input动态数据 61 //input动态数据
62 const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] }); 62 const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
63 63
64 - console.log(dynamicInput, 'dynamicInput');  
65 //删除Input 64 //删除Input
66 const remove = (item: Params) => { 65 const remove = (item: Params) => {
67 let index = dynamicInput.params.indexOf(item); 66 let index = dynamicInput.params.indexOf(item);
@@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
37 import { BasicModal, useModalInner } from '/@/components/Modal'; 37 import { BasicModal, useModalInner } from '/@/components/Modal';
38 import { add } from '/@/components/Form/src/componentMap'; 38 import { add } from '/@/components/Form/src/componentMap';
39 import TransferModal from '/@/components/Form/src/components/TransferModal.vue'; 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 import { DataFlowMethod, DataFlowParams } from './index'; 41 import { DataFlowMethod, DataFlowParams } from './index';
42 import { stepConfig, removeFieldByModeForm } from './config'; 42 import { stepConfig, removeFieldByModeForm } from './config';
43 import { postAddConvertApi } from '/@/api/datamanager/dataManagerApi'; 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 import { FormSchema } from '/@/components/Form'; 1 import { FormSchema } from '/@/components/Form';
2 import { findDictItemByCode } from '/@/api/system/dict'; 2 import { findDictItemByCode } from '/@/api/system/dict';
3 -import { h, unref } from 'vue';  
4 import { getDeviceProfile } from '/@/api/alarm/position'; 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 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 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 export const stepConfig = ['选择流转方式', '完善配置参数']; 7 export const stepConfig = ['选择流转方式', '完善配置参数'];
21 8
22 export const removeFieldByModeForm = ['name', 'description']; 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 const handleGroupDevice = (options: DeviceRecord[]) => { 11 const handleGroupDevice = (options: DeviceRecord[]) => {
35 const map = new Map<string, string[]>(); 12 const map = new Map<string, string[]>();
36 options.forEach((item) => { 13 options.forEach((item) => {
@@ -46,111 +23,17 @@ const handleGroupDevice = (options: DeviceRecord[]) => { @@ -46,111 +23,17 @@ const handleGroupDevice = (options: DeviceRecord[]) => {
46 return value; 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 return [ 37 return [
155 { 38 {
156 field: BasicInfoFormField.CONVERT_CONFIG_ID, 39 field: BasicInfoFormField.CONVERT_CONFIG_ID,
@@ -214,69 +97,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => { @@ -214,69 +97,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => {
214 rules: [{ required: true, message: '数据源设备为必选项', type: 'array' }], 97 rules: [{ required: true, message: '数据源设备为必选项', type: 'array' }],
215 componentProps: ({ formActionType }) => { 98 componentProps: ({ formActionType }) => {
216 const { getFieldsValue } = formActionType; 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 return { 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 const values = getFieldsValue(); 102 const values = getFieldsValue();
254 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID); 103 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
255 const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT); 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 import { FormSchema } from '/@/components/Form'; 1 import { FormSchema } from '/@/components/Form';
2 import { findDictItemByCode } from '/@/api/system/dict'; 2 import { findDictItemByCode } from '/@/api/system/dict';
3 -import { h, ref, unref } from 'vue'; 3 +import { ref } from 'vue';
4 import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi'; 4 import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi';
5 import { getDeviceProfile } from '/@/api/alarm/position'; 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 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 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 const typeValue = ref(''); 8 const typeValue = ref('');
15 export enum CredentialsEnum { 9 export enum CredentialsEnum {
@@ -76,108 +70,7 @@ const handleGroupDevice = (options: DeviceRecord[]) => { @@ -76,108 +70,7 @@ const handleGroupDevice = (options: DeviceRecord[]) => {
76 return value; 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 return [ 74 return [
182 { 75 {
183 field: BasicInfoFormField.CONVERT_CONFIG_ID, 76 field: BasicInfoFormField.CONVERT_CONFIG_ID,
@@ -239,69 +132,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => { @@ -239,69 +132,20 @@ export const modeForm = (submitFn?: Function): FormSchema[] => {
239 changeEvent: 'update:value', 132 changeEvent: 'update:value',
240 componentProps: ({ formActionType }) => { 133 componentProps: ({ formActionType }) => {
241 const { getFieldsValue } = formActionType; 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 return { 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 const values = getFieldsValue(); 137 const values = getFieldsValue();
279 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID); 138 const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
280 const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT); 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 },