el-plus-crud 0.0.49 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +19 -17
  2. package/dist/el-plus-crud.mjs +3605 -3453
  3. package/example/App.vue +1 -1
  4. package/lib/components/el-plus-form/ElPlusForm.vue +775 -771
  5. package/lib/components/el-plus-form/ElPlusFormDialog.vue +1 -1
  6. package/lib/components/el-plus-form/components/ElPlusFormArea.vue +62 -62
  7. package/lib/components/el-plus-form/components/ElPlusFormBtn.vue +103 -103
  8. package/lib/components/el-plus-form/components/ElPlusFormBtns.vue +140 -134
  9. package/lib/components/el-plus-form/components/ElPlusFormCascader.vue +64 -64
  10. package/lib/components/el-plus-form/components/ElPlusFormCascaderPanel.vue +54 -54
  11. package/lib/components/el-plus-form/components/ElPlusFormCheckbox.vue +45 -45
  12. package/lib/components/el-plus-form/components/ElPlusFormCheckboxButton.vue +45 -45
  13. package/lib/components/el-plus-form/components/ElPlusFormColor.vue +39 -39
  14. package/lib/components/el-plus-form/components/ElPlusFormDate.vue +40 -40
  15. package/lib/components/el-plus-form/components/ElPlusFormDaterange.vue +47 -47
  16. package/lib/components/el-plus-form/components/ElPlusFormDatetime.vue +41 -41
  17. package/lib/components/el-plus-form/components/ElPlusFormDatetimerange.vue +47 -47
  18. package/lib/components/el-plus-form/components/ElPlusFormInput.vue +62 -62
  19. package/lib/components/el-plus-form/components/ElPlusFormLink.vue +282 -282
  20. package/lib/components/el-plus-form/components/ElPlusFormLkuser.vue +490 -490
  21. package/lib/components/el-plus-form/components/ElPlusFormNbinput.vue +54 -54
  22. package/lib/components/el-plus-form/components/ElPlusFormNumber.vue +147 -147
  23. package/lib/components/el-plus-form/components/ElPlusFormPassword.vue +44 -44
  24. package/lib/components/el-plus-form/components/ElPlusFormQuickInput.vue +96 -96
  25. package/lib/components/el-plus-form/components/ElPlusFormRadio.vue +68 -68
  26. package/lib/components/el-plus-form/components/ElPlusFormRate.vue +54 -54
  27. package/lib/components/el-plus-form/components/ElPlusFormSelect.vue +162 -162
  28. package/lib/components/el-plus-form/components/ElPlusFormSlider.vue +39 -39
  29. package/lib/components/el-plus-form/components/ElPlusFormSwitch.vue +39 -39
  30. package/lib/components/el-plus-form/components/ElPlusFormTextarea.vue +50 -50
  31. package/lib/components/el-plus-form/components/ElPlusFormTransfer.vue +45 -45
  32. package/lib/components/el-plus-form/components/ElPlusFormTree.vue +77 -77
  33. package/lib/components/el-plus-form/components/ElPlusFormTreeSelect.vue +60 -60
  34. package/lib/components/el-plus-form/components/ElPlusFormUpbtn.vue +144 -0
  35. package/lib/components/el-plus-form/components/ElPlusFormUpload.vue +369 -369
  36. package/lib/components/el-plus-form/mixins/index.ts +2 -2
  37. package/lib/components/el-plus-table/components/header.vue +283 -260
  38. package/lib/components-list.ts +2 -0
  39. package/package.json +1 -1
  40. package/types/formList.d.ts +447 -446
