Commit 3502b7d09e5ce7ba96e9770dee2a73ea658aa503
Merge branch 'fix/DEFECT-1763' into 'main_dev'
fix: 修复数据流转产品变更设备未清空 See merge request yunteng/thingskit-front!1025
Showing
5 changed files
with
72 additions
and
553 deletions
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { Button, Transfer, Tag } from 'ant-design-vue'; | 2 | + import { Transfer, Select } from 'ant-design-vue'; |
3 | import { cloneDeep, get } from 'lodash-es'; | 3 | import { cloneDeep, get } from 'lodash-es'; |
4 | import { computed, CSSProperties, ExtractPropTypes, onMounted, ref, unref, watch } from 'vue'; | 4 | import { computed, CSSProperties, ExtractPropTypes, onMounted, ref, unref, watch } from 'vue'; |
5 | import { BasicModal, useModal } from '/@/components/Modal'; | 5 | import { BasicModal, useModal } from '/@/components/Modal'; |
@@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
29 | buttonName?: string; | 29 | buttonName?: string; |
30 | modalProps?: ExtractPropTypes<InstanceType<typeof BasicModal>['$props']>; | 30 | modalProps?: ExtractPropTypes<InstanceType<typeof BasicModal>['$props']>; |
31 | transferProps?: ExtractPropTypes<TransferType['$props']>; | 31 | transferProps?: ExtractPropTypes<TransferType['$props']>; |
32 | - buttonProps?: ExtractPropTypes<InstanceType<typeof Button>['$props']>; | 32 | + selectProps?: ExtractPropTypes<InstanceType<typeof Select>['$props']>; |
33 | disabled?: any; | 33 | disabled?: any; |
34 | }>(), | 34 | }>(), |
35 | { | 35 | { |
@@ -52,24 +52,15 @@ | @@ -52,24 +52,15 @@ | ||
52 | return unref(getOptions).filter((item) => unref(targetKeys).includes(item[valueField])); | 52 | return unref(getOptions).filter((item) => unref(targetKeys).includes(item[valueField])); |
53 | }); | 53 | }); |
54 | 54 | ||
55 | - const getShowTagOptions = computed(() => { | ||
56 | - const { maxTagLength } = props; | ||
57 | - return unref(targetOptions).slice(0, maxTagLength); | 55 | + const getSelectOptions = computed(() => { |
56 | + return unref(targetOptions).map((item) => ({ ...item, label: item.title, value: item.key })); | ||
58 | }); | 57 | }); |
59 | 58 | ||
60 | - const getSurplusOptionsLength = computed(() => { | ||
61 | - const { maxTagLength } = props; | ||
62 | - const surplusValue = unref(targetKeys).length - maxTagLength; | ||
63 | - return surplusValue < 0 ? 0 : surplusValue; | ||
64 | - }); | ||
65 | - | ||
66 | - const count = computed(() => { | ||
67 | - return unref(targetKeys).length; | ||
68 | - }); | 59 | + const getSelectValue = computed(() => unref(getSelectOptions).map((item) => item.value)); |
69 | 60 | ||
70 | const targetKeys = ref<string[]>(props.value || []); | 61 | const targetKeys = ref<string[]>(props.value || []); |
71 | 62 | ||
72 | - const getOptions = computed<Recordable[]>(() => { | 63 | + const getOptions = computed<Record<'key' | 'title', string>[]>(() => { |
73 | const { labelField, valueField } = props; | 64 | const { labelField, valueField } = props; |
74 | return unref(options).map((item) => ({ | 65 | return unref(options).map((item) => ({ |
75 | ...item, | 66 | ...item, |
@@ -99,13 +90,14 @@ | @@ -99,13 +90,14 @@ | ||
99 | }; | 90 | }; |
100 | }); | 91 | }); |
101 | 92 | ||
102 | - const getBindButtonProps = computed(() => { | ||
103 | - const { buttonProps = {} } = props; | 93 | + const getBindSelectProps = computed(() => { |
94 | + const { selectProps = {} } = props; | ||
104 | return { | 95 | return { |
105 | - ...buttonProps, | ||
106 | - type: 'link', | ||
107 | - onClick: handleOpenModal, | ||
108 | - } as ExtractPropTypes<InstanceType<typeof Button>['$props']>; | 96 | + maxTagCount: 3, |
97 | + ...selectProps, | ||
98 | + open: false, | ||
99 | + onDropdownVisibleChange: handleOpenModal, | ||
100 | + } as ExtractPropTypes<InstanceType<typeof Select>['$props']>; | ||
109 | }); | 101 | }); |
110 | 102 | ||
111 | const handleChange = (_targetKeys: string[], direction: 'left' | 'right', moveKeys: string[]) => { | 103 | const handleChange = (_targetKeys: string[], direction: 'left' | 'right', moveKeys: string[]) => { |
@@ -165,22 +157,11 @@ | @@ -165,22 +157,11 @@ | ||
165 | <Transfer v-bind="getBindProps" /> | 157 | <Transfer v-bind="getBindProps" /> |
166 | </section> | 158 | </section> |
167 | </BasicModal> | 159 | </BasicModal> |
168 | - <Button v-bind="getBindButtonProps" class="!flex !justify-center !items-center min-h-8"> | ||
169 | - <span v-if="!count">{{ $props.buttonName }}</span> | ||
170 | - <div v-if="!!count"> | ||
171 | - <Tag | ||
172 | - class="!px-2 !py-1 !bg-gray-50 !border-gray-100" | ||
173 | - v-for="item in getShowTagOptions" | ||
174 | - :key="item.key" | ||
175 | - > | ||
176 | - <span> | ||
177 | - {{ item.title }} | ||
178 | - </span> | ||
179 | - </Tag> | ||
180 | - <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength"> | ||
181 | - <span> +{{ getSurplusOptionsLength }}... </span> | ||
182 | - </Tag> | ||
183 | - </div> | ||
184 | - </Button> | 160 | + <Select |
161 | + v-bind="getBindSelectProps" | ||
162 | + :options="getSelectOptions" | ||
163 | + :value="getSelectValue" | ||
164 | + mode="multiple" | ||
165 | + /> | ||
185 | </div> | 166 | </div> |
186 | </template> | 167 | </template> |
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 | - disabled?: any; | ||
46 | - }>(), | ||
47 | - { | ||
48 | - buttonName: '选择设备', | ||
49 | - primaryKey: 'id', | ||
50 | - maxTagLength: 2, | ||
51 | - labelField: 'label', | ||
52 | - valueField: 'value', | ||
53 | - disabled: false, | ||
54 | - } | ||
55 | - ); | ||
56 | - | ||
57 | - const { prefixCls } = useDesign('transfer-table-modal'); | ||
58 | - | ||
59 | - const activeKey = ref<Active>(Active.PENDING); | ||
60 | - | ||
61 | - const selectedRows = ref<Options[]>([]); | ||
62 | - | ||
63 | - const selectedRowKeys = ref<string[]>(props.value || []); | ||
64 | - | ||
65 | - const pendingOptions = ref<Options[]>([]); | ||
66 | - | ||
67 | - const selectedConfirmQueue = ref<Options[]>([]); | ||
68 | - | ||
69 | - const pendingConfirmQueue = ref<Options[]>([]); | ||
70 | - | ||
71 | - const selectedTotal = ref(0); | ||
72 | - | ||
73 | - const pendingTotal = ref(0); | ||
74 | - | ||
75 | - const getFetchSetting = computed(() => { | ||
76 | - const { pendingTableProps } = props; | ||
77 | - return pendingTableProps?.fetchSetting || FETCH_SETTING; | ||
78 | - }); | ||
79 | - | ||
80 | - const getPendingRowSelection = computed<TableRowSelection>(() => { | ||
81 | - const rowKeys = unref(selectedRowKeys); | ||
82 | - return { | ||
83 | - type: 'checkbox', | ||
84 | - getCheckboxProps: (record: Recordable) => { | ||
85 | - const { primaryKey } = props; | ||
86 | - return { | ||
87 | - ...record, | ||
88 | - disabled: rowKeys.includes(record[primaryKey]), | ||
89 | - }; | ||
90 | - }, | ||
91 | - onSelect: (_record: Recordable, _selected: boolean, selectedRows: Object[]) => { | ||
92 | - pendingConfirmQueue.value = selectedRows; | ||
93 | - }, | ||
94 | - onSelectAll: (_selected: boolean, selectedRows: Recordable[]) => { | ||
95 | - pendingConfirmQueue.value = selectedRows; | ||
96 | - }, | ||
97 | - }; | ||
98 | - }); | ||
99 | - | ||
100 | - const getPendingTableBindProps = computed<Partial<DynamicProps<BasicTableProps>>>(() => { | ||
101 | - const { pendingTableProps, primaryKey } = props; | ||
102 | - return { | ||
103 | - ...pendingTableProps, | ||
104 | - rowKey: primaryKey, | ||
105 | - api: handlePendingApiIntercept, | ||
106 | - clickToRowSelect: false, | ||
107 | - rowSelection: getPendingRowSelection, | ||
108 | - }; | ||
109 | - }); | ||
110 | - | ||
111 | - const getSelectedTableBindProps = computed<Partial<DynamicProps<BasicTableProps>>>(() => { | ||
112 | - const { selectedTableProps, primaryKey } = props; | ||
113 | - return { | ||
114 | - ...selectedTableProps, | ||
115 | - dataSource: selectedRows, | ||
116 | - clickToRowSelect: false, | ||
117 | - rowKey: primaryKey, | ||
118 | - api: selectedTableProps!.api ? handleSelectedApiIntercept : undefined, | ||
119 | - rowSelection: { | ||
120 | - type: 'checkbox', | ||
121 | - onSelect: (_record: Recordable, _selected: boolean, selectedRows: Object[]) => { | ||
122 | - selectedConfirmQueue.value = selectedRows; | ||
123 | - }, | ||
124 | - onSelectAll: (_selected: boolean, selectedRows: Recordable[]) => { | ||
125 | - selectedConfirmQueue.value = selectedRows; | ||
126 | - }, | ||
127 | - }, | ||
128 | - }; | ||
129 | - }); | ||
130 | - | ||
131 | - const getModalBindProps = computed(() => { | ||
132 | - const { modalProps = {} } = props; | ||
133 | - return { | ||
134 | - width: '60%', | ||
135 | - title: '穿梭表格', | ||
136 | - wrapClassName: prefixCls, | ||
137 | - ...modalProps, | ||
138 | - showOkBtn: false, | ||
139 | - }; | ||
140 | - }); | ||
141 | - | ||
142 | - const getBindButtonProps = computed<ButtonProps>(() => { | ||
143 | - const { buttonProps = {} } = props; | ||
144 | - return { | ||
145 | - type: 'link', | ||
146 | - ...buttonProps, | ||
147 | - }; | ||
148 | - }); | ||
149 | - | ||
150 | - const getShowTagOptions = computed(() => { | ||
151 | - const { maxTagLength } = props; | ||
152 | - return unref(selectedRows).slice(0, maxTagLength); | ||
153 | - }); | ||
154 | - | ||
155 | - const getSurplusOptionsLength = computed(() => { | ||
156 | - const { maxTagLength } = props; | ||
157 | - const surplusValue = unref(selectedRows).length - maxTagLength; | ||
158 | - return surplusValue < 0 ? 0 : surplusValue; | ||
159 | - }); | ||
160 | - | ||
161 | - const [registerModal, { openModal }] = useModal(); | ||
162 | - | ||
163 | - const [ | ||
164 | - regsterPendingTable, | ||
165 | - { | ||
166 | - getSelectRows: getPendingSelectRows, | ||
167 | - getSelectRowKeys: getPendingSelectRowKeys, | ||
168 | - reload: reloadPending, | ||
169 | - clearSelectedRowKeys: clearPendingSelectedRowKeys, | ||
170 | - }, | ||
171 | - ] = useTable(unref(getPendingTableBindProps)); | ||
172 | - | ||
173 | - const [ | ||
174 | - registerSelectedTable, | ||
175 | - { getSelectRowKeys, setProps, clearSelectedRowKeys, reload: reloadSelected }, | ||
176 | - ] = useTable(unref(getSelectedTableBindProps)); | ||
177 | - | ||
178 | - async function handlePendingApiIntercept(params?: Recordable) { | ||
179 | - try { | ||
180 | - const { api } = props.pendingTableProps || {}; | ||
181 | - if (api && isFunction(api)) { | ||
182 | - let options = await api(params); | ||
183 | - pendingOptions.value = options; | ||
184 | - const { totalField, listField } = unref(getFetchSetting); | ||
185 | - const total = get(options, totalField!); | ||
186 | - if (unref(selectedTotal) + unref(pendingTotal) !== total) { | ||
187 | - pendingTotal.value = total; | ||
188 | - } | ||
189 | - let list: Recordable[] = get(options, listField!); | ||
190 | - list = getSelectedRows(list); | ||
191 | - options = set(options, listField!, list); | ||
192 | - return options; | ||
193 | - } | ||
194 | - } catch (error) { | ||
195 | - console.error(error); | ||
196 | - return []; | ||
197 | - } | ||
198 | - return []; | ||
199 | - } | ||
200 | - | ||
201 | - async function handleSelectedApiIntercept(params?: Recordable) { | ||
202 | - try { | ||
203 | - const { api } = props.selectedTableProps || {}; | ||
204 | - if (api && isFunction(api)) { | ||
205 | - let options = await api(params); | ||
206 | - pendingOptions.value = options; | ||
207 | - const { totalField, listField } = unref(getFetchSetting); | ||
208 | - selectedTotal.value = get(options, totalField!); | ||
209 | - let list: Recordable[] = get(options, listField!); | ||
210 | - list = getSelectedRows(list); | ||
211 | - options = set(options, listField!, list); | ||
212 | - return options; | ||
213 | - } | ||
214 | - } catch (error) { | ||
215 | - console.error(error); | ||
216 | - return []; | ||
217 | - } | ||
218 | - return []; | ||
219 | - } | ||
220 | - | ||
221 | - const handleOpenModal = async () => { | ||
222 | - const { disabled } = props; | ||
223 | - if (disabled) return; | ||
224 | - openModal(true); | ||
225 | - await nextTick(); | ||
226 | - if (props.value && !props.value.length) { | ||
227 | - activeKey.value = Active.PENDING; | ||
228 | - reloadPending(); | ||
229 | - } | ||
230 | - }; | ||
231 | - | ||
232 | - const handleTriggerEmit = (selectedRowKeys: string[], selectedRows: Options[]) => { | ||
233 | - const { transformValue } = props; | ||
234 | - let value = selectedRowKeys; | ||
235 | - if (transformValue && isFunction(transformValue)) { | ||
236 | - value = transformValue(selectedRowKeys, selectedRows); | ||
237 | - } | ||
238 | - emit('change', unref(selectedRowKeys), unref(selectedRows)); | ||
239 | - emit('update:value', unref(value)); | ||
240 | - }; | ||
241 | - | ||
242 | - const handleSelected = async () => { | ||
243 | - const { onSelectedAfter } = props; | ||
244 | - const currentPageSelectRows = getPendingSelectRows(); | ||
245 | - const currentPageSelectRowKeys = getPendingSelectRowKeys(); | ||
246 | - const { primaryKey } = props; | ||
247 | - selectedRows.value = uniqBy([...unref(selectedRows), ...currentPageSelectRows], primaryKey); | ||
248 | - selectedRowKeys.value = [...new Set([...unref(selectedRowKeys), ...currentPageSelectRowKeys])]; | ||
249 | - pendingConfirmQueue.value = []; | ||
250 | - // selectedTotal.value = unref(selectedRowKeys).length; | ||
251 | - pendingTotal.value = unref(pendingTotal) - currentPageSelectRows.length; | ||
252 | - selectedTotal.value = unref(selectedTotal) + currentPageSelectRows.length; | ||
253 | - | ||
254 | - clearPendingSelectedRowKeys(); | ||
255 | - handleTriggerEmit(unref(selectedRowKeys), unref(selectedRows)); | ||
256 | - | ||
257 | - if (onSelectedAfter && isFunction(onSelectedAfter)) { | ||
258 | - await onSelectedAfter(actionType); | ||
259 | - } | ||
260 | - reloadPending(); | ||
261 | - }; | ||
262 | - | ||
263 | - const handleRemoveSelected = async () => { | ||
264 | - const { onRemoveAfter } = props; | ||
265 | - const removeRowKeys = getSelectRowKeys(); | ||
266 | - selectedRowKeys.value = unref(selectedRowKeys).filter((key) => !removeRowKeys.includes(key)); | ||
267 | - selectedRows.value = unref(selectedRows).filter((item) => { | ||
268 | - const { primaryKey } = props; | ||
269 | - return unref(selectedRowKeys).includes(item[primaryKey]); | ||
270 | - }); | ||
271 | - pendingTotal.value = unref(pendingTotal) + removeRowKeys.length; | ||
272 | - selectedTotal.value = unref(selectedTotal) - removeRowKeys.length; | ||
273 | - | ||
274 | - clearSelectedRowKeys(); | ||
275 | - selectedConfirmQueue.value = []; | ||
276 | - setProps({ dataSource: unref(selectedRows) }); | ||
277 | - handleTriggerEmit(unref(selectedRowKeys), unref(selectedRows)); | ||
278 | - | ||
279 | - if (onRemoveAfter && isFunction(onRemoveAfter)) { | ||
280 | - await onRemoveAfter(actionType); | ||
281 | - } | ||
282 | - }; | ||
283 | - | ||
284 | - const actionType = { | ||
285 | - setSelectedOptions, | ||
286 | - setSelectedTotal, | ||
287 | - reloadPending, | ||
288 | - reloadSelected, | ||
289 | - }; | ||
290 | - | ||
291 | - const getSelectedRows = (options: Recordable[]) => { | ||
292 | - const { labelField, valueField } = props; | ||
293 | - return options.map((item) => ({ ...item, label: item[labelField], value: item[valueField] })); | ||
294 | - }; | ||
295 | - | ||
296 | - const getSelectedKeys = (options: Recordable[]) => { | ||
297 | - const { primaryKey } = props; | ||
298 | - return options.map((item) => item[primaryKey]); | ||
299 | - }; | ||
300 | - | ||
301 | - function setSelectedOptions(options: Recordable[]) { | ||
302 | - selectedRows.value = getSelectedRows(options); | ||
303 | - selectedRowKeys.value = getSelectedKeys(options); | ||
304 | - } | ||
305 | - | ||
306 | - function setSelectedTotal(number: number) { | ||
307 | - selectedTotal.value = number; | ||
308 | - } | ||
309 | - | ||
310 | - const handleCheckoutPanel = async (keys: Active) => { | ||
311 | - await nextTick(); | ||
312 | - if (keys === Active.PENDING) { | ||
313 | - reloadPending(); | ||
314 | - } else { | ||
315 | - reloadSelected(); | ||
316 | - setProps({ | ||
317 | - dataSource: unref(selectedRows), | ||
318 | - }); | ||
319 | - } | ||
320 | - }; | ||
321 | - | ||
322 | - watch( | ||
323 | - () => props.value, | ||
324 | - () => { | ||
325 | - if (props.value && !props.value.length) { | ||
326 | - selectedRowKeys.value = []; | ||
327 | - selectedRows.value = []; | ||
328 | - // pendingTotal.value = 0; | ||
329 | - selectedTotal.value = 0; | ||
330 | - } | ||
331 | - } | ||
332 | - ); | ||
333 | - | ||
334 | - onMounted(async () => { | ||
335 | - const { initSelectedOptions } = props; | ||
336 | - if (initSelectedOptions && isFunction(initSelectedOptions)) { | ||
337 | - const options = await initSelectedOptions(actionType); | ||
338 | - setSelectedOptions(options); | ||
339 | - } | ||
340 | - }); | ||
341 | -</script> | ||
342 | - | ||
343 | -<template> | ||
344 | - <section> | ||
345 | - <BasicModal @register="registerModal" v-bind="getModalBindProps"> | ||
346 | - <section class="bg-gray-100"> | ||
347 | - <Tabs v-model:active-key="activeKey" type="card" @change="handleCheckoutPanel"> | ||
348 | - <Tabs.TabPane :key="Active.PENDING"> | ||
349 | - <template #tab> | ||
350 | - <div class="flex items-center justify-center"> | ||
351 | - <span>待选设备</span> | ||
352 | - <Badge show-zero :count="pendingTotal" /> | ||
353 | - </div> | ||
354 | - </template> | ||
355 | - <BasicTable @register="regsterPendingTable"> | ||
356 | - <template #toolbar> | ||
357 | - <section class="flex w-full justify-end items-center"> | ||
358 | - <!-- <Button type="primary">全选</Button> --> | ||
359 | - <div class="text-blue-400"> | ||
360 | - <span class="mr-2">选择设备:</span> | ||
361 | - <span>{{ pendingConfirmQueue.length }}</span> | ||
362 | - </div> | ||
363 | - </section> | ||
364 | - </template> | ||
365 | - </BasicTable> | ||
366 | - <section class="flex justify-end px-4 pb-4"> | ||
367 | - <Button | ||
368 | - type="primary" | ||
369 | - @click="handleSelected" | ||
370 | - :disabled="!pendingConfirmQueue.length" | ||
371 | - > | ||
372 | - <span>确定已选</span> | ||
373 | - </Button> | ||
374 | - </section> | ||
375 | - </Tabs.TabPane> | ||
376 | - <Tabs.TabPane :key="Active.SELECTED"> | ||
377 | - <template #tab> | ||
378 | - <div class="flex items-center justify-center"> | ||
379 | - <span>已选设备</span> | ||
380 | - <Badge show-zero :count="selectedTotal" /> | ||
381 | - </div> | ||
382 | - </template> | ||
383 | - <BasicTable @register="registerSelectedTable"> | ||
384 | - <template #toolbar> | ||
385 | - <section class="flex w-full justify-end items-center"> | ||
386 | - <!-- <Button type="primary">全选</Button> --> | ||
387 | - <div class="text-blue-400"> | ||
388 | - <span class="mr-2">选择设备:</span> | ||
389 | - <span>{{ selectedConfirmQueue.length }}</span> | ||
390 | - </div> | ||
391 | - </section> | ||
392 | - </template> | ||
393 | - </BasicTable> | ||
394 | - <section class="flex justify-end px-4 pb-4"> | ||
395 | - <Button | ||
396 | - type="primary" | ||
397 | - :disabled="!selectedConfirmQueue.length" | ||
398 | - @click="handleRemoveSelected" | ||
399 | - > | ||
400 | - <span>移除已选</span> | ||
401 | - </Button> | ||
402 | - </section> | ||
403 | - </Tabs.TabPane> | ||
404 | - </Tabs> | ||
405 | - </section> | ||
406 | - </BasicModal> | ||
407 | - <Button @click="handleOpenModal" v-bind="getBindButtonProps"> | ||
408 | - <span v-if="!selectedRowKeys.length">选择设备</span> | ||
409 | - <div v-if="selectedRowKeys.length"> | ||
410 | - <Tag | ||
411 | - class="!px-2 !py-1 !bg-gray-50 !border-gray-100" | ||
412 | - v-for="item in getShowTagOptions" | ||
413 | - :key="item.value" | ||
414 | - > | ||
415 | - <span> | ||
416 | - {{ item.alias || item.name }} | ||
417 | - </span> | ||
418 | - </Tag> | ||
419 | - <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength"> | ||
420 | - <span> +{{ getSurplusOptionsLength }}... </span> | ||
421 | - </Tag> | ||
422 | - </div> | ||
423 | - </Button> | ||
424 | - </section> | ||
425 | -</template> | ||
426 | - | ||
427 | -<style lang="less"> | ||
428 | - @prefix-cls: ~'@{namespace}-transfer-table-modal'; | ||
429 | - | ||
430 | - .@{prefix-cls} { | ||
431 | - .vben-basic-table { | ||
432 | - padding-top: 0; | ||
433 | - } | ||
434 | - | ||
435 | - .vben-basic-form > .ant-row { | ||
436 | - width: 100%; | ||
437 | - } | ||
438 | - | ||
439 | - .ant-tabs-top-bar { | ||
440 | - background-color: #fff; | ||
441 | - } | ||
442 | - } | ||
443 | -</style> |
@@ -25,19 +25,18 @@ export function usePagination(refProps: ComputedRef<BasicTableProps>) { | @@ -25,19 +25,18 @@ export function usePagination(refProps: ComputedRef<BasicTableProps>) { | ||
25 | const { t } = useI18n(); | 25 | const { t } = useI18n(); |
26 | 26 | ||
27 | const configRef = ref<PaginationProps>({ | 27 | const configRef = ref<PaginationProps>({ |
28 | - hideOnSinglePage:true | 28 | + hideOnSinglePage: true, |
29 | }); | 29 | }); |
30 | const show = ref(true); | 30 | const show = ref(true); |
31 | 31 | ||
32 | watchEffect(() => { | 32 | watchEffect(() => { |
33 | const { pagination } = unref(refProps); | 33 | const { pagination } = unref(refProps); |
34 | - | 34 | + |
35 | if (!isBoolean(pagination) && pagination) { | 35 | if (!isBoolean(pagination) && pagination) { |
36 | configRef.value = { | 36 | configRef.value = { |
37 | ...unref(configRef), | 37 | ...unref(configRef), |
38 | ...(pagination ?? {}), | 38 | ...(pagination ?? {}), |
39 | - }; | ||
40 | - | 39 | + }; |
41 | } | 40 | } |
42 | }); | 41 | }); |
43 | 42 |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { Button, Tabs, Tag } from 'ant-design-vue'; | 2 | + import { Button, Tabs, Select } from 'ant-design-vue'; |
3 | import { remove, uniqBy, cloneDeep } from 'lodash'; | 3 | import { remove, uniqBy, cloneDeep } from 'lodash'; |
4 | - import { computed, nextTick, onMounted, ref, unref, toRaw } from 'vue'; | 4 | + import { nextTick, onMounted, ref, unref, toRaw, watch } from 'vue'; |
5 | import { | 5 | import { |
6 | deviceTableColumn, | 6 | deviceTableColumn, |
7 | deviceTableFormSchema, | 7 | deviceTableFormSchema, |
@@ -21,8 +21,7 @@ | @@ -21,8 +21,7 @@ | ||
21 | 21 | ||
22 | const props = withDefaults( | 22 | const props = withDefaults( |
23 | defineProps<{ | 23 | defineProps<{ |
24 | - getPendingTableParams: (params: Recordable) => any; | ||
25 | - getSelectedTableParams: (params: Recordable) => any; | 24 | + params?: Recordable; |
26 | value?: (Recordable & DeviceModel)[]; | 25 | value?: (Recordable & DeviceModel)[]; |
27 | maxTagLength?: number; | 26 | maxTagLength?: number; |
28 | openModalValidate?: () => boolean; | 27 | openModalValidate?: () => boolean; |
@@ -34,6 +33,7 @@ | @@ -34,6 +33,7 @@ | ||
34 | value: () => [], | 33 | value: () => [], |
35 | maxTagLength: 2, | 34 | maxTagLength: 2, |
36 | primaryKey: 'tbDeviceId', | 35 | primaryKey: 'tbDeviceId', |
36 | + params: () => ({}), | ||
37 | } | 37 | } |
38 | ); | 38 | ); |
39 | 39 | ||
@@ -56,23 +56,6 @@ | @@ -56,23 +56,6 @@ | ||
56 | 56 | ||
57 | const selectedConfirmQueue = ref<DeviceModel[]>([]); | 57 | const selectedConfirmQueue = ref<DeviceModel[]>([]); |
58 | 58 | ||
59 | - const getShowTagOptions = computed(() => { | ||
60 | - const { maxTagLength } = props; | ||
61 | - return unref(selectedTotalList).slice(0, maxTagLength); | ||
62 | - }); | ||
63 | - | ||
64 | - const getSurplusOptionsLength = computed(() => { | ||
65 | - const { maxTagLength } = props; | ||
66 | - const surplusValue = unref(selectedTotalList).length - maxTagLength; | ||
67 | - return surplusValue < 0 ? 0 : surplusValue; | ||
68 | - }); | ||
69 | - | ||
70 | - // const pendingListCount = computed(() => { | ||
71 | - // const { value } = props; | ||
72 | - // const selectedList = unref(pendingTotalList).filter((item) => value.includes(item.id)); | ||
73 | - // return unref(pendingTotalList).length - selectedList.length; | ||
74 | - // }); | ||
75 | - | ||
76 | const [registerModal, { openModal }] = useModal(); | 59 | const [registerModal, { openModal }] = useModal(); |
77 | 60 | ||
78 | const [regsterPendingTable, pendingTableActionType] = useTable({ | 61 | const [regsterPendingTable, pendingTableActionType] = useTable({ |
@@ -82,9 +65,8 @@ | @@ -82,9 +65,8 @@ | ||
82 | immediate: false, | 65 | immediate: false, |
83 | clickToRowSelect: false, | 66 | clickToRowSelect: false, |
84 | beforeFetch: (params) => { | 67 | beforeFetch: (params) => { |
85 | - const { getPendingTableParams } = props; | ||
86 | - const data = getPendingTableParams?.(params) || {}; | ||
87 | - Object.assign(params, { ...data, selected: false }); | 68 | + const { params: otherParams } = props; |
69 | + Object.assign(params, { ...otherParams, selected: false }); | ||
88 | return params; | 70 | return params; |
89 | }, | 71 | }, |
90 | afterFetch: (list: DeviceModel[]) => { | 72 | afterFetch: (list: DeviceModel[]) => { |
@@ -150,9 +132,8 @@ | @@ -150,9 +132,8 @@ | ||
150 | dataSource: selectedTotalList, | 132 | dataSource: selectedTotalList, |
151 | clickToRowSelect: false, | 133 | clickToRowSelect: false, |
152 | beforeFetch: (params) => { | 134 | beforeFetch: (params) => { |
153 | - const { getSelectedTableParams } = props; | ||
154 | - const data = getSelectedTableParams?.(params) || {}; | ||
155 | - Object.assign(params, { ...data, selected: false }); | 135 | + const { params: otherParams } = props; |
136 | + Object.assign(params, { ...otherParams, selected: false }); | ||
156 | return params; | 137 | return params; |
157 | }, | 138 | }, |
158 | rowSelection: { | 139 | rowSelection: { |
@@ -219,18 +200,31 @@ | @@ -219,18 +200,31 @@ | ||
219 | 200 | ||
220 | if (openModalValidate && isFunction(openModalValidate) && !openModalValidate()) return; | 201 | if (openModalValidate && isFunction(openModalValidate) && !openModalValidate()) return; |
221 | 202 | ||
203 | + activeKey.value = Active.PENDING; | ||
222 | openModal(true); | 204 | openModal(true); |
223 | await nextTick(); | 205 | await nextTick(); |
224 | pendingTableActionType.reload(); | 206 | pendingTableActionType.reload(); |
225 | }; | 207 | }; |
226 | 208 | ||
209 | + watch( | ||
210 | + () => props.params, | ||
211 | + () => { | ||
212 | + selectedTotalList.value = []; | ||
213 | + selectedConfirmQueue.value = []; | ||
214 | + pendingConfirmQueue.value = []; | ||
215 | + try { | ||
216 | + pendingTableActionType.clearSelectedRowKeys(); | ||
217 | + selectedTableActionType.clearSelectedRowKeys(); | ||
218 | + } catch (error) {} | ||
219 | + } | ||
220 | + ); | ||
221 | + | ||
227 | onMounted(async () => { | 222 | onMounted(async () => { |
228 | - const { getSelectedTableParams } = props; | ||
229 | - const data = getSelectedTableParams?.({}) || {}; | ||
230 | - if (!data?.convertConfigId || !data?.deviceProfileIds) { | 223 | + const { params } = props; |
224 | + if (!params?.convertConfigId || !params?.deviceProfileIds) { | ||
231 | return; | 225 | return; |
232 | } | 226 | } |
233 | - const { items } = await devicePage({ page: 1, pageSize: 10, ...data, selected: true }); | 227 | + const { items } = await devicePage({ page: 1, pageSize: 10, ...params, selected: true }); |
234 | selectedTotalList.value = items; | 228 | selectedTotalList.value = items; |
235 | }); | 229 | }); |
236 | </script> | 230 | </script> |
@@ -239,7 +233,7 @@ | @@ -239,7 +233,7 @@ | ||
239 | <section> | 233 | <section> |
240 | <BasicModal | 234 | <BasicModal |
241 | @register="registerModal" | 235 | @register="registerModal" |
242 | - title="穿梭表格" | 236 | + title="设备选择" |
243 | width="60%" | 237 | width="60%" |
244 | :wrapClassName="prefixCls" | 238 | :wrapClassName="prefixCls" |
245 | :showOkBtn="false" | 239 | :showOkBtn="false" |
@@ -251,13 +245,11 @@ | @@ -251,13 +245,11 @@ | ||
251 | <template #tab> | 245 | <template #tab> |
252 | <div class="flex items-center justify-center"> | 246 | <div class="flex items-center justify-center"> |
253 | <span>待选设备</span> | 247 | <span>待选设备</span> |
254 | - <!-- <Badge show-zero :count="pendingListCount" /> --> | ||
255 | </div> | 248 | </div> |
256 | </template> | 249 | </template> |
257 | <BasicTable @register="regsterPendingTable"> | 250 | <BasicTable @register="regsterPendingTable"> |
258 | <template #toolbar> | 251 | <template #toolbar> |
259 | <section class="flex w-full justify-end items-center"> | 252 | <section class="flex w-full justify-end items-center"> |
260 | - <!-- <Button type="primary">全选</Button> --> | ||
261 | <div class="text-blue-400"> | 253 | <div class="text-blue-400"> |
262 | <span class="mr-2">选择设备:</span> | 254 | <span class="mr-2">选择设备:</span> |
263 | <span>{{ pendingConfirmQueue.length }}</span> | 255 | <span>{{ pendingConfirmQueue.length }}</span> |
@@ -279,7 +271,6 @@ | @@ -279,7 +271,6 @@ | ||
279 | <template #tab> | 271 | <template #tab> |
280 | <div class="flex items-center justify-center"> | 272 | <div class="flex items-center justify-center"> |
281 | <span>已选设备</span> | 273 | <span>已选设备</span> |
282 | - <!-- <Badge show-zero :count="selectedTotalList.length" /> --> | ||
283 | </div> | 274 | </div> |
284 | </template> | 275 | </template> |
285 | <BasicTable @register="registerSelectedTable"> | 276 | <BasicTable @register="registerSelectedTable"> |
@@ -305,23 +296,22 @@ | @@ -305,23 +296,22 @@ | ||
305 | </Tabs> | 296 | </Tabs> |
306 | </section> | 297 | </section> |
307 | </BasicModal> | 298 | </BasicModal> |
308 | - <Button @click="handleOpenModal" type="link" :disabled="disabled"> | ||
309 | - <span v-if="!selectedTotalList.length">选择设备</span> | ||
310 | - <div v-if="selectedTotalList.length"> | ||
311 | - <Tag | ||
312 | - class="!px-2 !py-1 !bg-gray-50 !border-gray-100" | ||
313 | - v-for="item in getShowTagOptions" | ||
314 | - :key="item[primaryKey]" | ||
315 | - > | ||
316 | - <span> | ||
317 | - {{ item.alias || item.name }} | ||
318 | - </span> | ||
319 | - </Tag> | ||
320 | - <Tag class="!px-2 !py-1 !bg-gray-50 !border-gray-100" v-if="getSurplusOptionsLength"> | ||
321 | - <span> +{{ getSurplusOptionsLength }}... </span> | ||
322 | - </Tag> | ||
323 | - </div> | ||
324 | - </Button> | 299 | + <Select |
300 | + placeholder="请选择设备" | ||
301 | + :disabled="disabled" | ||
302 | + :value="selectedTotalList.map((item) => item[primaryKey])" | ||
303 | + mode="multiple" | ||
304 | + :maxTagCount="3" | ||
305 | + :open="false" | ||
306 | + @dropdownVisibleChange="handleOpenModal" | ||
307 | + :options=" | ||
308 | + selectedTotalList.map((item) => ({ | ||
309 | + ...item, | ||
310 | + label: item.alias || item.name, | ||
311 | + value: item[primaryKey], | ||
312 | + })) | ||
313 | + " | ||
314 | + /> | ||
325 | </section> | 315 | </section> |
326 | </template> | 316 | </template> |
327 | 317 |
@@ -73,6 +73,10 @@ export const modeForm = (disabled: boolean): FormSchema[] => { | @@ -73,6 +73,10 @@ export const modeForm = (disabled: boolean): FormSchema[] => { | ||
73 | labelField: 'name', | 73 | labelField: 'name', |
74 | valueField: 'tbProfileId', | 74 | valueField: 'tbProfileId', |
75 | disabled, | 75 | disabled, |
76 | + selectProps: { | ||
77 | + disabled, | ||
78 | + placeholder: '请选择产品', | ||
79 | + }, | ||
76 | transferProps: { | 80 | transferProps: { |
77 | listStyle: { height: '400px' }, | 81 | listStyle: { height: '400px' }, |
78 | showSearch: true, | 82 | showSearch: true, |
@@ -98,26 +102,14 @@ export const modeForm = (disabled: boolean): FormSchema[] => { | @@ -98,26 +102,14 @@ export const modeForm = (disabled: boolean): FormSchema[] => { | ||
98 | valueField: 'value', | 102 | valueField: 'value', |
99 | changeEvent: 'update:value', | 103 | changeEvent: 'update:value', |
100 | rules: [{ required: true, message: '数据源设备为必选项', type: 'array' }], | 104 | rules: [{ required: true, message: '数据源设备为必选项', type: 'array' }], |
101 | - componentProps: ({ formActionType }) => { | ||
102 | - const { getFieldsValue } = formActionType; | 105 | + componentProps: ({ formModel }) => { |
106 | + const convertConfigId = formModel[BasicInfoFormField.CONVERT_CONFIG_ID]; | ||
107 | + const deviceProfileIds = formModel[BasicInfoFormField.DATA_SOURCE_PRODUCT]; | ||
103 | return { | 108 | return { |
104 | disabled, | 109 | disabled, |
105 | - getPendingTableParams: () => { | ||
106 | - const values = getFieldsValue(); | ||
107 | - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID); | ||
108 | - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT); | ||
109 | - return { convertConfigId, deviceProfileIds }; | ||
110 | - }, | ||
111 | - getSelectedTableParams: () => { | ||
112 | - const values = getFieldsValue(); | ||
113 | - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID); | ||
114 | - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT); | ||
115 | - return { convertConfigId, deviceProfileIds }; | ||
116 | - }, | 110 | + params: { convertConfigId, deviceProfileIds }, |
117 | transformValue: handleGroupDevice, | 111 | transformValue: handleGroupDevice, |
118 | openModalValidate: () => { | 112 | openModalValidate: () => { |
119 | - const values = getFieldsValue(); | ||
120 | - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT); | ||
121 | if (!deviceProfileIds || !deviceProfileIds?.length) { | 113 | if (!deviceProfileIds || !deviceProfileIds?.length) { |
122 | createMessage.warning('请选择数据源设备'); | 114 | createMessage.warning('请选择数据源设备'); |
123 | } | 115 | } |