@ebiz/designer-components 0.1.12 → 0.1.13

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.
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="ebiz-employee-selector">
3
3
  <!-- 选择框展示区 -->
4
- <div v-if="showDefault" style="display: flex; flex-direction: column; align-items: flex-start; gap: 10px;">
4
+ <div v-if="showDefault" style="display: flex; flex-direction: column; align-items: flex-start; gap: 10px">
5
5
  <div class="selected-items" v-if="selectedItems && selectedItems.length">
6
6
  <div v-for="(item, index) in selectedItems" :key="index" class="selected-item">
7
7
  <t-avatar v-if="item.avatar" :image="item.avatar" size="small" />
@@ -17,9 +17,16 @@
17
17
  </div>
18
18
 
19
19
  <!-- 选择弹窗 -->
20
- <t-dialog v-model:visible="dialogVisible" :header="props.content" :width="800" footer :close-btn="true"
21
- :close-on-esc-keydown="true" :close-on-overlay-click="true" destroyOnClose>
22
-
20
+ <t-dialog
21
+ v-model:visible="dialogVisible"
22
+ :header="props.content"
23
+ :width="800"
24
+ footer
25
+ :close-btn="true"
26
+ :close-on-esc-keydown="true"
27
+ :close-on-overlay-click="true"
28
+ destroyOnClose
29
+ >
23
30
  <!-- 选项卡 -->
24
31
  <t-tabs v-model="activeTab" class="selector-tabs">
25
32
  <t-tab-panel value="organization" label="组织架构" :destroyOnHide="false"></t-tab-panel>
@@ -29,9 +36,7 @@
29
36
  <!-- <t-tab-panel value="subordinate" label="我的下属" :destroyOnHide="false"></t-tab-panel> -->
30
37
  </t-tabs>
31
38
 
32
-
33
39
  <div>
34
-
35
40
  <div class="selector-dialog-content">
36
41
  <!-- 左侧选择区域 -->
37
42
  <div class="left-panel">
@@ -42,21 +47,43 @@
42
47
  </div>
43
48
  <!-- 组织架构 -->
44
49
  <div v-show="activeTab === 'organization'" class="tab-content">
45
- <t-tree ref="organizationTree" :data="organizationData"
46
- :keys="{ label: 'name', value: 'id', children: 'children' }" hover activable :active="currentActive"
47
- @active="handleActive" />
50
+ <t-tree
51
+ ref="organizationTree"
52
+ :data="organizationData"
53
+ expandAll
54
+ :keys="{ label: 'name', value: 'id', children: 'children' }"
55
+ hover
56
+ activable
57
+ :active="currentActive"
58
+ @click="handleActive"
59
+ />
48
60
  </div>
49
61
 
50
62
  <!-- 角色 -->
51
63
  <div v-show="activeTab === 'role'" class="tab-content">
52
- <t-tree ref="roleTree" :data="roleData" :keys="{ label: 'name', value: 'code' }" hover activable
53
- :active="currentActive" @active="handleActive" />
64
+ <t-tree
65
+ ref="roleTree"
66
+ :data="roleData"
67
+ expandAll
68
+ :keys="{ label: 'name', value: 'code' }"
69
+ hover
70
+ activable
71
+ :active="currentActive"
72
+ @click="handleActive"
73
+ />
54
74
  </div>
55
75
 
56
76
  <!-- 岗位 -->
57
77
  <div v-show="activeTab === 'position'" class="tab-content">
58
- <t-tree ref="positionTree" :data="positionData" :keys="{ label: 'name', value: 'id' }" hover activable
59
- :active="currentActive" @active="handleActive" />
78
+ <t-tree
79
+ ref="positionTree"
80
+ :data="positionData"
81
+ :keys="{ label: 'name', value: 'id' }"
82
+ hover
83
+ activable
84
+ :active="currentActive"
85
+ @click="handleActive"
86
+ />
60
87
  </div>
61
88
 
62
89
  <!-- 同部门 -->
@@ -100,24 +127,35 @@
100
127
 
101
128
  <!-- 搜索框 -->
102
129
  <div class="search-box">
103
- <t-input v-model="searchText" placeholder="请输入姓名/拼音/工号搜索" clearable @keyup.enter="handleSearchEnter">
130
+ <t-input
131
+ v-model="searchText"
132
+ placeholder="请输入姓名/拼音/工号搜索"
133
+ clearable
134
+ @keyup.enter="handleSearch"
135
+ >
104
136
  <template #suffix-icon>
105
- <t-icon name="search" @click="handleSearchClick"></t-icon>
137
+ <t-icon name="search" @click="handleSearch"></t-icon>
106
138
  </template>
107
139
  </t-input>
