|
|
@@ -12,26 +12,30 @@
|
|
12
|
12
|
start-placeholder="开始" end-placeholder="结束" style="width:320px" @change="() => searchHandler(curQuery)" />
|
|
13
|
13
|
</div>
|
|
14
|
14
|
</div>
|
|
15
|
|
- <el-popover v-if=" deptType !== 'STATION' " class="popover" title="" :visible="visible" placement="bottom-start" trigger="click" width="45vw">
|
|
|
15
|
+ <el-popover v-if="deptType !== 'STATION'" class="popover" title="" :visible="visible" placement="bottom-start"
|
|
|
16
|
+ trigger="click" width="45vw">
|
|
16
|
17
|
<template #reference>
|
|
17
|
18
|
<div class="primary" style="border-radius: 6px;" @click.stop="visible = !visible">{{ props.deptType === 'user'
|
|
18
|
19
|
?
|
|
19
|
|
- '组织架构/模糊搜索' : deptType === 'BRIGADE' ? '部门选择' : deptType === 'MANAGER' ? '班组选择' : deptType === 'TEAMS' ? '小组选择' : '组织选择' }}</div>
|
|
|
20
|
+ '组织架构/模糊搜索' : deptType === 'BRIGADE' ? '部门选择' : deptType === 'MANAGER' ? '班组选择' : deptType === 'TEAMS' ?
|
|
|
21
|
+ '小组选择' : '组织选择' }}</div>
|
|
20
|
22
|
</template>
|
|
21
|
23
|
|
|
22
|
24
|
<div class="custom-el-style">
|
|
23
|
25
|
<div>
|
|
24
|
26
|
<el-autocomplete v-model="personName"
|
|
25
|
27
|
:fetch-suggestions="props.deptType === 'user' ? queryUsers : queryDept"
|
|
26
|
|
- :placeholder="props.deptType === 'user' ? '搜索员工/团队画像' : '搜索部门'" style="width:320px;" clearable
|
|
|
28
|
+ :placeholder="props.deptType === 'user' ? '搜索员工/团队画像' : '搜索部门'" style="width:400px;" clearable
|
|
27
|
29
|
@select="handleSelect">
|
|
28
|
30
|
<template #suffix><el-icon>
|
|
29
|
31
|
<Search />
|
|
30
|
32
|
</el-icon></template>
|
|
31
|
33
|
<template #default="{ item }">
|
|
32
|
|
- <span>{{ item.nickName || item.deptName }}</span>
|
|
33
|
|
- <span v-if="item.deptName && item.nickName" style="font-size:12px;color:#999;margin-left:8px">{{
|
|
34
|
|
- item.deptName }}</span>
|
|
|
34
|
+ <div style="display:flex;flex-direction:column;gap:2px;">
|
|
|
35
|
+ <span style="font-size:14px;color:#fff;">{{ item.nickName || item.deptName || item.name || item.label
|
|
|
36
|
+ }}</span>
|
|
|
37
|
+ <span v-if="item.path && item.path.length > 0" style="font-size:12px;color:#999;">{{ item.path.join('/ ') }}</span>
|
|
|
38
|
+ </div>
|
|
35
|
39
|
</template>
|
|
36
|
40
|
</el-autocomplete>
|
|
37
|
41
|
<!-- <div class="primary" style="border-radius: 6px;" @click="() => searchHandler()">模糊搜索</div> -->
|
|
|
@@ -90,11 +94,40 @@ const findNodeById = (nodes, id) => {
|
|
90
|
94
|
return null
|
|
91
|
95
|
}
|
|
92
|
96
|
|
|
|
97
|
+const buildPathForNode = (nodes, targetId, path = []) => {
|
|
|
98
|
+ if (!nodes) return path
|
|
|
99
|
+ for (const node of nodes) {
|
|
|
100
|
+ if (node.id === targetId || node.deptId === targetId) {
|
|
|
101
|
+ // 如果是用户节点,不把用户名字加入 path
|
|
|
102
|
+ if (node.deptType === 'user' || node.nodeType === 'user') {
|
|
|
103
|
+ return path
|
|
|
104
|
+ }
|
|
|
105
|
+ const name = node.nickName || node.deptName || node.name || node.label
|
|
|
106
|
+ return [...path, name]
|
|
|
107
|
+ }
|
|
|
108
|
+ if (node.children) {
|
|
|
109
|
+ const name = node.deptName || node.name || node.label
|
|
|
110
|
+ const found = buildPathForNode(node.children, targetId, [...path, name])
|
|
|
111
|
+ if (found.length > path.length) {
|
|
|
112
|
+ return found
|
|
|
113
|
+ }
|
|
|
114
|
+ }
|
|
|
115
|
+ }
|
|
|
116
|
+ return path
|
|
|
117
|
+}
|
|
|
118
|
+
|
|
93
|
119
|
const queryUsers = async (query, cb) => {
|
|
94
|
120
|
if (!query?.trim()) { cb([]); return }
|
|
95
|
121
|
try {
|
|
96
|
122
|
const res = await searchPortraitUsers(query.trim())
|
|
97
|
|
- cb((res.data || []).map(u => ({ ...u, value: u.nickName })))
|
|
|
123
|
+ const mapped = (res.data || []).map(u => {
|
|
|
124
|
+ let path = []
|
|
|
125
|
+ if (u.deptId) {
|
|
|
126
|
+ path = buildPathForNode(departments.value, u.deptId)
|
|
|
127
|
+ }
|
|
|
128
|
+ return { ...u, value: u.nickName, path }
|
|
|
129
|
+ })
|
|
|
130
|
+ cb(mapped)
|
|
98
|
131
|
} catch (_) { cb([]) }
|
|
99
|
132
|
}
|
|
100
|
133
|
|
|
|
@@ -102,17 +135,30 @@ const queryDept = async (query, cb) => {
|
|
102
|
135
|
if (!query?.trim()) { cb([]); return }
|
|
103
|
136
|
try {
|
|
104
|
137
|
const res = await listDept({ deptName: query.trim(), deptType: props.deptType })
|
|
105
|
|
- cb((res.data || []).map(d => ({ ...d, value: d.deptName })))
|
|
|
138
|
+ const mapped = (res.data || []).map(d => {
|
|
|
139
|
+ let path = []
|
|
|
140
|
+ if (d.id || d.deptId) {
|
|
|
141
|
+ path = buildPathForNode(departments.value, d.deptId || d.id)
|
|
|
142
|
+ }
|
|
|
143
|
+ return { ...d, value: d.deptName, path }
|
|
|
144
|
+ })
|
|
|
145
|
+ cb(mapped)
|
|
106
|
146
|
} catch (_) { cb([]) }
|
|
107
|
147
|
}
|
|
108
|
148
|
|
|
109
|
149
|
const handleSelect = (item) => {
|
|
|
150
|
+
|
|
110
|
151
|
if (props.deptType === 'user') {
|
|
111
|
|
- personName.value = item.nickName
|
|
112
|
|
- curQuery.value = { personName: item.nickName }
|
|
|
152
|
+ const path = item.path && item.path.length > 0 ? item.path : (item.deptId ? buildPathForNode(departments.value, item.deptId) : [])
|
|
|
153
|
+ const name = item.nickName
|
|
|
154
|
+
|
|
|
155
|
+ personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
|
|
|
156
|
+ curQuery.value = { personName: item.nickName,id:item.id }
|
|
113
|
157
|
searchHandler(curQuery.value)
|
|
114
|
158
|
} else {
|
|
115
|
|
- personName.value = item.deptName
|
|
|
159
|
+ const path = item.path && item.path.length > 0 ? item.path : ((item.id || item.deptId) ? buildPathForNode(departments.value, item.deptId || item.id) : [])
|
|
|
160
|
+ const name = item.deptName || item.name || item.label
|
|
|
161
|
+ personName.value = path.length > 0 ? path.join(' / ') : name
|
|
116
|
162
|
if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
|
|
117
|
163
|
curQuery.value = { deptId: item.deptId || item.id }
|
|
118
|
164
|
}
|
|
|
@@ -192,13 +238,19 @@ const searchHandler = (query = {}) => {
|
|
192
|
238
|
const handleNodeClick = (node) => {
|
|
193
|
239
|
if (props.deptType === 'user') {
|
|
194
|
240
|
if (node.nodeType === 'user') {
|
|
195
|
|
- personName.value = node.label
|
|
196
|
|
- curQuery.value = { personName: node.label }
|
|
|
241
|
+
|
|
|
242
|
+ const path = buildPathForNode(departments.value, node.deptId || node.id)
|
|
|
243
|
+ const name = node.label
|
|
|
244
|
+
|
|
|
245
|
+ personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
|
|
|
246
|
+ curQuery.value = { personName: node.label,id:node.id }
|
|
197
|
247
|
searchHandler(curQuery.value)
|
|
198
|
248
|
}
|
|
199
|
249
|
} else {
|
|
200
|
250
|
if (node.deptType === props.deptType) {
|
|
201
|
|
- personName.value = node.deptName || node.name || node.label;
|
|
|
251
|
+ const path = buildPathForNode(departments.value, node.deptId || node.id)
|
|
|
252
|
+ const name = node.deptName || node.name || node.label;
|
|
|
253
|
+ personName.value = path.length > 0 ? path.join(' / ') : name
|
|
202
|
254
|
if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
|
|
203
|
255
|
curQuery.value = { deptId: node.deptId || node.id }
|
|
204
|
256
|
}
|
|
|
@@ -253,11 +305,15 @@ onMounted(async () => {
|
|
253
|
305
|
if (defaultNode) {
|
|
254
|
306
|
currentKey.value = defaultId
|
|
255
|
307
|
if (props.deptType === 'user') {
|
|
256
|
|
- personName.value = defaultNode.label
|
|
|
308
|
+ const path = buildPathForNode(departments.value, defaultNode.deptId || defaultNode.id)
|
|
|
309
|
+ const name = defaultNode.label
|
|
|
310
|
+ personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
|
|
257
|
311
|
curQuery.value = { personName: defaultNode.label }
|
|
258
|
312
|
searchHandler(curQuery.value)
|
|
259
|
313
|
} else {
|
|
260
|
|
- personName.value = defaultNode.deptName || defaultNode.name || defaultNode.label
|
|
|
314
|
+ const path = buildPathForNode(departments.value, defaultNode.deptId || defaultNode.id)
|
|
|
315
|
+ const name = defaultNode.deptName || defaultNode.name || defaultNode.label
|
|
|
316
|
+ personName.value = path.length > 0 ? path.join(' / ') : name
|
|
261
|
317
|
if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
|
|
262
|
318
|
curQuery.value = { deptId: defaultNode.deptId || defaultNode.id }
|
|
263
|
319
|
}
|
|
|
@@ -281,10 +337,10 @@ onUnmounted(() => {
|
|
281
|
337
|
|
|
282
|
338
|
defineExpose({
|
|
283
|
339
|
getDefQuery() {
|
|
284
|
|
-
|
|
|
340
|
+
|
|
285
|
341
|
return {
|
|
286
|
342
|
...getTimeRange(),
|
|
287
|
|
-
|
|
|
343
|
+
|
|
288
|
344
|
}
|
|
289
|
345
|
}
|
|
290
|
346
|
})
|