@@ -1,490 +1,490 @@
1
- <template>
2
- <div class="el-plus-form-link-user">
3
- <el-select ref="selectRef" style="width: 100%" :class="desc.class" :style="desc.style" v-bind="topAttrs" :teleported="false" :disabled="disabled" :loading="loading" :modelValue="values" @visible-change="handelVisibleChange" @clear="handelClear">
4
- <el-option v-for="option in options" :key="option.value" v-bind="option" />
5
- </el-select>
6
- <!-- 弹框 -->
7
- <el-dialog :width="desc.dialogWidth || '900px'" :title="desc.placeholder || '选择' + desc.label" draggable :closeOnClickModal="false" showCancel v-model="isShowDialog" append-to-body destroy-on-close>
8
- <div style="width: 100%" class="form-link-user-dialog">
9
- <div class="panel-left">
10
- <!-- 搜索 -->
11
- <el-select style="width: 300px" placeholder="输入用户名进行搜索" v-bind="selectAttrs" @change="handelSelectChange">
12
- <el-option v-for="option in selectOptions" :key="option.value" v-bind="option" />
13
- </el-select>
14
- <el-divider></el-divider>
15
- <div class="dept-breadcrumb">
16
- <el-breadcrumb separator="/">
17
- <el-breadcrumb-item @click="goIndex(-1)">组织架构</el-breadcrumb-item>
18
- <el-breadcrumb-item v-for="(item, i) in deptTreeItems" :key="i" @click="goIndex(i)">
19
- {{ item.label }}
20
- </el-breadcrumb-item>
21
- </el-breadcrumb>
22
- </div>
23
- <!-- 组织机构列表 -->
24
- <el-table ref="multipleTableRef" :data="tableData" style="width: 100%; height: 500px" max-height="500px" @select="handelTableSelect" @select-all="handelTableSelectAll">
25
- <el-table-column type="selection" width="55" :selectable="handelTableSelectable" />
26
- <el-table-column label="组织/部门/人员" prop="label">
27
- <template #default="{ row }">
28
- <div style="display: flex; align-items: center">
29
- <el-icon style="margin-right: 5px">
30
- <Share v-if="row.type === 2" />
31
- <UserFilled v-else />
32
- </el-icon>
33
- {{ row.label }}
34
- </div>
35
- </template>
36
- </el-table-column>
37
- <el-table-column label="操作" width="80">
38
- <template #default="{ row, $index }">
39
- <el-button v-if="row.type === 2" :disabled="selectUser.some((item) => item.value === row.value)" type="primary" text plain @click="goInto(row, $index)">进入</el-button>
40
- </template>
41
- </el-table-column>
42
- </el-table>
43
- </div>
44
- <div class="panel-right">
45
- <div class="right-title">已选中项:</div>
46
- <el-scrollbar height="480px" class="tag-list">
47
- <el-tag style="margin-right: 10px; margin-bottom: 10px" v-for="tag in selectUser" :key="tag.value" closable @close="() => handelTagRemove(tag)">
48
- <el-icon style="margin-right: 5px">
49
- <Share v-if="tag.type === 2" />
50
- <UserFilled v-else />
51
- </el-icon>
52
- {{ tag.label }}
53
- </el-tag>
54
- </el-scrollbar>
55
- <div class="btn-panel">
56
- <el-button @click="cancel">取消</el-button>
57
- <el-button type="primary" @click="submit">确定</el-button>
58
- </div>
59
- </div>
60
- </div>
61
- </el-dialog>
62
- </div>
63
- </template>
64
- <script lang="ts">
65
- export default {
66
- name: 'ElPlusFormLkuser',
67
- inheritAttrs: false,
68
- typeName: 'lkuser',
69
- customOptions: {}
70
- }
71
- </script>
72
- <script lang="ts" setup>
73
- import { ref, reactive, nextTick, watch, onMounted, computed, inject, onBeforeMount, useAttrs } from 'vue'
74
- import { Share, UserFilled } from '@element-plus/icons-vue'
75
- import { cloneDeep } from 'lodash'
76
- import { getAttrs } from '../mixins'
77
-
78
- const globalData = inject('globalData') as any
79
- const defaultConf = inject('defaultConf') as ICRUDConfig
80
-
81
- interface ILinkItem {
82
- // 选中类型: 1,用户、 2:部门
83
- type: 1 | 2
84
- label: string
85
- value: string
86
- }
87
-
88
- const props = defineProps<{
89
- modelValue?: []
90
- field: string
91
- loading?: boolean
92
- desc: { [key: string]: any }
93
- formData: { [key: string]: any }
94
- disabled?: boolean
95
- }>()
96
-
97
- const onEvents = ref(getEvents(props))
98
-
99
- const emits = defineEmits(['update:modelValue', 'change', 'input', 'validateThis'])
100
-
101
- const currentValue = ref((props.modelValue || []) as any[])
102
- emits('update:modelValue', currentValue)
103
-
104
- // 顶部的select
105
- const selectRef = ref()
106
- const values = reactive([] as Array<string>)
107
- const options = reactive([] as Array<ILinkItem>)
108
- const topAttrs = reactive({
109
- multiple: true,
110
- size: props.desc.size,
111
- collapseTags: false,
112
- collapseTagsTooltip: false,
113
- clearable: true
114
- })
115
-
116
- const isShowDialog = ref(false)
117
-
118
- // 存储的值
119
- const selectUser = reactive([] as Array<ILinkItem>)
120
-
121
- // 搜索框
122
- const selectOptions = reactive([] as any[])
123
- const selectAttrs = ref({})
124
-
125
- /**
126
- * 处理自定义请求
127
- * @param param
128
- */
129
- async function remoteMethod(query: string) {
130
- selectOptions.splice(0, selectOptions.length, ...(await selectRemote(query)))
131
- }
132
-
133
- // 组织架构数据
134
- const deptTreeIndex = ref([] as number[])
135
- const deptTreeItems = ref([] as any[])
136
- // 用户数据列表
137
- const tableUserData = ref([] as any[])
138
-
139
- // 机构列表数据
140
- const multipleTableRef = ref()
141
- const tableData = computed(() => {
142
- const tempList = [] as ILinkItem[]
143
- // 遍历组织架构数据
144
- let tempData = cloneDeep(globalData[defaultConf.form?.linkUser?.deptListKey || ''])
145
- if (deptTreeIndex.value && deptTreeIndex.value.length > 0) {
146
- deptTreeIndex.value.map((item) => {
147
- tempData = tempData[item].children || []
148
- })
149
- }
150
- tempData.map((item: any) => tempList.push({ type: 2, label: item.name, value: item.id }))
151
- // 遍历用户数据
152
- tableUserData.value.map((item) => tempList.push({ type: 1, label: item.nickname, value: item.userId }))
153
-
154
- // 这里默认选中
155
- nextTick(() => {
156
- setTimeout(() => {
157
- tempList.map((item) => {
158
- multipleTableRef.value?.toggleRowSelection(
159
- item,
160
- selectUser.some((i) => i.value === item.value)
161
- )
162
- })
163
- }, 10)
164
- })
165
- return tempList
166
- })
167
-
168
- /**
169
- * 获取事件
170
- * @returns
171
- */
172
- function getEvents(props: any) {
173
- const tempOn = {} as any
174
- if (props.desc?.on) {
175
- Object.keys(props.desc.on).map((key: string) => {
176
- tempOn[key] = (val: any) => {
177
- props.desc.on[key](props.formData, props.rowIndex, val)
178
- }
179
- })
180
- }
181
- return tempOn
182
- }
183
-
184
- /**
185
- * 处理点击事件
186
- * @param val
187
- */
188
- function handelVisibleChange(val: any) {
189
- if (val) {
190
- selectRef.value.blur()
191
- isShowDialog.value = true
192
- }
193
- }
194
-
195
- /**
196
- * 处理清空选项
197
- */
198
- function handelClear() {
199
- selectUser.splice(0, selectUser.length)
200
- // 清空列表选中项
201
- tableData.value.map((item) => {
202
- multipleTableRef.value?.toggleRowSelection(
203
- item,
204
- selectUser.some((i) => i.value === item.value)
205
- )
206
- })
207
- submit()
208
- }
209
-
210
- /**
211
- * 处理自定义请求
212
- * @param param
213
- */
214
-
215
- /**
216
- * 处理下拉框选中
217
- * @param val
218
- */
219
- function handelSelectChange(val: any) {
220
- addAndRemove({ ...selectOptions.find((item) => item.value === val), type: 1 })
221
- }
222
-
223
- /**
224
- * 远程查询用户列表
225
- * @param nickname
226
- */
227
- async function selectRemote(nickname: string) {
228
- if (nickname.length > 0) {
229
- return ((await defaultConf.form?.linkUser?.getUserList({ nickname, current: 1, size: 10, enabled: 1 })) as any).records?.map((item: any) => {
230
- return { value: item.userId, label: item.nickname }
231
- })
232
- }
233
- return []
234
- }
235
-
236
- /**
237
- * 进入下级组织架构
238
- * @param item
239
- */
240
- async function goInto(item: ILinkItem, index: number) {
241
- // 查询机构用户
242
- tableUserData.value = (await defaultConf.form?.linkUser?.getUserList({ deptId: item.value, size: 999 })).records as any[]
243
- deptTreeIndex.value.push(index)
244
- deptTreeItems.value.push(item)
245
- }
246
-
247
- /**
248
- * 返回上级组织架构
249
- * @param index
250
- */
251
- async function goIndex(index: number) {
252
- // 查询机构用户
253
- tableUserData.value = index >= 0 ? ((await defaultConf.form?.linkUser?.getUserList({ deptId: deptTreeItems.value[index].value, size: 999 })).records as any[]) : []
254
- deptTreeIndex.value.splice(index + 1)
255
- deptTreeItems.value.splice(index + 1)
256
- }
257
-
258
- /**
259
- * 处理当前行是否能够被选中
260
- * @param row
261
- */
262
- function handelTableSelectable(row: any) {
263
- if (props.desc.onlyUser) {
264
- return row.type === 1
265
- }
266
- return true
267
- }
268
-
269
- /**
270
- * 处理单个选中的情况
271
- * @param selection
272
- * @param row
273
- */
274
- function handelTableSelect(selection: ILinkItem[], item: ILinkItem) {
275
- addAndRemove(item, !selection.some((i) => i.value === item.value))
276
- }
277
-
278
- /**
279
- * 处理全选
280
- * @param selection
281
- * @param row
282
- */
283
- function handelTableSelectAll(selection: ILinkItem[]) {
284
- const isRemove = !(selection && selection.length > 0)
285
- tableData.value.map((item) => {
286
- if (!props.desc.onlyUser || (props.desc.onlyUser && item.type === 1)) {
287
- addAndRemove(item, isRemove)
288
- }
289
- })
290
- }
291
-
292
- /**
293
- * 处理删除标签
294
- * @param item
295
- */
296
- function handelTagRemove(item: ILinkItem) {
297
- if (tableData.value.some((i) => i.value === item.value)) {
298
- multipleTableRef.value?.toggleRowSelection(item, false)
299
- }
300
- addAndRemove(item, true)
301
- }
302
-
303
- /**
304
- * 添加或者移除
305
- * @param item
306
- */
307
- function addAndRemove(item: ILinkItem, isRemove: boolean = false) {
308
- // 校验是否已经有了
309
- const index = selectUser.findIndex((i) => i.value === item.value)
310
- if (isRemove) {
311
- if (index >= 0) {
312
- selectUser.splice(index, 1)
313
- }
314
- } else {
315
- if (index < 0) {
316
- selectUser.push(item)
317
- }
318
- }
319
- }
320
-
321
- /**
322
- * 取消按钮
323
- */
324
- function cancel() {
325
- isShowDialog.value = false
326
- }
327
-
328
- /**
329
- * 确认按钮
330
- */
331
- function submit() {
332
- options.splice(0, options.length, ...selectUser)
333
- const userIds = [] as string[]
334
- const deptIds = [] as string[]
335
- const userNames = [] as string[]
336
- const deptNames = [] as string[]
337
- values.splice(0, values.length)
338
-
339
- // 遍历数据
340
- selectUser.map((item) => {
341
- values.push(item.value)
342
- if (item.type === 1) {
343
- userIds.push(item.value)
344
- userNames.push(item.label)
345
- } else {
346
- deptIds.push(item.value)
347
- deptNames.push(item.label)
348
- }
349
- })
350
-
351
- isShowDialog.value = false
352
- currentValue.value = selectUser.length > 0 ? [userIds, deptIds, userNames, deptNames] : []
353
- // 触发外部change事件
354
- if (onEvents.value.change) {
355
- onEvents.value.change(props.formData, null, currentValue.value)
356
- }
357
- emits('validateThis')
358
- }
359
-
360
- /**
361
- * 初始化选中数据
362
- */
363
- function initSelectData() {
364
- const tempList = [] as Array<ILinkItem>
365
- if (props.modelValue) {
366
- let [userIds, deptIds, userNames, deptNames] = props.modelValue as any
367
- if (deptIds && deptNames && deptIds.length === deptNames.length) {
368
- deptIds.map((id: string, i: number) => {
369
- tempList.push({ type: 2, value: id, label: deptNames[i] })
370
- })
371
- }
372
- if (userIds && userNames && userIds.length === userNames.length) {
373
- userIds.map((id: string, i: number) => {
374
- tempList.push({ type: 1, value: id, label: userNames[i] })
375
- })
376
- }
377
- }
378
- return tempList
379
- }
380
-
381
- /**
382
- * 初始化选中Id
383
- */
384
- function initSelectIds() {
385
- const tempList = [] as Array<string>
386
- if (props.modelValue) {
387
- let [userIds, deptIds] = props.modelValue as any
388
- tempList.push(...(deptIds || []))
389
- tempList.push(...(userIds || []))
390
- }
391
- return tempList
392
- }
393
-
394
- /**
395
- * 初始化数据
396
- */
397
- function init() {
398
- selectUser.splice(0, selectUser.length, ...initSelectData())
399
- options.splice(0, options.length, ...initSelectData())
400
- values.splice(0, values.length, ...initSelectIds())
401
- }
402
-
403
- onBeforeMount(async () => {
404
- // // 如果没有配置,则抛出一个警告
405
- selectAttrs.value = await getAttrs(props, {
406
- remote: true,
407
- filterable: true,
408
- remoteShowSuffix: true,
409
- loadingText: '远程查询中...',
410
- remoteMethod: remoteMethod,
411
- ...useAttrs()
412
- })
413
- })
414
-
415
- watch(
416
- () => props.modelValue,
417
- () => init(),
418
- { deep: true }
419
- )
420
-
421
- onMounted(async () => {
422
- init()
423
- })
424
- </script>
425
- <style lang="scss" scoped>
426
- .el-plus-form-link-user {
427
- width: 100%;
428
-
429
- .items-panel {
430
- :deep(.el-input__inner) {
431
- cursor: pointer;
432
- }
433
- }
434
-
435
- :deep(.el-tag__close) {
436
- display: none !important;
437
- }
438
- }
439
- </style>
440
- <style lang="scss">
441
- .form-link-user-dialog {
442
- width: 100%;
443
- display: flex;
444
- box-sizing: border-box;
445
-
446
- .panel-left {
447
- width: 60%;
448
- display: flex;
449
- flex-direction: column;
450
-
451
- .dept-breadcrumb {
452
- width: 100%;
453
- padding: 0 10px;
454
- margin-bottom: 20px;
455
- cursor: pointer;
456
- }
457
- }
458
-
459
- .panel-right {
460
- width: 40%;
461
- margin-left: 20px;
462
- border-left: 1px var(--el-border-color) var(--el-border-style);
463
- padding: 20px;
464
- display: flex;
465
- overflow: hidden;
466
- flex-direction: column;
467
-
468
- .right-title {
469
- width: 100%;
470
- font-size: 14px;
471
- color: #999999;
472
- margin-bottom: 20px;
473
- }
474
-
475
- .tag-list {
476
- width: 100%;
477
- flex: 1;
478
- overflow-y: hidden;
479
- }
480
-
481
- .btn-panel {
482
- width: 100%;
483
- min-height: 50px;
484
- padding-top: 10px;
485
- display: flex;
486
- justify-content: center;
487
- }
488
- }
489
- }
490
- </style>
1
+ <template>
2
+ <div class="el-plus-form-link-user">
3
+ <el-select ref="selectRef" style="width: 100%" :class="desc.class" :style="desc.style" v-bind="topAttrs" :teleported="false" :disabled="disabled" :loading="loading" :modelValue="values" @visible-change="handelVisibleChange" @clear="handelClear">
4
+ <el-option v-for="option in options" :key="option.value" v-bind="option" />
5
+ </el-select>
6
+ <!-- 弹框 -->
7
+ <el-dialog :width="desc.dialogWidth || '900px'" :title="desc.placeholder || '选择' + desc.label" draggable :closeOnClickModal="false" showCancel v-model="isShowDialog" append-to-body destroy-on-close>
8
+ <div style="width: 100%" class="form-link-user-dialog">
9
+ <div class="panel-left">
10
+ <!-- 搜索 -->
11
+ <el-select style="width: 300px" placeholder="输入用户名进行搜索" v-bind="selectAttrs" @change="handelSelectChange">
12
+ <el-option v-for="option in selectOptions" :key="option.value" v-bind="option" />
13
+ </el-select>
14
+ <el-divider></el-divider>
15
+ <div class="dept-breadcrumb">
16
+ <el-breadcrumb separator="/">
17
+ <el-breadcrumb-item @click="goIndex(-1)">组织架构</el-breadcrumb-item>
18
+ <el-breadcrumb-item v-for="(item, i) in deptTreeItems" :key="i" @click="goIndex(i)">
19
+ {{ item.label }}
20
+ </el-breadcrumb-item>
21
+ </el-breadcrumb>
22
+ </div>
23
+ <!-- 组织机构列表 -->
24
+ <el-table ref="multipleTableRef" :data="tableData" style="width: 100%; height: 500px" max-height="500px" @select="handelTableSelect" @select-all="handelTableSelectAll">
25
+ <el-table-column type="selection" width="55" :selectable="handelTableSelectable" />
26
+ <el-table-column label="组织/部门/人员" prop="label">
27
+ <template #default="{ row }">
28
+ <div style="display: flex; align-items: center">
29
+ <el-icon style="margin-right: 5px">
30
+ <Share v-if="row.type === 2" />
31
+ <UserFilled v-else />
32
+ </el-icon>
33
+ {{ row.label }}
34
+ </div>
35
+ </template>
36
+ </el-table-column>
37
+ <el-table-column label="操作" width="80">
38
+ <template #default="{ row, $index }">
39
+ <el-button v-if="row.type === 2" :disabled="selectUser.some((item) => item.value === row.value)" type="primary" text plain @click="goInto(row, $index)">进入</el-button>
40
+ </template>
41
+ </el-table-column>
42
+ </el-table>
43
+ </div>
44
+ <div class="panel-right">
45
+ <div class="right-title">已选中项:</div>
46
+ <el-scrollbar height="480px" class="tag-list">
47
+ <el-tag style="margin-right: 10px; margin-bottom: 10px" v-for="tag in selectUser" :key="tag.value" closable @close="() => handelTagRemove(tag)">
48
+ <el-icon style="margin-right: 5px">
49
+ <Share v-if="tag.type === 2" />
50
+ <UserFilled v-else />
51
+ </el-icon>
52
+ {{ tag.label }}
53
+ </el-tag>
54
+ </el-scrollbar>
55
+ <div class="btn-panel">
56
+ <el-button @click="cancel">取消</el-button>
57
+ <el-button type="primary" @click="submit">确定</el-button>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </el-dialog>
62
+ </div>
63
+ </template>
64
+ <script lang="ts">
65
+ export default {
66
+ name: 'ElPlusFormLkuser',
67
+ inheritAttrs: false,
68
+ typeName: 'lkuser',
69
+ customOptions: {}
70
+ }
71
+ </script>
72
+ <script lang="ts" setup>
73
+ import { ref, reactive, nextTick, watch, onMounted, computed, inject, onBeforeMount, useAttrs } from 'vue'
74
+ import { Share, UserFilled } from '@element-plus/icons-vue'
75
+ import { cloneDeep } from 'lodash'
76
+ import { getAttrs } from '../mixins'
77
+
78
+ const globalData = inject('globalData') as any
79
+ const defaultConf = inject('defaultConf') as ICRUDConfig
80
+
81
+ interface ILinkItem {
82
+ // 选中类型: 1,用户、 2:部门
83
+ type: 1 | 2
84
+ label: string
85
+ value: string
86
+ }
87
+
88
+ const props = defineProps<{
89
+ modelValue?: []
90
+ field: string
91
+ loading?: boolean
92
+ desc: { [key: string]: any }
93
+ formData: { [key: string]: any }
94
+ disabled?: boolean
95
+ }>()
96
+
97
+ const onEvents = ref(getEvents(props))
98
+
99
+ const emits = defineEmits(['update:modelValue', 'change', 'input', 'validateThis'])
100
+
101
+ const currentValue = ref((props.modelValue || []) as any[])
102
+ emits('update:modelValue', currentValue)
103
+
104
+ // 顶部的select
105
+ const selectRef = ref()
106
+ const values = reactive([] as Array<string>)
107
+ const options = reactive([] as Array<ILinkItem>)
108
+ const topAttrs = reactive({
109
+ multiple: true,
110
+ size: props.desc.size,
111
+ collapseTags: false,
112
+ collapseTagsTooltip: false,
113
+ clearable: true
114
+ })
115
+
116
+ const isShowDialog = ref(false)
117
+
118
+ // 存储的值
119
+ const selectUser = reactive([] as Array<ILinkItem>)
120
+
121
+ // 搜索框
122
+ const selectOptions = reactive([] as any[])
123
+ const selectAttrs = ref({})
124
+
125
+ /**
126
+ * 处理自定义请求
127
+ * @param param
128
+ */
129
+ async function remoteMethod(query: string) {
130
+ selectOptions.splice(0, selectOptions.length, ...(await selectRemote(query)))
131
+ }
132
+
133
+ // 组织架构数据
134
+ const deptTreeIndex = ref([] as number[])
135
+ const deptTreeItems = ref([] as any[])
136
+ // 用户数据列表
137
+ const tableUserData = ref([] as any[])
138
+
139
+ // 机构列表数据
140
+ const multipleTableRef = ref()
141
+ const tableData = computed(() => {
142
+ const tempList = [] as ILinkItem[]
143
+ // 遍历组织架构数据
144
+ let tempData = cloneDeep(globalData[defaultConf.form?.linkUser?.deptListKey || ''])
145
+ if (deptTreeIndex.value && deptTreeIndex.value.length > 0) {
146
+ deptTreeIndex.value.map((item) => {
147
+ tempData = tempData[item].children || []
148
+ })
149
+ }
150
+ tempData.map((item: any) => tempList.push({ type: 2, label: item.name, value: item.id }))
151
+ // 遍历用户数据
152
+ tableUserData.value.map((item) => tempList.push({ type: 1, label: item.nickname, value: item.userId }))
153
+
154
+ // 这里默认选中
155
+ nextTick(() => {
156
+ setTimeout(() => {
157
+ tempList.map((item) => {
158
+ multipleTableRef.value?.toggleRowSelection(
159
+ item,
160
+ selectUser.some((i) => i.value === item.value)
161
+ )
162
+ })
163
+ }, 10)
164
+ })
165
+ return tempList
166
+ })
167
+
168
+ /**
169
+ * 获取事件
170
+ * @returns
171
+ */
172
+ function getEvents(props: any) {
173
+ const tempOn = {} as any
174
+ if (props.desc?.on) {
175
+ Object.keys(props.desc.on).map((key: string) => {
176
+ tempOn[key] = (val: any) => {
177
+ props.desc.on[key](props.formData, props.rowIndex, val)
178
+ }
179
+ })
180
+ }
181
+ return tempOn
182
+ }
183
+
184
+ /**
185
+ * 处理点击事件
186
+ * @param val
187
+ */
188
+ function handelVisibleChange(val: any) {
189
+ if (val) {
190
+ selectRef.value.blur()
191
+ isShowDialog.value = true
192
+ }
193
+ }
194
+
195
+ /**
196
+ * 处理清空选项
197
+ */
198
+ function handelClear() {
199
+ selectUser.splice(0, selectUser.length)
200
+ // 清空列表选中项
201
+ tableData.value.map((item) => {
202
+ multipleTableRef.value?.toggleRowSelection(
203
+ item,
204
+ selectUser.some((i) => i.value === item.value)
205
+ )
206
+ })
207
+ submit()
208
+ }
209
+
210
+ /**
211
+ * 处理自定义请求
212
+ * @param param
213
+ */
214
+
215
+ /**
216
+ * 处理下拉框选中
217
+ * @param val
218
+ */
219
+ function handelSelectChange(val: any) {
220
+ addAndRemove({ ...selectOptions.find((item) => item.value === val), type: 1 })
221
+ }
222
+
223
+ /**
224
+ * 远程查询用户列表
225
+ * @param nickname
226
+ */
227
+ async function selectRemote(nickname: string) {
228
+ if (nickname.length > 0) {
229
+ return ((await defaultConf.form?.linkUser?.getUserList({ nickname, current: 1, size: 10, enabled: 1 })) as any).records?.map((item: any) => {
230
+ return { value: item.userId, label: item.nickname }
231
+ })
232
+ }
233
+ return []
234
+ }
235
+
236
+ /**
237
+ * 进入下级组织架构
238
+ * @param item
239
+ */
240
+ async function goInto(item: ILinkItem, index: number) {
241
+ // 查询机构用户
242
+ tableUserData.value = (await defaultConf.form?.linkUser?.getUserList({ deptId: item.value, size: 999 })).records as any[]
243
+ deptTreeIndex.value.push(index)
244
+ deptTreeItems.value.push(item)
245
+ }
246
+
247
+ /**
248
+ * 返回上级组织架构
249
+ * @param index
250
+ */
251
+ async function goIndex(index: number) {
252
+ // 查询机构用户
253
+ tableUserData.value = index >= 0 ? ((await defaultConf.form?.linkUser?.getUserList({ deptId: deptTreeItems.value[index].value, size: 999 })).records as any[]) : []
254
+ deptTreeIndex.value.splice(index + 1)
255
+ deptTreeItems.value.splice(index + 1)
256
+ }
257
+
258
+ /**
259
+ * 处理当前行是否能够被选中
260
+ * @param row
261
+ */
262
+ function handelTableSelectable(row: any) {
263
+ if (props.desc.onlyUser) {
264
+ return row.type === 1
265
+ }
266
+ return true
267
+ }
268
+
269
+ /**
270
+ * 处理单个选中的情况
271
+ * @param selection
272
+ * @param row
273
+ */
274
+ function handelTableSelect(selection: ILinkItem[], item: ILinkItem) {
275
+ addAndRemove(item, !selection.some((i) => i.value === item.value))
276
+ }
277
+
278
+ /**
279
+ * 处理全选
280
+ * @param selection
281
+ * @param row
282
+ */
283
+ function handelTableSelectAll(selection: ILinkItem[]) {
284
+ const isRemove = !(selection && selection.length > 0)
285
+ tableData.value.map((item) => {
286
+ if (!props.desc.onlyUser || (props.desc.onlyUser && item.type === 1)) {
287
+ addAndRemove(item, isRemove)
288
+ }
289
+ })
290
+ }
291
+
292
+ /**
293
+ * 处理删除标签
294
+ * @param item
295
+ */
296
+ function handelTagRemove(item: ILinkItem) {
297
+ if (tableData.value.some((i) => i.value === item.value)) {
298
+ multipleTableRef.value?.toggleRowSelection(item, false)
299
+ }
300
+ addAndRemove(item, true)
301
+ }
302
+
303
+ /**
304
+ * 添加或者移除
305
+ * @param item
306
+ */
307
+ function addAndRemove(item: ILinkItem, isRemove: boolean = false) {
308
+ // 校验是否已经有了
309
+ const index = selectUser.findIndex((i) => i.value === item.value)
310
+ if (isRemove) {
311
+ if (index >= 0) {
312
+ selectUser.splice(index, 1)
313
+ }
314
+ } else {
315
+ if (index < 0) {
316
+ selectUser.push(item)
317
+ }
318
+ }
319
+ }
320
+
321
+ /**
322
+ * 取消按钮
323
+ */
324
+ function cancel() {
325
+ isShowDialog.value = false
326
+ }
327
+
328
+ /**
329
+ * 确认按钮
330
+ */
331
+ function submit() {
332
+ options.splice(0, options.length, ...selectUser)
333
+ const userIds = [] as string[]
334
+ const deptIds = [] as string[]
335
+ const userNames = [] as string[]
336
+ const deptNames = [] as string[]
337
+ values.splice(0, values.length)
338
+
339
+ // 遍历数据
340
+ selectUser.map((item) => {
341
+ values.push(item.value)
342
+ if (item.type === 1) {
343
+ userIds.push(item.value)
344
+ userNames.push(item.label)
345
+ } else {
346
+ deptIds.push(item.value)
347
+ deptNames.push(item.label)
348
+ }
349
+ })
350
+
351
+ isShowDialog.value = false
352
+ currentValue.value = selectUser.length > 0 ? [userIds, deptIds, userNames, deptNames] : []
353
+ // 触发外部change事件
354
+ if (onEvents.value.change) {
355
+ onEvents.value.change(props.formData, null, currentValue.value)
356
+ }
357
+ emits('validateThis')
358
+ }
359
+
360
+ /**
361
+ * 初始化选中数据
362
+ */
363
+ function initSelectData() {
364
+ const tempList = [] as Array<ILinkItem>
365
+ if (props.modelValue) {
366
+ let [userIds, deptIds, userNames, deptNames] = props.modelValue as any
367
+ if (deptIds && deptNames && deptIds.length === deptNames.length) {
368
+ deptIds.map((id: string, i: number) => {
369
+ tempList.push({ type: 2, value: id, label: deptNames[i] })
370
+ })
371
+ }
372
+ if (userIds && userNames && userIds.length === userNames.length) {
373
+ userIds.map((id: string, i: number) => {
374
+ tempList.push({ type: 1, value: id, label: userNames[i] })
375
+ })
376
+ }
377
+ }
378
+ return tempList
379
+ }
380
+
381
+ /**
382
+ * 初始化选中Id
383
+ */
384
+ function initSelectIds() {
385
+ const tempList = [] as Array<string>
386
+ if (props.modelValue) {
387
+ let [userIds, deptIds] = props.modelValue as any
388
+ tempList.push(...(deptIds || []))
389
+ tempList.push(...(userIds || []))
390
+ }
391
+ return tempList
392
+ }
393
+
394
+ /**
395
+ * 初始化数据
396
+ */
397
+ function init() {
398
+ selectUser.splice(0, selectUser.length, ...initSelectData())
399
+ options.splice(0, options.length, ...initSelectData())
400
+ values.splice(0, values.length, ...initSelectIds())
401
+ }
402
+
403
+ onBeforeMount(async () => {
404
+ // // 如果没有配置,则抛出一个警告
405
+ selectAttrs.value = await getAttrs(props, {
406
+ remote: true,
407
+ filterable: true,
408
+ remoteShowSuffix: true,
409
+ loadingText: '远程查询中...',
410
+ remoteMethod: remoteMethod,
411
+ ...useAttrs()
412
+ })
413
+ })
414
+
415
+ watch(
416
+ () => props.modelValue,
417
+ () => init(),
418
+ { deep: true }
419
+ )
420
+
421
+ onMounted(async () => {
422
+ init()
423
+ })
424
+ </script>
425
+ <style lang="scss" scoped>
426
+ .el-plus-form-link-user {
427
+ width: 100%;
428
+
429
+ .items-panel {
430
+ :deep(.el-input__inner) {
431
+ cursor: pointer;
432
+ }
433
+ }
434
+
435
+ :deep(.el-tag__close) {
436
+ display: none !important;
437
+ }
438
+ }
439
+ </style>
440
+ <style lang="scss">
441
+ .form-link-user-dialog {
442
+ width: 100%;
443
+ display: flex;
444
+ box-sizing: border-box;
445
+
446
+ .panel-left {
447
+ width: 60%;
448
+ display: flex;
449
+ flex-direction: column;
450
+
451
+ .dept-breadcrumb {
452
+ width: 100%;
453
+ padding: 0 10px;
454
+ margin-bottom: 20px;
455
+ cursor: pointer;
456
+ }
457
+ }
458
+
459
+ .panel-right {
460
+ width: 40%;
461
+ margin-left: 20px;
462
+ border-left: 1px var(--el-border-color) var(--el-border-style);
463
+ padding: 20px;
464
+ display: flex;
465
+ overflow: hidden;
466
+ flex-direction: column;
467
+
468
+ .right-title {
469
+ width: 100%;
470
+ font-size: 14px;
471
+ color: #999999;
472
+ margin-bottom: 20px;
473
+ }
474
+
475
+ .tag-list {
476
+ width: 100%;
477
+ flex: 1;
478
+ overflow-y: hidden;
479
+ }
480
+
481
+ .btn-panel {
482
+ width: 100%;
483
+ min-height: 50px;
484
+ padding-top: 10px;
485
+ display: flex;
486
+ justify-content: center;
487
+ }
488
+ }
489
+ }
490
+ </style>