108
- <t-button v-if="searchText" size="small" theme="default" class="clear-search-btn"
109
- @click="clearSearch">清除搜索</t-button>
140
+ <t-button v-if="searchText" size="small" theme="default" class="clear-search-btn" @click="clearSearch"
141
+ >清除搜索</t-button
142
+ >
110
143
  </div>
111
144
 
112
145
  <div class="employee-list">
113
- <div v-for="(item, index) in filteredEmployeeList" :key="index" class="employee-item">
114
- <t-checkbox v-model="item.checked" @change="handleCheckChange(item)"></t-checkbox>
146
+ <div
147
+ v-for="(item, index) in filteredEmployeeList"
148
+ :key="index"
149
+ class="employee-item"
150
+ @click="handleCheckChange(item)"
151
+ >
152
+ <t-checkbox v-model="item.checked" style="pointer-events: none"></t-checkbox>
115
153
  <div class="employee-avatar">
116
154
  <t-avatar v-if="item.avatar" :image="item.avatar" size="small" />
117
155
  <t-avatar v-else size="small">{{ getAvatarText(item.name) }}</t-avatar>
118
156
  </div>
119
157
  <div class="employee-info">
120
- <div class="employee-code">{{ item.no }} - </div>
158
+ <div class="employee-code">{{ item.no }} -</div>
121
159
  <div class="employee-name">{{ item.name }}</div>
122
160
  </div>
123
161
  </div>
@@ -129,7 +167,6 @@
129
167
  </div>
130
168
  </div>
131
169
 
132
-
133
170
  <!-- 底部按钮区域 -->
134
171
  <template #footer>
135
172
  <div class="dialog-footer">
@@ -158,7 +195,7 @@
158
195
  </template>
159
196
 
160
197
  <script setup>
161
- import { ref, computed, watch, onMounted } from 'vue';
198
+ import { ref, computed, watch, onMounted } from 'vue'
162
199
  import {
163
200
  Dialog as TDialog,
164
201
  Button as TButton,
@@ -174,8 +211,8 @@ import {
174
211
  List as TList,
175
212
  ListItem as TListItem,
176
213
  MessagePlugin
177
- } from 'tdesign-vue-next';
178
- import dataService from '../apiService/simpleDataService';
214
+ } from 'tdesign-vue-next'
215
+ import dataService from '../apiService/simpleDataService'
179
216
 
180
217
  // 定义组件属性
181
218
  const props = defineProps({
@@ -226,16 +263,16 @@ const props = defineProps({
226
263
  type: String,
227
264
  default: '选择人员'
228
265
  }
229
- });
266
+ })
230
267
 
231
268
  // 定义组件事件
232
- const emit = defineEmits(['update:modelValue', 'change', 'update:visible', 'confirm']);
233
- const tempVisible = ref(false);
269
+ const emit = defineEmits(['update:modelValue', 'change', 'update:visible', 'confirm'])
270
+ const tempVisible = ref(false)
234
271
  // 内部状态变量
235
272
  const dialogVisible = computed({
236
273
  set(val) {
237
274
  if (props.visible == null) {
238
- tempVisible.value = val;
275
+ tempVisible.value = val
239
276
  return
240
277
  }
241
278
  emit('update:visible', val)
@@ -243,79 +280,75 @@ const dialogVisible = computed({
243
280
  get() {
244
281
  return props.visible ?? tempVisible.value
245
282
  }
246
- });
283
+ })
247
284
 
248
- const searchText = ref('');
249
- const activeTab = ref(props.defaultTab);
250
- const loading = ref(false);
251
- const selectedItems = ref([]);
285
+ const searchText = ref('')
286
+ const activeTab = ref(props.defaultTab)
287
+ const loading = ref(false)
288
+ const selectedItems = ref([])
252
289
  // 对话框中临时保存的选中员工列表
253
- const tempSelectedEmployees = ref([]);
290
+ const tempSelectedEmployees = computed(() => employeeList.value.filter((i) => i.checked))
254
291
  // 是否查询子部门
255
- const childDeptEnable = ref(false);
292
+ const childDeptEnable = ref(false)
256
293
 
257
294
  // 数据源
258
- const organizationData = ref([]);
259
- const roleData = ref([]);
260
- const positionData = ref([]);
261
- const departmentData = ref([]);
262
- const subordinateData = ref([]);
263
- const employeeList = ref([]);
264
- const currentActive = ref([]);
265
- const currentNodeName = ref('');
266
- const selectAll = ref(false);
295
+ const organizationData = ref([])
296
+ const roleData = ref([])
297
+ const positionData = ref([])
298
+ const departmentData = ref([])
299
+ const subordinateData = ref([])
300
+ const employeeList = ref([])
301
+ const currentActive = ref([])
302
+ const currentNodeName = ref('')
303
+ const selectAll = computed(() => employeeList.value > 0 && employeeList.value.every((i) => i.checked))
267
304
 
268
305
  // 从名称中获取头像显示文本
269
306
  const getAvatarText = (name) => {
270
- return name ? name.substring(0, 1) : '';
271
- };
307
+ return name ? name.substring(0, 1) : ''
308
+ }
272
309
 
