@ebiz/designer-components 0.1.14 → 0.1.16

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