|
|
@@ -1,44 +1,40 @@
|
|
1
|
1
|
<template>
|
|
2
|
2
|
<div class="ep-topbar" @click="visible = false">
|
|
3
|
3
|
<div class="time-btns">
|
|
4
|
|
- <div :class="currentTime==='week' ? 'primary' : 'default'" @click="selectTime('week')">近一周</div>
|
|
5
|
|
- <div :class="currentTime==='month' ? 'primary' : 'default'" @click="selectTime('month')">近一月</div>
|
|
6
|
|
- <div :class="currentTime==='quarter' ? 'primary' : 'default'" @click="selectTime('quarter')">近三月</div>
|
|
7
|
|
- <div :class="currentTime==='year' ? 'primary' : 'default'" @click="selectTime('year')">近一年</div>
|
|
8
|
|
- <div :class="currentTime==='custom' ? 'primary' : 'default'" @click="selectTime('custom')">自定义时间范围</div>
|
|
9
|
|
- <div class="custom-style-date-picker-wrap" v-if="currentTime==='custom'">
|
|
10
|
|
- <el-date-picker
|
|
11
|
|
- class="custom-style-date-picker"
|
|
12
|
|
- v-model="dateRange"
|
|
13
|
|
- type="daterange"
|
|
14
|
|
- range-separator="至"
|
|
15
|
|
- start-placeholder="开始"
|
|
16
|
|
- end-placeholder="结束"
|
|
17
|
|
- style="width:320px"
|
|
18
|
|
- @change="() => searchHandler()"
|
|
19
|
|
- />
|
|
|
4
|
+ <div :class="currentTime === 'week' ? 'primary' : 'default'" @click="selectTime('week')">近一周</div>
|
|
|
5
|
+ <div :class="currentTime === 'month' ? 'primary' : 'default'" @click="selectTime('month')">近一月</div>
|
|
|
6
|
+ <div :class="currentTime === 'quarter' ? 'primary' : 'default'" @click="selectTime('quarter')">近三月</div>
|
|
|
7
|
+ <div :class="currentTime === 'year' ? 'primary' : 'default'" @click="selectTime('year')">近一年</div>
|
|
|
8
|
+ <div :class="currentTime === 'custom' ? 'primary' : 'default'" @click="selectTime('custom')">自定义时间范围</div>
|
|
|
9
|
+ <div class="custom-style-date-picker-wrap" v-if="currentTime === 'custom'">
|
|
|
10
|
+ <el-date-picker class="custom-style-date-picker" v-model="dateRange" type="daterange" range-separator="至"
|
|
|
11
|
+ start-placeholder="开始" end-placeholder="结束" style="width:320px" @change="() => searchHandler()" />
|
|
20
|
12
|
</div>
|
|
21
|
13
|
</div>
|
|
22
|
14
|
<el-popover class="popover" title="" :visible="visible" placement="bottom-start" trigger="click" width="45vw">
|
|
23
|
15
|
<template #reference>
|
|
24
|
|
- <div class="primary" style="border-radius: 6px;" @click.stop="visible = !visible">组织架构/模糊搜索</div>
|
|
|
16
|
+ <div class="primary" style="border-radius: 6px;" @click.stop="visible = !visible">{{ props.deptType === 'user' ?
|
|
|
17
|
+ '组织架构/模糊搜索' : '部门选择' }}</div>
|
|
25
|
18
|
</template>
|
|
26
|
19
|
|
|
27
|
20
|
<div class="custom-el-style">
|
|
28
|
21
|
<div>
|
|
29
|
|
- <el-autocomplete v-model="personName" :fetch-suggestions="queryUsers" placeholder="搜索员工/团队画像" style="width:320px;" clearable>
|
|
30
|
|
- <template #suffix
|
|
31
|
|
- ><el-icon><Search /></el-icon
|
|
32
|
|
- ></template>
|
|
|
22
|
+ <el-autocomplete v-model="personName" :fetch-suggestions="props.deptType === 'user' ? queryUsers : queryDept"
|
|
|
23
|
+ :placeholder="props.deptType === 'user' ? '搜索员工/团队画像' : '搜索部门'" style="width:320px;" clearable>
|
|
|
24
|
+ <template #suffix><el-icon>
|
|
|
25
|
+ <Search />
|
|
|
26
|
+ </el-icon></template>
|
|
33
|
27
|
<template #default="{ item }">
|
|
34
|
|
- <span>{{ item.nickName }}</span>
|
|
35
|
|
- <span v-if="item.deptName" style="font-size:12px;color:#999;margin-left:8px">{{ item.deptName }}</span>
|
|
|
28
|
+ <span>{{ item.nickName || item.deptName }}</span>
|
|
|
29
|
+ <span v-if="item.deptName && item.nickName" style="font-size:12px;color:#999;margin-left:8px">{{
|
|
|
30
|
+ item.deptName }}</span>
|
|
36
|
31
|
</template>
|
|
37
|
32
|
</el-autocomplete>
|
|
38
|
33
|
<div class="primary" style="border-radius: 6px;" @click="() => searchHandler()">模糊搜索</div>
|
|
39
|
34
|
</div>
|
|
40
|
35
|
<div style="margin-top: 20px;">
|
|
41
|
|
- <el-tree :data="departments" :default-expanded-keys="[100]" :props="{ value: 'id', showPrefix: false }" accordion @node-click="handleNodeClick" />
|
|
|
36
|
+ <el-tree :data="departments" :default-expanded-keys="[100]" :props="{ value: 'id', showPrefix: false }"
|
|
|
37
|
+ accordion @node-click="handleNodeClick" />
|
|
42
|
38
|
</div>
|
|
43
|
39
|
</div>
|
|
44
|
40
|
</el-popover>
|
|
|
@@ -48,7 +44,15 @@
|
|
48
|
44
|
<script setup>
|
|
49
|
45
|
import { onMounted, onUnmounted } from 'vue'
|
|
50
|
46
|
import { searchPortraitUsers } from '@/api/score/index'
|
|
51
|
|
-import { getDeptUserTree } from '@/api/item/items'
|
|
|
47
|
+import { getDeptList } from '@/api/item/items'
|
|
|
48
|
+import { listDept } from '@/api/system/dept'
|
|
|
49
|
+
|
|
|
50
|
+const props = defineProps({
|
|
|
51
|
+ deptType: {
|
|
|
52
|
+ type: String,
|
|
|
53
|
+ default: 'user'
|
|
|
54
|
+ }
|
|
|
55
|
+})
|
|
52
|
56
|
|
|
53
|
57
|
const visible = defineModel('visible', false)
|
|
54
|
58
|
const emit = defineEmits(['search'])
|
|
|
@@ -65,6 +69,31 @@ const queryUsers = async (query, cb) => {
|
|
65
|
69
|
} catch (_) { cb([]) }
|
|
66
|
70
|
}
|
|
67
|
71
|
|
|
|
72
|
+const queryDept = async (query, cb) => {
|
|
|
73
|
+ if (!query?.trim()) { cb([]); return }
|
|
|
74
|
+ try {
|
|
|
75
|
+ const res = await listDept({ deptName: query.trim(), deptType: props.deptType })
|
|
|
76
|
+ cb((res.data || []).map(d => ({ ...d, value: d.deptName })))
|
|
|
77
|
+ } catch (_) { cb([]) }
|
|
|
78
|
+}
|
|
|
79
|
+
|
|
|
80
|
+const filterDeptTree = (data, targetType) => {
|
|
|
81
|
+ const filterNode = (node) => {
|
|
|
82
|
+ if (node.deptType === targetType) {
|
|
|
83
|
+ return { ...node, children: undefined }
|
|
|
84
|
+ }
|
|
|
85
|
+ if (node.children && node.children.length > 0) {
|
|
|
86
|
+ const filteredChildren = node.children.map(child => filterNode(child)).filter(Boolean)
|
|
|
87
|
+ if (filteredChildren.length > 0) {
|
|
|
88
|
+ return { ...node, children: filteredChildren }
|
|
|
89
|
+ }
|
|
|
90
|
+ }
|
|
|
91
|
+ return null
|
|
|
92
|
+ }
|
|
|
93
|
+
|
|
|
94
|
+ return data.map(node => filterNode(node)).filter(Boolean)
|
|
|
95
|
+}
|
|
|
96
|
+
|
|
68
|
97
|
const getTimeRange = () => {
|
|
69
|
98
|
if (currentTime.value === 'custom') {
|
|
70
|
99
|
if (dateRange.value?.length === 2) {
|
|
|
@@ -73,16 +102,16 @@ const getTimeRange = () => {
|
|
73
|
102
|
return {}
|
|
74
|
103
|
}
|
|
75
|
104
|
const end = new Date(), begin = new Date()
|
|
76
|
|
- if (currentTime.value === 'week') begin.setDate(end.getDate()-7)
|
|
77
|
|
- else if (currentTime.value === 'month') begin.setMonth(end.getMonth()-1)
|
|
78
|
|
- else if (currentTime.value === 'quarter') begin.setMonth(end.getMonth()-3)
|
|
79
|
|
- else begin.setFullYear(end.getFullYear()-1)
|
|
|
105
|
+ if (currentTime.value === 'week') begin.setDate(end.getDate() - 7)
|
|
|
106
|
+ else if (currentTime.value === 'month') begin.setMonth(end.getMonth() - 1)
|
|
|
107
|
+ else if (currentTime.value === 'quarter') begin.setMonth(end.getMonth() - 3)
|
|
|
108
|
+ else begin.setFullYear(end.getFullYear() - 1)
|
|
80
|
109
|
return { beginTime: formatDate(begin), endTime: formatDate(end) }
|
|
81
|
110
|
}
|
|
82
|
111
|
|
|
83
|
112
|
const formatDate = (d) => {
|
|
84
|
113
|
const dt = new Date(d)
|
|
85
|
|
- return `${dt.getFullYear()}-${String(dt.getMonth()+1).padStart(2,'0')}-${String(dt.getDate()).padStart(2,'0')}`
|
|
|
114
|
+ return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, '0')}-${String(dt.getDate()).padStart(2, '0')}`
|
|
86
|
115
|
}
|
|
87
|
116
|
|
|
88
|
117
|
const selectTime = (t) => {
|
|
|
@@ -91,15 +120,37 @@ const selectTime = (t) => {
|
|
91
|
120
|
}
|
|
92
|
121
|
|
|
93
|
122
|
const searchHandler = (query = {}) => {
|
|
94
|
|
- const queryParams = { ...getTimeRange(), personName: personName.value, ...query }
|
|
95
|
|
- if (queryParams.personName) {
|
|
|
123
|
+ const queryParams = { ...getTimeRange(), ...query }
|
|
|
124
|
+ if (props.deptType === 'user') {
|
|
|
125
|
+ if (queryParams.personName) {
|
|
|
126
|
+ emit('search', queryParams)
|
|
|
127
|
+ }
|
|
|
128
|
+ } else {
|
|
96
|
129
|
emit('search', queryParams)
|
|
97
|
130
|
}
|
|
98
|
131
|
}
|
|
99
|
132
|
|
|
100
|
133
|
const handleNodeClick = (node) => {
|
|
101
|
|
- if (node.nodeType === 'user') {
|
|
102
|
|
- searchHandler({ personName: node.label })
|
|
|
134
|
+ if (props.deptType === 'user') {
|
|
|
135
|
+ if (node.nodeType === 'user') {
|
|
|
136
|
+ personName.value = node.label
|
|
|
137
|
+ searchHandler({ personName: node.label })
|
|
|
138
|
+ }
|
|
|
139
|
+ } else {
|
|
|
140
|
+ if (node.deptType === props.deptType) {
|
|
|
141
|
+ personName.value = node.deptName || node.name || node.label;
|
|
|
142
|
+ let obj = {}
|
|
|
143
|
+ if(props.deptType === 'BRIGADE') {
|
|
|
144
|
+ obj = { deptId: node.deptId || node.id }
|
|
|
145
|
+ }
|
|
|
146
|
+ if(props.deptType === 'MANAGER') {
|
|
|
147
|
+ obj = { teamId: node.deptId || node.id }
|
|
|
148
|
+ }
|
|
|
149
|
+ if(props.deptType === 'TEAMS') {
|
|
|
150
|
+ obj = { groupId: node.deptId || node.id }
|
|
|
151
|
+ }
|
|
|
152
|
+ searchHandler(obj)
|
|
|
153
|
+ }
|
|
103
|
154
|
}
|
|
104
|
155
|
}
|
|
105
|
156
|
|
|
|
@@ -126,17 +177,20 @@ const resetStyle = () => {
|
|
126
|
177
|
|
|
127
|
178
|
onMounted(async () => {
|
|
128
|
179
|
setStyle()
|
|
129
|
|
- const res = await getDeptUserTree()
|
|
130
|
|
- departments.value = res.data
|
|
|
180
|
+ const res = await getDeptList({ deptType: props.deptType })
|
|
|
181
|
+ if (props.deptType === 'user') {
|
|
|
182
|
+ departments.value = res.data
|
|
|
183
|
+ } else {
|
|
|
184
|
+ departments.value = filterDeptTree(res.data, props.deptType)
|
|
|
185
|
+ }
|
|
131
|
186
|
})
|
|
132
|
187
|
onUnmounted(() => {
|
|
133
|
188
|
resetStyle()
|
|
134
|
189
|
})
|
|
135
|
190
|
|
|
136
|
191
|
defineExpose({
|
|
137
|
|
- getDefQuery () {
|
|
|
192
|
+ getDefQuery() {
|
|
138
|
193
|
return {
|
|
139
|
|
- personName: '',
|
|
140
|
194
|
...getTimeRange()
|
|
141
|
195
|
}
|
|
142
|
196
|
}
|
|
|
@@ -160,21 +214,25 @@ defineExpose({
|
|
160
|
214
|
gap: 10px;
|
|
161
|
215
|
flex-wrap: wrap;
|
|
162
|
216
|
margin-right: 40px;
|
|
163
|
|
- & > div {
|
|
|
217
|
+
|
|
|
218
|
+ &>div {
|
|
164
|
219
|
padding: 8px 24px;
|
|
165
|
220
|
border-radius: 28px;
|
|
166
|
221
|
font-weight: 500;
|
|
167
|
222
|
}
|
|
168
|
223
|
}
|
|
|
224
|
+
|
|
169
|
225
|
.primary {
|
|
170
|
226
|
background: linear-gradient(125deg, #2AB3E6, #9605FC);
|
|
171
|
227
|
color: #fff;
|
|
172
|
228
|
padding: 8px 24px;
|
|
173
|
229
|
}
|
|
|
230
|
+
|
|
174
|
231
|
.default {
|
|
175
|
232
|
background: #1C1936;
|
|
176
|
233
|
color: #4C4C93;
|
|
177
|
234
|
position: relative;
|
|
|
235
|
+
|
|
178
|
236
|
&::before {
|
|
179
|
237
|
content: '';
|
|
180
|
238
|
position: absolute;
|
|
|
@@ -186,12 +244,14 @@ defineExpose({
|
|
186
|
244
|
opacity: 0.5;
|
|
187
|
245
|
}
|
|
188
|
246
|
}
|
|
|
247
|
+
|
|
189
|
248
|
.custom-style-date-picker-wrap {
|
|
190
|
249
|
position: relative;
|
|
191
|
250
|
border-radius: 19px;
|
|
192
|
251
|
height: 38px;
|
|
193
|
252
|
padding: 0 !important;
|
|
194
|
253
|
--el-text-color-primary: #fff;
|
|
|
254
|
+
|
|
195
|
255
|
&::before {
|
|
196
|
256
|
content: '';
|
|
197
|
257
|
position: absolute;
|
|
|
@@ -207,53 +267,60 @@ defineExpose({
|
|
207
|
267
|
</style>
|
|
208
|
268
|
|
|
209
|
269
|
<style lang="scss">
|
|
210
|
|
- .custom-el-style {
|
|
211
|
|
- width:100%;
|
|
212
|
|
- padding: 10px;
|
|
213
|
|
- position: relative;
|
|
214
|
|
- background: #1c1936;
|
|
215
|
|
- border-radius: 8px;
|
|
216
|
|
- --el-text-color-regular: #fff;
|
|
217
|
|
- --el-fill-color-blank: #17122A;
|
|
218
|
|
- --el-border-color: linear-gradient(150deg, #0f46fa 0%, #bd03fb 100%);
|
|
219
|
|
- --el-border-color-hover: linear-gradient(150deg, #0f46fa 0%, #bd03fb 100%);
|
|
220
|
|
- .primary {
|
|
221
|
|
- background: linear-gradient(125deg, #2AB3E6, #9605FC);
|
|
222
|
|
- color: #fff;
|
|
223
|
|
- padding: 6px 20px;
|
|
224
|
|
- display: inline-block;
|
|
225
|
|
- margin-left: 15px;
|
|
226
|
|
- }
|
|
227
|
|
- &::before {
|
|
228
|
|
- content: '';
|
|
229
|
|
- position: absolute;
|
|
230
|
|
- inset: -2px;
|
|
231
|
|
- border-radius: 10px;
|
|
232
|
|
- background: linear-gradient(150deg, #0f46fa 0%, #0f46fa 10%, #020E15, #020E15, #020E15, #bd03fb 90%, #bd03fb 100%);
|
|
233
|
|
- filter: brightness(2) contrast(150%);
|
|
234
|
|
- z-index: -2;
|
|
235
|
|
- opacity: 0.5;
|
|
236
|
|
- }
|
|
237
|
|
- .el-input__wrapper {
|
|
238
|
|
- }
|
|
239
|
|
- .el-tree {
|
|
240
|
|
- background-color: #1c1936;
|
|
241
|
|
- color: #fff;
|
|
242
|
|
- .el-tree-node__content {
|
|
243
|
|
- --el-tree-node-hover-bg-color: #5c676d;
|
|
244
|
|
- }
|
|
245
|
|
- }
|
|
246
|
|
- }
|
|
247
|
|
- .el-autocomplete-suggestion {
|
|
248
|
|
- background: #17122A;
|
|
|
270
|
+.custom-el-style {
|
|
|
271
|
+ width: 100%;
|
|
|
272
|
+ padding: 10px;
|
|
|
273
|
+ position: relative;
|
|
|
274
|
+ background: #1c1936;
|
|
|
275
|
+ border-radius: 8px;
|
|
|
276
|
+ --el-text-color-regular: #fff;
|
|
|
277
|
+ --el-fill-color-blank: #17122A;
|
|
|
278
|
+ --el-border-color: linear-gradient(150deg, #0f46fa 0%, #bd03fb 100%);
|
|
|
279
|
+ --el-border-color-hover: linear-gradient(150deg, #0f46fa 0%, #bd03fb 100%);
|
|
|
280
|
+
|
|
|
281
|
+ .primary {
|
|
|
282
|
+ background: linear-gradient(125deg, #2AB3E6, #9605FC);
|
|
|
283
|
+ color: #fff;
|
|
|
284
|
+ padding: 6px 20px;
|
|
|
285
|
+ display: inline-block;
|
|
|
286
|
+ margin-left: 15px;
|
|
249
|
287
|
}
|
|
250
|
|
- .custom-style-date-picker {
|
|
251
|
|
- background: #1C1936 !important;
|
|
252
|
|
- box-shadow: none !important;
|
|
253
|
|
- height: 38px !important;
|
|
254
|
|
- border-radius: 19px;
|
|
|
288
|
+
|
|
|
289
|
+ &::before {
|
|
|
290
|
+ content: '';
|
|
|
291
|
+ position: absolute;
|
|
|
292
|
+ inset: -2px;
|
|
|
293
|
+ border-radius: 10px;
|
|
|
294
|
+ background: linear-gradient(150deg, #0f46fa 0%, #0f46fa 10%, #020E15, #020E15, #020E15, #bd03fb 90%, #bd03fb 100%);
|
|
|
295
|
+ filter: brightness(2) contrast(150%);
|
|
|
296
|
+ z-index: -2;
|
|
|
297
|
+ opacity: 0.5;
|
|
255
|
298
|
}
|
|
256
|
|
- .el-popper {
|
|
257
|
|
- --el-popover-padding: 0px;
|
|
|
299
|
+
|
|
|
300
|
+ .el-input__wrapper {}
|
|
|
301
|
+
|
|
|
302
|
+ .el-tree {
|
|
|
303
|
+ background-color: #1c1936;
|
|
|
304
|
+ color: #fff;
|
|
|
305
|
+
|
|
|
306
|
+ .el-tree-node__content {
|
|
|
307
|
+ --el-tree-node-hover-bg-color: #5c676d;
|
|
|
308
|
+ }
|
|
258
|
309
|
}
|
|
|
310
|
+}
|
|
|
311
|
+
|
|
|
312
|
+.el-autocomplete-suggestion {
|
|
|
313
|
+ background: #17122A;
|
|
|
314
|
+}
|
|
|
315
|
+
|
|
|
316
|
+.custom-style-date-picker {
|
|
|
317
|
+ background: #1C1936 !important;
|
|
|
318
|
+ box-shadow: none !important;
|
|
|
319
|
+ height: 38px !important;
|
|
|
320
|
+ border-radius: 19px;
|
|
|
321
|
+}
|
|
|
322
|
+
|
|
|
323
|
+.el-popper {
|
|
|
324
|
+ --el-popover-padding: 0px;
|
|
|
325
|
+}
|
|
259
|
326
|
</style>
|