Showing
7 changed files
with
481 additions
and
791 deletions
src/components/Form/src/components/TransferTableModal.vue
deleted
100644 → 0
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 | }, | ... | ... |