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,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 | }, |