273
310
  // 处理组织数据,转换为树形结构
274
311
  const _processOrgData = (data) => {
275
312
  // 转换数据结构为树形结构
276
- const map = {};
277
- const result = [];
313
+ const map = {}
314
+ const result = []
278
315
 
279
- data.forEach(item => {
316
+ data.forEach((item) => {
280
317
  map[item.id] = {
281
318
  ...item,
282
319
  name: item.name,
283
320
  id: item.id,
284
321
  children: []
285
- };
286
- });
322
+ }
323
+ })
287
324
 
288
- data.forEach(item => {
289
- const node = map[item.id];
325
+ data.forEach((item) => {
326
+ const node = map[item.id]
290
327
 
291
328
  if (item.manager_dept && map[item.manager_dept]) {
292
- map[item.manager_dept].children.push(node);
329
+ map[item.manager_dept].children.push(node)
293
330
  } else {
294
331
  // 只有在显示根组织或不存在父节点时才添加到结果中
295
332
  if (props.showRootOrg || !item.manager_dept) {
296
- result.push(node);
333
+ result.push(node)
297
334
  }
298
335
  }
299
- });
336
+ })
300
337
 
301
- return result;
302
- };
338
+ return result
339
+ }
303
340
 
304
341
  // 更新全选状态
305
- const updateSelectAllStatus = () => {
306
- selectAll.value = employeeList.value.length > 0 && employeeList.value.every(item => item.checked);
307
- };
308
-
309
342
  const updateSelectStatus = () => {
310
- employeeList.value.forEach(item => {
311
- item.checked = props.modelValue.includes(item.id);
343
+ employeeList.value.forEach((item) => {
344
+ item.checked = props.modelValue.includes(item.id)
312
345
  })
313
346
  }
314
347
 
315
348
  // 选中的员工列表
316
349
  const selectedEmployees = computed(() => {
317
- return employeeList.value.filter((item) => item.checked);
318
- });
350
+ return employeeList.value.filter((item) => item.checked)
351
+ })
319
352
 
320
353
  // 根据搜索文本过滤的员工列表
321
354
  const filteredEmployeeList = computed(() => {
@@ -333,84 +366,68 @@ const filteredEmployeeList = computed(() => {
333
366
  // (item.code && item.code.toLowerCase().includes(keyword))
334
367
  // );
335
368
  // });
336
- });
337
-
338
- const allData = ref([])
339
-
340
- const fetchAllData = async () => {
341
- const response = await dataService.fetch({}, {}, '/process/deptList');
342
- employeeList.value = response ?? [];
343
- }
344
- fetchAllData()
369
+ })
345
370
 
346
371
  // 获取组织架构数据
347
372
  const fetchOrganizationData = async () => {
348
- loading.value = true;
373
+ loading.value = true
349
374
  try {
350
375
  const response = await dataService.fetch(
351
376
  {},
352
377
  {
353
378
  apiId: 1933,
354
379
  key: 'organizationalStructure'
355
- }, "/process/deptList"
356
- );
357
- organizationData.value = response;
358
- handleActive(response[0].id, 'organization')
380
+ },
381
+ '/process/deptList'
382
+ )
383
+ organizationData.value = response
384
+ // handleActive(response[0].id, 'organization')
359
385
  // organizationData.value = processOrgData(response.data || []);
360
386
  } catch (error) {
361
387
  MessagePlugin.error({
362
388
  content: '获取组织架构数据失败',
363
389
  duration: 3000
364
- });
390
+ })
365
391
  } finally {
366
- loading.value = false;
392
+ loading.value = false
367
393
  }
368
- };
394
+ }
369
395
 
370
396
  // 获取角色数据
371
397
  const fetchRoleData = async () => {
372
- loading.value = true;
398
+ loading.value = true
373
399
  try {
374
- const response = await dataService.fetch(
375
- {},
376
- {},
377
- '/process/roleList'
378
- );
379
- roleData.value = response || [];
400
+ const response = await dataService.fetch({}, {}, '/process/roleList')
401
+ roleData.value = response || []
380
402
  } catch (error) {
381
403
  MessagePlugin.error({
382
404
  content: '获取角色数据失败',
383
405
  duration: 3000
384
- });
406
+ })
385
407
  } finally {
386
- loading.value = false;
408
+ loading.value = false
387
409
  }
388
- };
410
+ }
389
411
 
390
412
  // 获取岗位数据
