|
|
@@ -20,13 +20,13 @@
|
|
20
|
20
|
<view v-if="selectedTimeTag === 4" class="date-range-picker">
|
|
21
|
21
|
<picker mode="date" :value="beginTime" @change="onBeginTimeChange">
|
|
22
|
22
|
<view class="date-input" :class="{ filled: beginTime }">
|
|
23
|
|
- {{ (beginTime || '').substring(0, 10) || '开始日期' }}
|
|
|
23
|
+ {{ beginTime || '开始日期' }}
|
|
24
|
24
|
</view>
|
|
25
|
25
|
</picker>
|
|
26
|
26
|
<text class="date-separator">至</text>
|
|
27
|
27
|
<picker mode="date" :value="endTime" @change="onEndTimeChange">
|
|
28
|
28
|
<view class="date-input" :class="{ filled: endTime }">
|
|
29
|
|
- {{ (endTime || '').substring(0, 10) || '结束日期' }}
|
|
|
29
|
+ {{ endTime || '结束日期' }}
|
|
30
|
30
|
</view>
|
|
31
|
31
|
</picker>
|
|
32
|
32
|
</view>
|
|
|
@@ -98,7 +98,8 @@
|
|
98
|
98
|
<view class="info-item">
|
|
99
|
99
|
<view class="info-label">标签:</view>
|
|
100
|
100
|
<view class="info-value" v-if="portrait.userTags">
|
|
101
|
|
- <text class="tag" v-for="tag in portrait.userTags.split(',')" :key="tag">{{ tag }}</text>
|
|
|
101
|
+ <text class="tag" v-for="tag in portrait.userTags.split(',')" :key="tag">{{ tag
|
|
|
102
|
+ }}</text>
|
|
102
|
103
|
</view>
|
|
103
|
104
|
</view>
|
|
104
|
105
|
</view>
|
|
|
@@ -146,7 +147,13 @@
|
|
146
|
147
|
</SectionTitle>
|
|
147
|
148
|
|
|
148
|
149
|
<SectionTitle v-if="activeTab === 'profile'" title="个人能力">
|
|
149
|
|
- <div class="chart-container" ref="radarChart"></div>
|
|
|
150
|
+ <div class="chart-legend">
|
|
|
151
|
+ <div class="legend-item legend-warning"><span></span>预警线(低于75分)</div>
|
|
|
152
|
+ <!-- <div class="legend-item legend-normal"><span></span>正常线(75~90分)</div> -->
|
|
|
153
|
+ <div class="legend-item legend-excellent"><span></span>优秀线(高于90分)</div>
|
|
|
154
|
+ <div class="legend-item legend-current"><span></span>当前员工分值</div>
|
|
|
155
|
+ </div>
|
|
|
156
|
+ <div class="chart-container" ref="radarChart" ></div>
|
|
150
|
157
|
</SectionTitle>
|
|
151
|
158
|
|
|
152
|
159
|
<SectionTitle v-if="activeTab === 'profile'" title="补充信息">
|
|
|
@@ -211,7 +218,7 @@
|
|
211
|
218
|
<view class="warning-score-item">
|
|
212
|
219
|
<text class="warning-score-label">综合得分</text>
|
|
213
|
220
|
<text class="warning-score-value" :class="scoreLevelClass">{{ portrait.totalScore || 0
|
|
214
|
|
- }}</text>
|
|
|
221
|
+ }}</text>
|
|
215
|
222
|
</view>
|
|
216
|
223
|
</view>
|
|
217
|
224
|
<view class="warning-detail" v-if="scoreDetails.length">
|
|
|
@@ -243,14 +250,8 @@
|
|
243
|
250
|
</view>
|
|
244
|
251
|
<scroll-view v-if="!employeeSearchKeyword.trim()" scroll-y class="tree-list">
|
|
245
|
252
|
<template v-for="(node, index) in deptTreeData">
|
|
246
|
|
- <employee-tree-node
|
|
247
|
|
- :key="node.id"
|
|
248
|
|
- :node="node"
|
|
249
|
|
- :expanded-ids="expandedDeptIds"
|
|
250
|
|
- :selected-id="selectedEmployeeId"
|
|
251
|
|
- @toggle="toggleDeptExpand"
|
|
252
|
|
- @select="onEmployeeSelect"
|
|
253
|
|
- />
|
|
|
253
|
+ <employee-tree-node :key="node.id" :node="node" :expanded-ids="expandedDeptIds"
|
|
|
254
|
+ :selected-id="selectedEmployeeId" @toggle="toggleDeptExpand" @select="onEmployeeSelect" />
|
|
254
|
255
|
</template>
|
|
255
|
256
|
</scroll-view>
|
|
256
|
257
|
<scroll-view v-else scroll-y class="employee-list">
|
|
|
@@ -269,6 +270,54 @@
|
|
269
|
270
|
</scroll-view>
|
|
270
|
271
|
</view>
|
|
271
|
272
|
</u-popup>
|
|
|
273
|
+
|
|
|
274
|
+ <!-- 雷达图tooltip -->
|
|
|
275
|
+ <u-popup :show="showRadarTooltipPopup" mode="center" :round="12"
|
|
|
276
|
+ :mask-close-able="true" @close="closeRadarPopup">
|
|
|
277
|
+
|
|
|
278
|
+ <div class="radar-tooltip-popup">
|
|
|
279
|
+ <div class="tooltip-card">
|
|
|
280
|
+ <!-- 标题 -->
|
|
|
281
|
+ <view class="tooltip-header">
|
|
|
282
|
+ <text class="tooltip-title">{{ activeDimName }}</text>
|
|
|
283
|
+ <u-icon name="close" color="#666666" size="20" @click="closeRadarPopup" />
|
|
|
284
|
+ </view>
|
|
|
285
|
+
|
|
|
286
|
+ <!-- 加分区域 -->
|
|
|
287
|
+ <div class="tooltip-section">
|
|
|
288
|
+ <div class="section-list">
|
|
|
289
|
+ <template v-if="addGroupList.length">
|
|
|
290
|
+ <div class="list-item" v-for="(item, i) in addGroupList" :key="i">
|
|
|
291
|
+ <span>{{ item.name }}:</span>
|
|
|
292
|
+ <span class="add-text">+{{ item.total }}分</span>
|
|
|
293
|
+ </div>
|
|
|
294
|
+ </template>
|
|
|
295
|
+ <div v-else class="p-empty">暂无加分记录</div>
|
|
|
296
|
+ </div>
|
|
|
297
|
+ <div class="section-total add">
|
|
|
298
|
+ <span>合计加分:</span>
|
|
|
299
|
+ <span>{{ addTotal }}分</span>
|
|
|
300
|
+ </div>
|
|
|
301
|
+ </div>
|
|
|
302
|
+ <!-- 扣分区域 -->
|
|
|
303
|
+ <div class="tooltip-section">
|
|
|
304
|
+ <div class="section-list">
|
|
|
305
|
+ <template v-if="deductGroupList.length">
|
|
|
306
|
+ <div class="list-item" v-for="(item, i) in deductGroupList" :key="i">
|
|
|
307
|
+ <span>{{ item.name }}:</span>
|
|
|
308
|
+ <span class="deduct-text">{{ item.total }}分</span>
|
|
|
309
|
+ </div>
|
|
|
310
|
+ </template>
|
|
|
311
|
+ <div v-else class="p-empty">暂无扣分记录</div>
|
|
|
312
|
+ </div>
|
|
|
313
|
+ <div class="section-total deduct">
|
|
|
314
|
+ <span>合计扣分:</span>
|
|
|
315
|
+ <span>{{ deductTotal }}分</span>
|
|
|
316
|
+ </div>
|
|
|
317
|
+ </div>
|
|
|
318
|
+ </div>
|
|
|
319
|
+ </div>
|
|
|
320
|
+ </u-popup>
|
|
272
|
321
|
</view>
|
|
273
|
322
|
</template>
|
|
274
|
323
|
|
|
|
@@ -329,7 +378,14 @@ export default {
|
|
329
|
378
|
employeeLoading: false,
|
|
330
|
379
|
expandedDeptIds: [],
|
|
331
|
380
|
isSecurityCheck: false,
|
|
332
|
|
- userInfo: null
|
|
|
381
|
+ userInfo: null,
|
|
|
382
|
+ // 雷达图tooltip相关
|
|
|
383
|
+ activeDimName: null,
|
|
|
384
|
+ radarTooltipPosition: { x: 0, y: 0 },
|
|
|
385
|
+ // 控制雷达图 tooltip popup 显示
|
|
|
386
|
+ showRadarTooltipPopup: false,
|
|
|
387
|
+ // 评分明细数据
|
|
|
388
|
+ allScoreDetails: []
|
|
333
|
389
|
}
|
|
334
|
390
|
},
|
|
335
|
391
|
computed: {
|
|
|
@@ -350,11 +406,6 @@ export default {
|
|
350
|
406
|
return age + '岁'
|
|
351
|
407
|
},
|
|
352
|
408
|
tagScoreDisplay() {
|
|
353
|
|
-
|
|
354
|
|
- // if (this.tagScoreData == null) return '0'
|
|
355
|
|
- // if (typeof this.tagScoreData === 'object') {
|
|
356
|
|
- // return this.tagScoreData.totalScore ?? this.tagScoreData.score ?? this.tagScoreData ?? '0'
|
|
357
|
|
- // }
|
|
358
|
409
|
return this.portrait?.userTags?.split(',').length || 0
|
|
359
|
410
|
},
|
|
360
|
411
|
scoreLevelClass() {
|
|
|
@@ -377,6 +428,39 @@ export default {
|
|
377
|
428
|
return this.employeeList.filter(item =>
|
|
378
|
429
|
(item.nickName || '').toLowerCase().includes(keyword)
|
|
379
|
430
|
)
|
|
|
431
|
+ },
|
|
|
432
|
+ // 雷达图tooltip相关计算
|
|
|
433
|
+ addList() {
|
|
|
434
|
+ const all = (this.allScoreDetails || []).filter(d => d.totalScore != null && Number(d.totalScore) > 0)
|
|
|
435
|
+ return this.activeDimName ? all.filter(d => d.dimensionName === this.activeDimName) : all
|
|
|
436
|
+ },
|
|
|
437
|
+ deductList() {
|
|
|
438
|
+ const all = (this.allScoreDetails || []).filter(d => d.totalScore != null && Number(d.totalScore) < 0)
|
|
|
439
|
+ return this.activeDimName ? all.filter(d => d.dimensionName === this.activeDimName) : all
|
|
|
440
|
+ },
|
|
|
441
|
+ addGroupList() {
|
|
|
442
|
+ const groups = {}
|
|
|
443
|
+ this.addList.forEach(d => {
|
|
|
444
|
+ const key = d.level2Name || '其他'
|
|
|
445
|
+ groups[key] = (groups[key] || 0) + Number(d.totalScore)
|
|
|
446
|
+ })
|
|
|
447
|
+ return Object.entries(groups).map(([name, total]) => ({ name, total: total.toFixed(2) }))
|
|
|
448
|
+ },
|
|
|
449
|
+ deductGroupList() {
|
|
|
450
|
+ const groups = {}
|
|
|
451
|
+ this.deductList.forEach(d => {
|
|
|
452
|
+ const key = d.level2Name || '其他'
|
|
|
453
|
+ groups[key] = (groups[key] || 0) + Number(d.totalScore)
|
|
|
454
|
+ })
|
|
|
455
|
+ return Object.entries(groups).map(([name, total]) => ({ name, total: total.toFixed(2) }))
|
|
|
456
|
+ },
|
|
|
457
|
+ addTotal() {
|
|
|
458
|
+ const s = this.addList.reduce((acc, d) => acc + Number(d.totalScore), 0)
|
|
|
459
|
+ return (s > 0 ? '+' : '') + s.toFixed(2)
|
|
|
460
|
+ },
|
|
|
461
|
+ deductTotal() {
|
|
|
462
|
+ const s = this.deductList.reduce((acc, d) => acc + Number(d.totalScore), 0)
|
|
|
463
|
+ return s.toFixed(2)
|
|
380
|
464
|
}
|
|
381
|
465
|
},
|
|
382
|
466
|
mounted() {
|
|
|
@@ -571,11 +655,11 @@ export default {
|
|
571
|
655
|
}
|
|
572
|
656
|
// 自动计算时间范围
|
|
573
|
657
|
const now = new Date()
|
|
574
|
|
- // 设置结束时间为今天的 23:59:59
|
|
575
|
|
- const endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59)
|
|
|
658
|
+ // 设置结束时间为今天
|
|
|
659
|
+ const endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
576
|
660
|
// 设置开始时间
|
|
577
|
661
|
let beginTime
|
|
578
|
|
- switch(index) {
|
|
|
662
|
+ switch (index) {
|
|
579
|
663
|
case 0: // 近一周
|
|
580
|
664
|
beginTime = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
|
|
581
|
665
|
break
|
|
|
@@ -591,26 +675,17 @@ export default {
|
|
591
|
675
|
default:
|
|
592
|
676
|
beginTime = now
|
|
593
|
677
|
}
|
|
594
|
|
- // 格式化日期为 YYYY-MM-DD HH:mm:ss
|
|
595
|
|
- this.beginTime = this.formatFullDate(beginTime)
|
|
596
|
|
- this.endTime = this.formatFullDate(endTime)
|
|
|
678
|
+ // 格式化日期为 YYYY-MM-DD
|
|
|
679
|
+ this.beginTime = this.formatDate(beginTime)
|
|
|
680
|
+ this.endTime = this.formatDate(endTime)
|
|
597
|
681
|
// 选择时间标签后立即查询
|
|
598
|
682
|
if (this.selectedEmployeeId) {
|
|
599
|
683
|
this.fetchEmployeePortrait()
|
|
600
|
684
|
}
|
|
601
|
685
|
},
|
|
602
|
|
- formatFullDate(d) {
|
|
603
|
|
- const y = d.getFullYear()
|
|
604
|
|
- const m = String(d.getMonth() + 1).padStart(2, '0')
|
|
605
|
|
- const day = String(d.getDate()).padStart(2, '0')
|
|
606
|
|
- const h = String(d.getHours()).padStart(2, '0')
|
|
607
|
|
- const min = String(d.getMinutes()).padStart(2, '0')
|
|
608
|
|
- const s = String(d.getSeconds()).padStart(2, '0')
|
|
609
|
|
- return `${y}-${m}-${day} ${h}:${min}:${s}`
|
|
610
|
|
- },
|
|
611
|
686
|
onBeginTimeChange(e) {
|
|
612
|
687
|
const dateStr = e.detail.value
|
|
613
|
|
- this.beginTime = dateStr + ' 00:00:00'
|
|
|
688
|
+ this.beginTime = dateStr
|
|
614
|
689
|
// 自定义时间选择后立即查询
|
|
615
|
690
|
if (this.selectedEmployeeId && this.endTime) {
|
|
616
|
691
|
this.fetchEmployeePortrait()
|
|
|
@@ -618,7 +693,7 @@ export default {
|
|
618
|
693
|
},
|
|
619
|
694
|
onEndTimeChange(e) {
|
|
620
|
695
|
const dateStr = e.detail.value
|
|
621
|
|
- this.endTime = dateStr + ' 23:59:59'
|
|
|
696
|
+ this.endTime = dateStr
|
|
622
|
697
|
// 自定义时间选择后立即查询
|
|
623
|
698
|
if (this.selectedEmployeeId && this.beginTime) {
|
|
624
|
699
|
this.fetchEmployeePortrait()
|
|
|
@@ -656,12 +731,13 @@ export default {
|
|
656
|
731
|
})
|
|
657
|
732
|
// 只取数组中最后一个元素的 scoreDetails
|
|
658
|
733
|
const allScoreDetails = res.data.scoreDetails || []
|
|
|
734
|
+ this.allScoreDetails = allScoreDetails
|
|
659
|
735
|
this.scoreDetails = allScoreDetails.length > 0 ? allScoreDetails[allScoreDetails.length - 1] : []
|
|
660
|
736
|
}
|
|
661
|
737
|
}).catch(() => { })
|
|
662
|
738
|
|
|
663
|
739
|
const tagPromise = countTagScore(params).then(res => {
|
|
664
|
|
-
|
|
|
740
|
+
|
|
665
|
741
|
const data = res.data
|
|
666
|
742
|
if (Array.isArray(data)) {
|
|
667
|
743
|
const found = data.find(item => item.userId === this.selectedEmployeeId)
|
|
|
@@ -673,21 +749,21 @@ export default {
|
|
673
|
749
|
|
|
674
|
750
|
Promise.all([portraitPromise, tagPromise]).finally(() => {
|
|
675
|
751
|
this.$nextTick(() => {
|
|
676
|
|
-
|
|
|
752
|
+
|
|
677
|
753
|
this.initRadarChart()
|
|
678
|
754
|
this.initScoreChart()
|
|
679
|
755
|
})
|
|
680
|
756
|
})
|
|
681
|
757
|
},
|
|
682
|
758
|
initScoreChart() {
|
|
683
|
|
-
|
|
|
759
|
+
|
|
684
|
760
|
if (!this.$refs.scoreCircle) return
|
|
685
|
761
|
if (this.scoreChartInstance) {
|
|
686
|
762
|
this.scoreChartInstance.dispose()
|
|
687
|
763
|
}
|
|
688
|
764
|
this.scoreChartInstance = echarts.init(this.$refs.scoreCircle)
|
|
689
|
765
|
const score = this.portrait.totalScore || 0
|
|
690
|
|
-
|
|
|
766
|
+
|
|
691
|
767
|
const option = {
|
|
692
|
768
|
series: [
|
|
693
|
769
|
{
|
|
|
@@ -757,58 +833,113 @@ export default {
|
|
757
|
833
|
this.scoreChartInstance.setOption(option)
|
|
758
|
834
|
},
|
|
759
|
835
|
initRadarChart() {
|
|
760
|
|
-
|
|
|
836
|
+
|
|
761
|
837
|
if (!this.$refs.radarChart) return
|
|
762
|
838
|
if (this.radarChartInstance) {
|
|
763
|
839
|
this.radarChartInstance.dispose()
|
|
764
|
840
|
}
|
|
765
|
841
|
this.radarChartInstance = echarts.init(this.$refs.radarChart)
|
|
766
|
842
|
const dimensions = this.portrait.dimensions || []
|
|
767
|
|
- const maxScore = dimensions.length > 0 ? Math.max(...dimensions.map(d => d.score || 0)) : 100
|
|
768
|
|
- const indicator = dimensions.map(d => ({
|
|
769
|
|
- name: d.name + '\n' + d.score,
|
|
770
|
|
- max: maxScore
|
|
771
|
|
- }))
|
|
|
843
|
+
|
|
|
844
|
+ // 仿照 index copy.vue 的配置
|
|
|
845
|
+ const radarData = {
|
|
|
846
|
+ grounp: dimensions.map(d => ({ name: d.name + '\n\n' + d.score, max: 100 })),
|
|
|
847
|
+ data: [{
|
|
|
848
|
+ name: '个人能力',
|
|
|
849
|
+ value: dimensions.map(attr => attr.score),
|
|
|
850
|
+ symbolSize: 10,
|
|
|
851
|
+ areaStyle: {
|
|
|
852
|
+ show: false,
|
|
|
853
|
+ opacity: 0
|
|
|
854
|
+ },
|
|
|
855
|
+ lineStyle: {
|
|
|
856
|
+ color: '#4DC8FE',
|
|
|
857
|
+ width: 1
|
|
|
858
|
+ },
|
|
|
859
|
+ itemStyle: { color: '#fff', borderWidth: 1, borderColor: '#00C8DA', borderJoin: 'round' }
|
|
|
860
|
+ }]
|
|
|
861
|
+ }
|
|
|
862
|
+
|
|
772
|
863
|
const option = {
|
|
773
|
864
|
radar: {
|
|
774
|
|
- indicator: indicator,
|
|
|
865
|
+ indicator: radarData.grounp,
|
|
775
|
866
|
center: ['50%', '52%'],
|
|
776
|
|
- radius: '60%',
|
|
|
867
|
+ radius: '50%',
|
|
777
|
868
|
splitNumber: 8,
|
|
778
|
|
- axisLine: {
|
|
779
|
|
- lineStyle: { color: 'rgba(0,0,0,0.15)' }
|
|
780
|
|
- },
|
|
781
|
|
- splitLine: {
|
|
782
|
|
- lineStyle: {
|
|
783
|
|
- color: ['rgba(0,0,0,0.1)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0.1)', 'rgba(0,0,0,0.1)', '#fe4322', '#8EC742', 'rgba(0,0,0,0.1)']
|
|
784
|
|
- }
|
|
785
|
|
- },
|
|
|
869
|
+ axisLine: { lineStyle: { color: '#ccc' } },
|
|
|
870
|
+ splitLine: { lineStyle: { color: ['#ccc', '#ccc', '#ccc', '#ccc', '#ccc', '#ccc', '#fe4322', '#8EC742', '#ccc'], width: 1 } },
|
|
786
|
871
|
splitArea: { show: false },
|
|
787
|
872
|
axisName: {
|
|
788
|
873
|
color: '#333',
|
|
789
|
874
|
fontSize: 12
|
|
790
|
875
|
}
|
|
791
|
876
|
},
|
|
792
|
|
- series: [{
|
|
793
|
|
- type: 'radar',
|
|
794
|
|
- data: [{
|
|
795
|
|
- name: '个人能力',
|
|
796
|
|
- value: dimensions.map(d => d.score),
|
|
797
|
|
- areaStyle: { color: 'rgba(77, 200, 254, 0.2)' },
|
|
798
|
|
- lineStyle: { color: '#4DC8FE', width: 2 },
|
|
799
|
|
- itemStyle: {
|
|
800
|
|
- color: '#333',
|
|
801
|
|
- borderWidth: 1,
|
|
802
|
|
- borderColor: '#00C8DA'
|
|
803
|
|
- },
|
|
|
877
|
+ series: [
|
|
|
878
|
+ {
|
|
|
879
|
+ type: 'radar',
|
|
|
880
|
+ data: radarData.data,
|
|
804
|
881
|
symbol: 'circle',
|
|
805
|
|
- symbolSize: 8
|
|
806
|
|
- }]
|
|
807
|
|
- }]
|
|
|
882
|
+ symbolSize: 13,
|
|
|
883
|
+ label: {
|
|
|
884
|
+ show: false,
|
|
|
885
|
+ formatter: (p) => p.value,
|
|
|
886
|
+ color: '#333',
|
|
|
887
|
+ fontSize: 16,
|
|
|
888
|
+ fontWeight: 'bold'
|
|
|
889
|
+ }
|
|
|
890
|
+ }
|
|
|
891
|
+ ]
|
|
808
|
892
|
}
|
|
|
893
|
+
|
|
809
|
894
|
this.radarChartInstance.setOption(option)
|
|
|
895
|
+
|
|
|
896
|
+ // 绑定鼠标事件
|
|
|
897
|
+ this.bindRadarEvents()
|
|
|
898
|
+ },
|
|
|
899
|
+ bindRadarEvents() {
|
|
|
900
|
+ if (!this.radarChartInstance || !this.$refs.radarChart) return
|
|
|
901
|
+
|
|
|
902
|
+ this.radarChartInstance.off('click')
|
|
|
903
|
+
|
|
|
904
|
+ this.radarChartInstance.on('click', (params) => {
|
|
|
905
|
+ if (!Array.isArray(this.portrait.dimensions) || !this.portrait.dimensions.length) return
|
|
|
906
|
+
|
|
|
907
|
+ const rect = this.$refs.radarChart.getBoundingClientRect()
|
|
|
908
|
+ if (!rect) return
|
|
|
909
|
+
|
|
|
910
|
+ const cx = rect.width / 2
|
|
|
911
|
+ const cy = rect.height / 2
|
|
|
912
|
+ const dx = params.event.offsetX - cx
|
|
|
913
|
+ const dy = params.event.offsetY - cy
|
|
|
914
|
+ const distance = Math.sqrt(dx * dx + dy * dy)
|
|
|
915
|
+ const radarRadius = rect.width * 0.35 // 对应 radius: 65%
|
|
|
916
|
+
|
|
|
917
|
+ if (distance > radarRadius) {
|
|
|
918
|
+ return
|
|
|
919
|
+ }
|
|
|
920
|
+
|
|
|
921
|
+ // 角度计算
|
|
|
922
|
+ let angle = Math.atan2(dx, -dy) * (180 / Math.PI)
|
|
|
923
|
+ if (angle < 0) angle += 360
|
|
|
924
|
+ const count = this.portrait.dimensions.length
|
|
|
925
|
+ const step = 360 / count
|
|
|
926
|
+ let idx = Math.abs(Math.round(angle / step) % count - count)
|
|
|
927
|
+ if (idx < 0) idx += count
|
|
|
928
|
+ if (idx >= count) idx = 0
|
|
|
929
|
+
|
|
|
930
|
+ // 显示tooltip popup - 加上小延迟避免 u-popup 立即关闭的问题
|
|
|
931
|
+ this.activeDimName = this.portrait.dimensions[idx].name
|
|
|
932
|
+ setTimeout(() => {
|
|
|
933
|
+ this.showRadarTooltipPopup = true
|
|
|
934
|
+ }, 50)
|
|
|
935
|
+ })
|
|
|
936
|
+ },
|
|
|
937
|
+ // 关闭雷达图 tooltip popup
|
|
|
938
|
+ closeRadarPopup() {
|
|
|
939
|
+ this.showRadarTooltipPopup = false
|
|
810
|
940
|
}
|
|
811
|
941
|
}
|
|
|
942
|
+
|
|
812
|
943
|
}
|
|
813
|
944
|
</script>
|
|
814
|
945
|
|
|
|
@@ -1007,7 +1138,7 @@ export default {
|
|
1007
|
1138
|
border-bottom: 2rpx solid transparent;
|
|
1008
|
1139
|
transition: all 0.3s;
|
|
1009
|
1140
|
|
|
1010
|
|
- &.active {
|
|
|
1141
|
+ &.active {
|
|
1011
|
1142
|
color: #333;
|
|
1012
|
1143
|
border-bottom-color: #333;
|
|
1013
|
1144
|
}
|
|
|
@@ -1207,6 +1338,63 @@ export default {
|
|
1207
|
1338
|
height: 500rpx;
|
|
1208
|
1339
|
}
|
|
1209
|
1340
|
|
|
|
1341
|
+.chart-legend {
|
|
|
1342
|
+ display: flex;
|
|
|
1343
|
+ justify-content: center;
|
|
|
1344
|
+ align-items: center;
|
|
|
1345
|
+ flex-wrap: wrap;
|
|
|
1346
|
+ gap: 10px 18px;
|
|
|
1347
|
+ padding-top: 8px;
|
|
|
1348
|
+ color: #fff;
|
|
|
1349
|
+ font-size: 14px;
|
|
|
1350
|
+
|
|
|
1351
|
+}
|
|
|
1352
|
+
|
|
|
1353
|
+.legend-item {
|
|
|
1354
|
+ display: flex;
|
|
|
1355
|
+ align-items: center;
|
|
|
1356
|
+ gap: 6rpx;
|
|
|
1357
|
+
|
|
|
1358
|
+ span {
|
|
|
1359
|
+ width: 24rpx;
|
|
|
1360
|
+ height: 10rpx;
|
|
|
1361
|
+ border: 2rpx solid currentColor;
|
|
|
1362
|
+ border-radius: 2rpx;
|
|
|
1363
|
+ }
|
|
|
1364
|
+}
|
|
|
1365
|
+
|
|
|
1366
|
+.legend-warning {
|
|
|
1367
|
+ color: #fe4322;
|
|
|
1368
|
+
|
|
|
1369
|
+ span {
|
|
|
1370
|
+ background-color: #fe4322;
|
|
|
1371
|
+ }
|
|
|
1372
|
+}
|
|
|
1373
|
+
|
|
|
1374
|
+.legend-normal {
|
|
|
1375
|
+ color: black;
|
|
|
1376
|
+
|
|
|
1377
|
+ span {
|
|
|
1378
|
+ background-color: gray;
|
|
|
1379
|
+ }
|
|
|
1380
|
+}
|
|
|
1381
|
+
|
|
|
1382
|
+.legend-excellent {
|
|
|
1383
|
+ color: #8EC742;
|
|
|
1384
|
+
|
|
|
1385
|
+ span {
|
|
|
1386
|
+ background-color: #8EC742;
|
|
|
1387
|
+ }
|
|
|
1388
|
+}
|
|
|
1389
|
+
|
|
|
1390
|
+.legend-current {
|
|
|
1391
|
+ color: #1890ff;
|
|
|
1392
|
+
|
|
|
1393
|
+ span {
|
|
|
1394
|
+ background-color: #1890ff;
|
|
|
1395
|
+ }
|
|
|
1396
|
+}
|
|
|
1397
|
+
|
|
1210
|
1398
|
.supp-grid {
|
|
1211
|
1399
|
display: grid;
|
|
1212
|
1400
|
grid-template-columns: 1fr 1fr;
|
|
|
@@ -1378,4 +1566,72 @@ export default {
|
|
1378
|
1566
|
}
|
|
1379
|
1567
|
}
|
|
1380
|
1568
|
}
|
|
|
1569
|
+
|
|
|
1570
|
+.radar-tooltip-popup {
|
|
|
1571
|
+ padding: 20rpx;
|
|
|
1572
|
+ min-width: 300px;
|
|
|
1573
|
+
|
|
|
1574
|
+ .p-empty {
|
|
|
1575
|
+ text-align: center;
|
|
|
1576
|
+ margin-top: 10rpx;
|
|
|
1577
|
+ font-size: 24rpx;
|
|
|
1578
|
+ color: #999;
|
|
|
1579
|
+ }
|
|
|
1580
|
+
|
|
|
1581
|
+ .tooltip-header {
|
|
|
1582
|
+ display: flex;
|
|
|
1583
|
+ justify-content: space-between;
|
|
|
1584
|
+ align-items: center;
|
|
|
1585
|
+ padding: 0 10rpx 20rpx;
|
|
|
1586
|
+ border-bottom: 1rpx solid #eee;
|
|
|
1587
|
+ margin-bottom: 20rpx;
|
|
|
1588
|
+
|
|
|
1589
|
+ .tooltip-title {
|
|
|
1590
|
+ font-size: 32rpx;
|
|
|
1591
|
+ font-weight: bold;
|
|
|
1592
|
+ color: #333;
|
|
|
1593
|
+ }
|
|
|
1594
|
+ }
|
|
|
1595
|
+
|
|
|
1596
|
+ .tooltip-section {
|
|
|
1597
|
+ padding: 0 10rpx;
|
|
|
1598
|
+ margin-bottom: 16rpx;
|
|
|
1599
|
+ }
|
|
|
1600
|
+
|
|
|
1601
|
+ .list-item {
|
|
|
1602
|
+ margin-top: 8rpx;
|
|
|
1603
|
+ display: flex;
|
|
|
1604
|
+ align-items: center;
|
|
|
1605
|
+ justify-content: space-between;
|
|
|
1606
|
+ font-size: 26rpx;
|
|
|
1607
|
+ color: #333;
|
|
|
1608
|
+
|
|
|
1609
|
+ .deduct-text {
|
|
|
1610
|
+ color: #ff4d4f;
|
|
|
1611
|
+ }
|
|
|
1612
|
+
|
|
|
1613
|
+ .add-text {
|
|
|
1614
|
+ color: #00b42a;
|
|
|
1615
|
+ }
|
|
|
1616
|
+ }
|
|
|
1617
|
+
|
|
|
1618
|
+ .section-total {
|
|
|
1619
|
+ margin-top: 12rpx;
|
|
|
1620
|
+ padding-top: 12rpx;
|
|
|
1621
|
+ border-top: 1rpx solid #f0f0f0;
|
|
|
1622
|
+ display: flex;
|
|
|
1623
|
+ align-items: center;
|
|
|
1624
|
+ justify-content: space-between;
|
|
|
1625
|
+ font-weight: 500;
|
|
|
1626
|
+ font-size: 28rpx;
|
|
|
1627
|
+
|
|
|
1628
|
+ &.deduct {
|
|
|
1629
|
+ color: #ff4d4f;
|
|
|
1630
|
+ }
|
|
|
1631
|
+
|
|
|
1632
|
+ &.add {
|
|
|
1633
|
+ color: #00b42a;
|
|
|
1634
|
+ }
|
|
|
1635
|
+ }
|
|
|
1636
|
+}
|
|
1381
|
1637
|
</style>
|