391
413
  const fetchPositionData = async () => {
392
- loading.value = true;
414
+ loading.value = true
393
415
  try {
394
- const response = await dataService.fetch(
395
- {},
396
- {
397
- },
398
- '/process/roleList'
399
- );
400
- positionData.value = response?.data || [];
416
+ const response = await dataService.fetch({}, {}, '/process/roleList')
417
+ positionData.value = response?.data || []
401
418
  } catch (error) {
402
419
  MessagePlugin.error({
403
420
  content: '获取岗位数据失败',
404
421
  duration: 3000
405
- });
422
+ })
406
423
  } finally {
407
- loading.value = false;
424
+ loading.value = false
408
425
  }
409
- };
426
+ }
410
427
 
411
428
  // 获取部门数据
412
429
  const fetchDepartmentData = async () => {
413
- loading.value = true;
430
+ loading.value = true
414
431
  try {
415
432
  const response = await dataService.fetch(
416
433
  {},
@@ -419,21 +436,21 @@ const fetchDepartmentData = async () => {
419
436
  key: 'departmentList',
420
437
  apiType: 'MULTIPLE_DATA_SEARCH'
421
438
  }
422
- );
423
- departmentData.value = response?.data || [];
439
+ )
440
+ departmentData.value = response?.data || []
424
441
  } catch (error) {
425
442
  MessagePlugin.error({
426
443
  content: '获取部门数据失败',
427
444
  duration: 3000
428
- });
445
+ })
429
446
  } finally {
430
- loading.value = false;
447
+ loading.value = false
431
448
  }
432
- };
449
+ }
433
450
 
434
451
  // 获取下属数据
435
452
  const fetchSubordinateData = async () => {
436
- loading.value = true;
453
+ loading.value = true
437
454
  try {
438
455
  const response = await dataService.fetch(
439
456
  {},
@@ -441,390 +458,347 @@ const fetchSubordinateData = async () => {
441
458
  apiKey: 'subordinateList',
442
459
  apiType: 'MULTIPLE_DATA_SEARCH'
443
460
  }
444
- );
445
- subordinateData.value = response?.data || [];
461
+ )
462
+ subordinateData.value = response?.data || []
446
463
  } catch (error) {
447
464
  MessagePlugin.error({
448
465
  content: '获取下属数据失败',
449
466
  duration: 3000
450
- });
467
+ })
451
468
  } finally {
452
- loading.value = false;
469
+ loading.value = false
453
470
  }
454
- };
471
+ }
455
472
 
456
473
  // 根据节点ID获取员工列表
457
- const fetchEmployeesByNode = async (nodeId, type, keyword = searchText.value) => {
458
- loading.value = true;
474
+ const fetchEmployeesByNode = async (nodeId, keyword = searchText.value) => {
475
+ loading.value = true
459
476
  try {
460
- const params = {};
477
+ const params = {}
461
478
 
462
479
  // 只有当nodeId不为空且type有效时,添加对应参数
463
- if (nodeId && type) {
480
+ if (nodeId && activeTab.value) {
464
481
  // 根据不同类型设置不同的查询参数
465
- switch (type) {
482
+ switch (activeTab.value) {
466
483
  case 'organization':
467
- params.deptId = Array.isArray(nodeId) ? nodeId[0] : nodeId;
484
+ params.deptId = Array.isArray(nodeId) ? nodeId[0] : nodeId
468
485
  // 添加子部门查询参数
469
- params.childDeptEnable = childDeptEnable.value;
470
- break;
486
+ params.childDeptEnable = childDeptEnable.value
487
+ break
471
488
  case 'role':
472
- params.roleKeyWork = nodeId[0];
473
- break;
489
+ params.roleKeyWork = nodeId[0]
490
+ break
474
491
  case 'position':
475
- params.positionId = nodeId;
476
- break;
492
+ params.positionId = nodeId
493
+ break
477
494
  case 'department':
478
- params.departmentId = nodeId;
479
- break;
495
+ params.departmentId = nodeId
496
+ break
480
497
  case 'subordinate':
481
- params.managerId = nodeId;
482
- break;
498
+ params.managerId = nodeId
499
+ break
483
500
  }
484
501
  }
485
502
 
486
503
  // 如果有搜索关键词,添加到查询参数中
487
504
  if (keyword) {
488
- params.keyWord = keyword;
505
+ params.keyWord = keyword
489
506
  }
490
507
 
491
- const response = await dataService.fetch(
492
- params,
493
- {},
494
- '/process/userList'
495
- );
508
+ const response = await dataService.fetch(params, {}, '/process/userList')
496
509
  // 获取当前已选择的员工ID列表
497
- const selectedIds = [...new Set(tempSelectedEmployees.value.map(emp => emp.id))];
510
+ const selectedIds = [...new Set(tempSelectedEmployees.value.map((emp) => emp.id))]
498
511
 
499
512
  // 处理返回数据,添加checked属性,保留已选状态
500
- const employees = (response || []).map(emp => ({
513
+ const employees = (response || []).map((emp) => ({
501
514
  ...emp,
502
515
  checked: selectedIds.includes(emp.id)
503
- }));
516
+ }))
504
517
 
505
- employeeList.value = employees;
506
- updateSelectAllStatus();
518
+ employeeList.value = employees
507
519
  } catch (error) {
508
520
  MessagePlugin.error({
509
521
  content: '获取员工列表失败',
510
522
  duration: 3000
511
- });
523
+ })
512
524
  } finally {
513
- loading.value = false;
525
+ loading.value = false
514
526
  }
515
- };
527
+ }
516
528
 
517
529
  // 根据ID列表批量获取员工信息
518
- const fetchEmployeesByIds = async (ids) => {
530
+ const fetchEmployeesByIds = (ids) => {
519
531
  if (!ids || ids.length === 0) {
520
- selectedItems.value = [];
521
- return;
532
+ selectedItems.value = []
533
+ return
522
534
  }
523
-
524
- loading.value = true;
525
- try {
526
- const response = await dataService.fetch(
535
+ loading.value = true
536
+ dataService
537
+ .fetch(
527
538
  {
528
539
  userIds: ids // 使用新的接口参数格式
529
540
  },
530
541
  {},
531
542
  '/process/userList' // 直接使用新的API路径
532
- );
533
-
534
- if (response && Array.isArray(response)) {
535
- selectedItems.value = response;
536
- } else {
537
- selectedItems.value = [];
538
- MessagePlugin.warning({
539
- content: '获取员工详情返回的数据格式不正确',
543
+ )
544
+ .then((res) => {
545
+ selectedItems.value = res ?? []
546
+ })
547
+ .catch((error) => {
548
+ selectedItems.value = []
549
+ MessagePlugin.error({
550
+ content: '获取员工详情失败: ' + (error.message || '未知错误'),
540
551
  duration: 3000
541
- });
542
- }
543
- } catch (error) {
544
- selectedItems.value = [];
545
- MessagePlugin.error({
546
- content: '获取员工详情失败: ' + (error.message || '未知错误'),
547
- duration: 3000
548
- });
549
- } finally {
550
- loading.value = false;
551
- }
552
- };
552
+ })
553
+ })
554
+ .finally(() => {
555
+ loading.value = false
556
+ })
557
+ }
553
558
 
554
559
  // 处理节点激活
555
- const handleActive = (value, context) => {
556
- currentActive.value = [value];
557
- currentNodeName.value = context.node?.label || '';
558
-
560
+ const handleActive = ({ node }) => {
561
+ currentActive.value = node?.value
562
+ currentNodeName.value = node?.label || ''
559
563
  // 获取该节点下的员工
560
- fetchEmployeesByNode(value, activeTab.value);
561
- };
564
+ fetchEmployeesByNode(node.value)
565
+ }
562
566
 
563
567
  // 选择部门
564
568
  const selectDepartment = (department) => {
565
- currentNodeName.value = department.name;
566
- fetchEmployeesByNode(department.id, activeTab.value);
567
- };
569
+ currentNodeName.value = department.name
570
+ fetchEmployeesByNode(department.id)
571
+ }
568
572
 
569
573
  // 处理全选
570
574
  const handleSelectAll = (checked) => {
571
- employeeList.value.forEach(item => {
572
- item.checked = checked;
573
-
574
- // 如果选中,确保添加到临时选中列表
575
- if (checked && !tempSelectedEmployees.value.some(emp => emp.id === item.id)) {
576
- tempSelectedEmployees.value.push(item);
577
- }
578
- });
579
- };
575
+ employeeList.value.forEach((item) => {
576
+ item.checked = checked
577
+ })
578
+ }
580
579
 
581
580
  // 处理选中状态变更
582
581
  const handleCheckChange = (item) => {
583
582
  // 单选模式下,取消其他选中
584
583
  if (props.single) {
585
- employeeList.value.forEach(emp => {
584
+ employeeList.value.forEach((emp) => {
586
585
  if (emp.id !== item.id) {
587
- emp.checked = false;
586
+ emp.checked = false
588
587
  }
589
- });
590
- // 单选模式下,直接替换tempSelectedEmployees
591
- tempSelectedEmployees.value = item.checked ? [item] : [];
588
+ })
589
+ item.checked = true
592
590
  } else {
593
591
  // 多选模式
594
592
  // 如果选中,添加到临时选中列表
595
- if (item.checked && !tempSelectedEmployees.value.some(emp => emp.id === item.id)) {
596
- tempSelectedEmployees.value.push(item);
597
- } else if (!item.checked) {
598
- // 如果取消选中,从临时选中列表中移除
599
- const index = tempSelectedEmployees.value.findIndex(emp => emp.id === item.id);
600
- if (index !== -1) {
601
- tempSelectedEmployees.value.splice(index, 1);
602
- }
603
- }
593
+ item.checked = !item.checked
604
594
  }
605
595
 
606
596
  // 检查最大选择数量限制
607
597
  if (props.maxCount > 0) {
608
- const checkedCount = tempSelectedEmployees.value.length;
598
+ const checkedCount = tempSelectedEmployees.value.length
609
599
  if (checkedCount > props.maxCount) {
610
- item.checked = false;
611
- const index = tempSelectedEmployees.value.findIndex(emp => emp.id === item.id);
612
- if (index !== -1) {
613
- tempSelectedEmployees.value.splice(index, 1);
614
- }
600
+ item.checked = false
615
601
  MessagePlugin.warning({
616
602
  content: `最多只能选择${props.maxCount}个人员`,
617
603
  duration: 3000
618
- });
604
+ })
619
605
  }
620
606
  }
621
-
622
- updateSelectAllStatus();
623
- };
607
+ }
624
608
 
625
609
  // 移除已选择的项目
626
610
  const removeItem = (index, id) => {
627
611
  // 移除ID
628
- const newIds = [...props.modelValue];
629
- const idIndex = newIds.indexOf(id);
612
+ const newIds = [...props.modelValue]
613
+ const idIndex = newIds.indexOf(id)
630
614
  if (idIndex !== -1) {
631
- newIds.splice(idIndex, 1);
632
- emit('update:modelValue', newIds);
633
- emit('change', newIds);
615
+ newIds.splice(idIndex, 1)
616
+ emit('update:modelValue', newIds)
617
+ emit('change', newIds)
634
618
  }
635
619
 
636
620
  // 移除展示项
637
- selectedItems.value.splice(index, 1);
638
- };
621
+ selectedItems.value.splice(index, 1)
622
+ }
639
623
 
640
624
  // 从已选列表中移除员工
641
625
  const removeSelectedEmployee = (employee) => {
642
626
  // 将员工的checked状态设为false
643
- const foundEmployee = employeeList.value.find(item => item.id === employee.id);
627
+ const foundEmployee = employeeList.value.find((item) => item.id === employee.id)
644
628
  if (foundEmployee) {
645
- foundEmployee.checked = false;
646
- }
647
-
648
- // 从临时选中列表中移除
649
- const index = tempSelectedEmployees.value.findIndex(emp => emp.id === employee.id);
650
- if (index !== -1) {
651
- tempSelectedEmployees.value.splice(index, 1);
629
+ foundEmployee.checked = false
652
630
  }
653
-
654
- // 更新全选状态
655
- updateSelectAllStatus();
656
- };
631
+ }
657
632
 
658
633
  // 初始化选择器
659
634
  const initSelector = async () => {
660
635
  // 获取数据
661
636
  if (activeTab.value === 'organization' && organizationData.value.length === 0) {
662
- await fetchOrganizationData();
637
+ await fetchOrganizationData()
663
638
  } else if (activeTab.value === 'role' && roleData.value.length === 0) {
664
- await fetchRoleData();
639
+ await fetchRoleData()
665
640
  } else if (activeTab.value === 'position' && positionData.value.length === 0) {
666
- await fetchPositionData();
641
+ await fetchPositionData()
667
642
  } else if (activeTab.value === 'department' && departmentData.value.length === 0) {
668
- await fetchDepartmentData();
643
+ await fetchDepartmentData()
669
644
  } else if (activeTab.value === 'subordinate' && subordinateData.value.length === 0) {
670
- await fetchSubordinateData();
645
+ await fetchSubordinateData()
671
646
  }
672
- };
647
+ }
673
648
 
674
649
  // 显示对话框
675
650
  const showDialog = () => {
676
651
  // 初始化临时选中列表
677
652
  if (selectedItems.value.length > 0) {
678
- tempSelectedEmployees.value = [...selectedItems.value];
653
+ tempSelectedEmployees.value = [...selectedItems.value]
679
654
  updateSelectStatus()
680
655
  } else {
681
- tempSelectedEmployees.value = [];
656
+ tempSelectedEmployees.value = []
682
657
  }
683
658
 
684
659
  // 初始化数据
685
660
  if (props.visible == null) {
686
- initSelector();
661
+ initSelector()
687
662
  }
688
- dialogVisible.value = true;
689
- };
663
+ dialogVisible.value = true
664
+ }
690
665
 
691
666
  // 确认选择
692
667
  const handleConfirm = () => {
693
- const selectedEmployeeIds = tempSelectedEmployees.value.map(item => item.id);
668
+ const selectedEmployeeIds = tempSelectedEmployees.value.map((item) => item.id)
694
669
 
695
- emit('update:modelValue', selectedEmployeeIds);
696
- emit('change', selectedEmployeeIds);
697
- emit('confirm', selectedEmployeeIds);
698
- dialogVisible.value = false;
699
- };
670
+ emit('update:modelValue', selectedEmployeeIds)
671
+ emit('change', selectedEmployeeIds)
672
+ emit('confirm', selectedEmployeeIds)
673
+ dialogVisible.value = false
674
+ }
700
675
 
701
676
  // 取消选择
702
677
  const handleCancel = () => {
703
678
  // 放弃临时选择
704
- tempSelectedEmployees.value = [];
705
- dialogVisible.value = false;
706
- };
679
+ tempSelectedEmployees.value = []
680
+ dialogVisible.value = false
681
+ }
707
682
 
708
683
  // 监听标签页切换
709
684
  watch(activeTab, () => {
710
685
  // 切换标签页时重新加载数据
711
- initSelector();
712
- });
686
+ initSelector()
687
+ })
713
688
 
714
689
  // 监听modelValue变化,更新展示的员工信息
715
- watch(() => props.modelValue, (newIds, oldIds) => {
716
- // 判断值是否真的变化了 (通过比较JSON字符串)
717
- const newIdsStr = JSON.stringify(newIds || []);
718
- const oldIdsStr = JSON.stringify(oldIds || []);
719
-
720
- if (newIdsStr !== oldIdsStr) {
721
- // 获取员工详情数据
722
- fetchEmployeesByIds(newIds);
723
- }
724
- }, { immediate: true, deep: true });
725
- watch(() => props.visible, (val) => {
726
- tempSelectedEmployees.value = [];
727
- currentActive.value = [];
728
- currentNodeName.value = '';
729
-
730
- if (val) {
731
- fetchOrganizationData()
732
- }
733
- }, { immediate: true })
734
- // 监听选中员工变化,更新临时已选列表
735
- watch(selectedEmployees, (newVal) => {
736
- // 更新临时选中列表,保留之前不在当前列表中的已选员工
737
- const currentIds = new Set(newVal.map(emp => emp.id));
738
-
739
- // 移除tempSelectedEmployees中已经不再选中的员工
740
- tempSelectedEmployees.value = tempSelectedEmployees.value.filter(emp =>
741
- !currentIds.has(emp.id) || newVal.some(item => item.id === emp.id)
742
- );
743
-
744
- // 添加新选中的员工
745
- newVal.forEach(emp => {
746
- if (!tempSelectedEmployees.value.some(item => item.id === emp.id)) {
747
- tempSelectedEmployees.value.push(emp);
690
+ watch(
691
+ () => props.modelValue,
692
+ (newIds, oldIds) => {
693
+ // 判断值是否真的变化了 (通过比较JSON字符串)
694
+ const newIdsStr = JSON.stringify(newIds || [])
695
+ const oldIdsStr = JSON.stringify(oldIds || [])
696
+
697
+ if (newIdsStr !== oldIdsStr) {
698
+ // 获取员工详情数据
699
+ fetchEmployeesByIds(newIds)
748
700
  }
749
- });
750
- }, { deep: true });
701
+ },
702
+ { immediate: true, deep: true }
703
+ )
704
+ watch(
705
+ () => props.visible,
706
+ (val) => {
707
+ tempSelectedEmployees.value = []
708
+ currentActive.value = []
709
+ currentNodeName.value = ''
710
+
711
+ if (val) {
712
+ fetchOrganizationData()
713
+ }
714
+ },
715
+ { immediate: true }
716
+ )
717
+ // 监听选中员工变化,更新临时已选列表
718
+ watch(
719
+ selectedEmployees,
720
+ (newVal) => {
721
+ // 更新临时选中列表,保留之前不在当前列表中的已选员工
722
+ const currentIds = new Set(newVal.map((emp) => emp.id))
723
+
724
+ // 移除tempSelectedEmployees中已经不再选中的员工
725
+ tempSelectedEmployees.value = tempSelectedEmployees.value.filter(
726
+ (emp) => !currentIds.has(emp.id) || newVal.some((item) => item.id === emp.id)
727
+ )
728
+
729
+ // 添加新选中的员工
730
+ newVal.forEach((emp) => {
731
+ if (!tempSelectedEmployees.value.some((item) => item.id === emp.id)) {
732
+ tempSelectedEmployees.value.push(emp)
733
+ }
734
+ })
735
+ },
736
+ { deep: true }
737
+ )
751
738
 
752
739
  // 监听子部门查询开关变化
753
740
  watch(childDeptEnable, () => {
754
741
  // 如果当前在组织架构页面且有选中节点,重新加载员工列表
755
742
  if (activeTab.value === 'organization' && currentActive.value && currentActive.value.length > 0) {
756
- fetchEmployeesByNode(currentActive.value[0], activeTab.value);
743
+ fetchEmployeesByNode(currentActive.value[0])
757
744
  }
758
- });
745
+ })
759
746
 
760
747
  // 防抖函数
761
748
  const debounce = (fn, delay) => {
762
- let timer = null;
749
+ let timer = null
763
750
  return function (...args) {
764
- if (timer) clearTimeout(timer);
751
+ if (timer) clearTimeout(timer)
765
752
  timer = setTimeout(() => {
766
- fn.apply(this, args);
767
- }, delay);
768
- };
769
- };
753
+ fn.apply(this, args)
754
+ }, delay)
755
+ }
756
+ }
770
757
 
771
758
  // 防抖处理过的搜索函数
772
759
  const debouncedSearch = debounce((keyword) => {
773
760
  if (keyword) {
774
- const nodeId = currentActive.value && currentActive.value.length > 0 ? currentActive.value[0] : null;
775
- const type = nodeId ? activeTab.value : null;
776
- fetchEmployeesByNode(nodeId, type, keyword);
761
+ const nodeId = currentActive.value && currentActive.value.length > 0 ? currentActive.value[0] : null
762
+ fetchEmployeesByNode(nodeId, keyword)
777
763
  } else if (currentActive.value && currentActive.value.length > 0) {
778
764
  // 如果搜索框清空,恢复显示当前选中节点的员工列表
779
- fetchEmployeesByNode(currentActive.value[0], activeTab.value);
765
+ fetchEmployeesByNode(currentActive.value[0])
780
766
  } else {
781
767
  // 如果没有选中节点,清空员工列表
782
- employeeList.value = [];
768
+ employeeList.value = []
783
769
  }
784
- }, 300); // 300ms防抖
770
+ }, 300) // 300ms防抖
785
771
 
786
772
  // 监听搜索文本变化,触发搜索
787
- watch(searchText, (newValue) => {
788
- debouncedSearch(newValue);
789
- }, { immediate: false });
790
-
791
- // 组件挂载时执行
792
- onMounted(() => {
793
- // 获取已选员工详情
794
- fetchEmployeesByIds(props.modelValue);
795
- });
773
+ watch(
774
+ searchText,
775
+ (newValue) => {
776
+ debouncedSearch(newValue)
777
+ },
778
+ { immediate: false }
779
+ )
796
780
 
797
781
  // 处理搜索图标点击
798
- const handleSearchClick = () => {
782
+ const handleSearch = () => {
799
783
  if (searchText.value) {
800
- const nodeId = currentActive.value && currentActive.value.length > 0 ? currentActive.value[0] : null;
801
- const type = nodeId ? activeTab.value : null;
802
- fetchEmployeesByNode(nodeId, type, searchText.value);
784
+ const nodeId = currentActive.value && currentActive.value.length > 0 ? currentActive.value[0] : null
785
+ fetchEmployeesByNode(nodeId, searchText.value)
803
786
  }
804
- };
805
-
806
- // 处理回车键搜索
807
- const handleSearchEnter = () => {
808
- if (searchText.value) {
809
- const nodeId = currentActive.value && currentActive.value.length > 0 ? currentActive.value[0] : null;
810
- const type = nodeId ? activeTab.value : null;
811
- fetchEmployeesByNode(nodeId, type, searchText.value);
812
- }
813
- };
787
+ }
814
788
 
815
789
  // 清除搜索
816
790
  const clearSearch = () => {
817
- searchText.value = '';
791
+ searchText.value = ''
818
792
  if (currentActive.value && currentActive.value.length > 0) {
819
- fetchEmployeesByNode(currentActive.value[0], activeTab.value);
793
+ fetchEmployeesByNode(currentActive.value[0])
820
794
  } else {
821
795
  // 如果没有选中节点,重置员工列表但保留选中状态
822
- employeeList.value = employeeList.value.map(emp => ({
796
+ employeeList.value = employeeList.value.map((emp) => ({
823
797
  ...emp,
824
- checked: tempSelectedEmployees.value.some(item => item.id === emp.id)
825
- }));
798
+ checked: tempSelectedEmployees.value.some((item) => item.id === emp.id)
799
+ }))
826
800
  }
827
- };
801
+ }
828
802
  </script>
829
803
 
830
804
  <style scoped>
@@ -884,7 +858,7 @@ const clearSearch = () => {
884
858
  }
885
859
 
886
860
  .item-remove:hover {
887
- color: #E34D59;
861
+ color: #e34d59;
888
862
  }
889
863
 
890
864
  /* 选择弹窗 */
@@ -1096,6 +1070,6 @@ const clearSearch = () => {
1096
1070
  }
1097
1071
 
1098
1072
  .selected-people-item .item-remove:hover {
1099
- color: #E34D59;
1073
+ color: #e34d59;
1100
1074
  }
1101
1075
  </style>