|
@@ -1,5 +1,5 @@
|
|
<template>
|
|
<template>
|
|
- <div class="personnel-compare-view full">
|
|
|
|
|
|
+ <div class="personnel-compare-view">
|
|
<div class="p-l-base p-r-base p-t-medium-base fill-blank filter-form" style="padding-bottom: 10px">
|
|
<div class="p-l-base p-r-base p-t-medium-base fill-blank filter-form" style="padding-bottom: 10px">
|
|
<base-form size="small" :label-width="'88px'" :model="model" :items="items">
|
|
<base-form size="small" :label-width="'88px'" :model="model" :items="items">
|
|
<template #form-item-button-group>
|
|
<template #form-item-button-group>
|
|
@@ -7,17 +7,246 @@
|
|
</template>
|
|
</template>
|
|
</base-form>
|
|
</base-form>
|
|
</div>
|
|
</div>
|
|
- <div class="flex-1 p-small"></div>
|
|
|
|
|
|
+ <div v-loading="loading" class="p-small">
|
|
|
|
+ <el-radio-group v-model="dataType">
|
|
|
|
+ <el-radio-button v-for="type in dataTypeValues" :key="type" :label="type">
|
|
|
|
+ {{ dataTypeLabelMap[type] }}
|
|
|
|
+ </el-radio-button>
|
|
|
|
+ </el-radio-group>
|
|
|
|
+ <div class="m-t-small">
|
|
|
|
+ <base-table
|
|
|
|
+ v-if="dataType !== 'segmentScores'"
|
|
|
|
+ ref="tableRef1"
|
|
|
|
+ border
|
|
|
|
+ stripe
|
|
|
|
+ size="small"
|
|
|
|
+ :columns="columns"
|
|
|
|
+ :data="allTableData"
|
|
|
|
+ :height="'500px'"
|
|
|
|
+ highlight-current-row
|
|
|
|
+ >
|
|
|
|
+ </base-table>
|
|
|
|
+ <base-table
|
|
|
|
+ v-else
|
|
|
|
+ ref="tableRef2"
|
|
|
|
+ border
|
|
|
|
+ stripe
|
|
|
|
+ size="small"
|
|
|
|
+ :columns="columns2"
|
|
|
|
+ :data="allTableData"
|
|
|
|
+ :height="'500px'"
|
|
|
|
+ highlight-current-row
|
|
|
|
+ >
|
|
|
|
+ </base-table>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-if="allTableData.length" class="m-t-small out-chart-box">
|
|
|
|
+ <div v-if="dataType !== 'segmentScores'" class="chart-box">
|
|
|
|
+ <vue-e-charts class="full" :option="lineChartOptions"></vue-e-charts>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else class="chart-box">
|
|
|
|
+ <vue-e-charts class="full" :option="multLineChartOptions"></vue-e-charts>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
<script setup lang="ts" name="PersonnelCompare">
|
|
<script setup lang="ts" name="PersonnelCompare">
|
|
|
|
+import { ref, reactive, computed, watch } from 'vue'
|
|
import BaseForm from '@/components/element/BaseForm.vue'
|
|
import BaseForm from '@/components/element/BaseForm.vue'
|
|
-import { ElButton } from 'element-plus'
|
|
|
|
|
|
+import useFetch from '@/hooks/useFetch'
|
|
|
|
+import BaseTable from '@/components/element/BaseTable.vue'
|
|
|
|
+import { ElButton, ElRadioButton, ElRadioGroup } from 'element-plus'
|
|
import useCompareFilter from './hooks/useCompareFilter'
|
|
import useCompareFilter from './hooks/useCompareFilter'
|
|
|
|
+import VueECharts from 'vue-echarts'
|
|
|
|
+
|
|
|
|
+const dataType = ref('avg')
|
|
|
|
+const dataTypeValues = ['avg', 'std', 'segmentScores', 'markingCount', 'xyRelate']
|
|
|
|
+const dataTypeLabelMap = reactive<any>({
|
|
|
|
+ avg: '平均分',
|
|
|
|
+ std: '标准差',
|
|
|
|
+ segmentScores: '给分分布',
|
|
|
|
+ markingCount: '工作量',
|
|
|
|
+ xyRelate: '相关系数',
|
|
|
|
+})
|
|
|
|
+const multLineXdatas = ref([])
|
|
const { model, fetchModel, items, onOptionInit } = useCompareFilter()
|
|
const { model, fetchModel, items, onOptionInit } = useCompareFilter()
|
|
|
|
|
|
|
|
+const { fetch, result, loading } = useFetch('getCompareList')
|
|
|
|
+const averageDatas = computed(() => {
|
|
|
|
+ if (result.value) {
|
|
|
|
+ let data = result.value.groups.map((item: any) => {
|
|
|
|
+ return {
|
|
|
|
+ markingGroupNumber: item.markingGroupNumber,
|
|
|
|
+ avg: item.avg,
|
|
|
|
+ avgMarkingCount: item.avgMarkingCount,
|
|
|
|
+ std: item.std,
|
|
|
|
+ xyRelate: item.xyRelate,
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ return data
|
|
|
|
+ } else {
|
|
|
|
+ return []
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+const allTableData = computed(() => {
|
|
|
|
+ if (result.value) {
|
|
|
|
+ let arr = []
|
|
|
|
+ for (let i = 0; i < result.value.groups.length; i++) {
|
|
|
|
+ let g = result.value.groups[i]
|
|
|
|
+ arr.push(...g.markerCompares)
|
|
|
|
+ }
|
|
|
|
+ return arr
|
|
|
|
+ } else {
|
|
|
|
+ return []
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+watch(allTableData, () => {
|
|
|
|
+ if (!multLineXdatas.value.length) {
|
|
|
|
+ multLineXdatas.value = allTableData.value[0].segmentScores.map((item: any) => {
|
|
|
|
+ return item.scoreStart
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+const columns = computed(() => {
|
|
|
|
+ return [
|
|
|
|
+ { label: '账号', prop: 'loginName', align: 'center', minWidth: 120, fixed: 'left' },
|
|
|
|
+ { label: '姓名', prop: 'markerName', align: 'center', minWidth: 120, fixed: 'left' },
|
|
|
|
+ ...(result.value || { columns: [] }).columns.map((d: any) => {
|
|
|
|
+ return {
|
|
|
|
+ label: d,
|
|
|
|
+ align: 'center',
|
|
|
|
+ formatter(row: any) {
|
|
|
|
+ let find = row.dateItems.find((v: any) => v.date === d)
|
|
|
|
+ return find ? find[dataType.value] : ''
|
|
|
|
+ },
|
|
|
|
+ sortMethod: function (a: any, b: any) {
|
|
|
|
+ let aValue = a.dateItems.find((v: any) => v.date === d)[dataType.value] || 0
|
|
|
|
+ let bValue = b.dateItems.find((v: any) => v.date === d)[dataType.value] || 0
|
|
|
|
+ return aValue - bValue
|
|
|
|
+ },
|
|
|
|
+ minWidth: 100,
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ ]
|
|
|
|
+})
|
|
|
|
+const columns2: any = computed(() => {
|
|
|
|
+ let initColumns = [
|
|
|
|
+ { label: '账号', prop: 'loginName', align: 'center', minWidth: 120, fixed: 'left' },
|
|
|
|
+ { label: '姓名', prop: 'markerName', align: 'center', minWidth: 120, fixed: 'left' },
|
|
|
|
+ ]
|
|
|
|
+ if (allTableData.value.length) {
|
|
|
|
+ let pushColumns = allTableData.value[0].segmentScores.map((item: any) => {
|
|
|
|
+ return {
|
|
|
|
+ label: item.scoreStart,
|
|
|
|
+ align: 'center',
|
|
|
|
+ formatter(row: any) {
|
|
|
|
+ return row.segmentScores.find((v: any) => v.scoreStart == item.scoreStart).rate
|
|
|
|
+ },
|
|
|
|
+ sortMethod: function (a: any, b: any) {
|
|
|
|
+ let aRate = a.segmentScores.find((v: any) => v.scoreStart === item.scoreStart)?.rate
|
|
|
|
+ let bRate = b.segmentScores.find((v: any) => v.scoreStart === item.scoreStart)?.rate
|
|
|
|
+ return aRate - bRate
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ initColumns.push(...pushColumns)
|
|
|
|
+ }
|
|
|
|
+ return initColumns
|
|
|
|
+})
|
|
|
|
+const lineChartOptions = computed(() => {
|
|
|
|
+ let xData = allTableData.value.map((item) => item.loginName)
|
|
|
|
+ return {
|
|
|
|
+ xAxis: {
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
+ axisTick: { show: false },
|
|
|
|
+ splitLine: { show: false },
|
|
|
|
+ axisLabel: {
|
|
|
|
+ align: 'right',
|
|
|
|
+ },
|
|
|
|
+ data: xData,
|
|
|
|
+ },
|
|
|
|
+ yAxis: [
|
|
|
|
+ {
|
|
|
|
+ type: 'value',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: 'value',
|
|
|
|
+ // axisLabel: {
|
|
|
|
+ // formatter: `{value}%`,
|
|
|
|
+ // },
|
|
|
|
+ splitLine: { show: false },
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ series: [
|
|
|
|
+ {
|
|
|
|
+ name: dataTypeLabelMap[dataType.value],
|
|
|
|
+ type: 'line',
|
|
|
|
+ barWidth: 20,
|
|
|
|
+ itemStyle: {
|
|
|
|
+ color: '#3AD500',
|
|
|
|
+ },
|
|
|
|
+ data: allTableData.value.map((item) => item[dataType.value]),
|
|
|
|
+ markLine: {
|
|
|
|
+ data: averageDatas.value.map((item: any) => {
|
|
|
|
+ return {
|
|
|
|
+ name: item.markingGroupNumber == 0 ? '总体平均分' : `小组${item.markingGroupNumber}平均分`,
|
|
|
|
+ yAxis: item[dataType.value === 'markingCount' ? 'avgMarkingCount' : dataType.value],
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+const multLineChartOptions = computed(() => {
|
|
|
|
+ return {
|
|
|
|
+ xAxis: {
|
|
|
|
+ axisLine: { show: false },
|
|
|
|
+ axisTick: { show: false },
|
|
|
|
+ splitLine: { show: false },
|
|
|
|
+ axisLabel: {
|
|
|
|
+ align: 'right',
|
|
|
|
+ },
|
|
|
|
+ data: multLineXdatas,
|
|
|
|
+ },
|
|
|
|
+ yAxis: [
|
|
|
|
+ {
|
|
|
|
+ type: 'value',
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: 'value',
|
|
|
|
+ splitLine: { show: false },
|
|
|
|
+ },
|
|
|
|
+ ],
|
|
|
|
+ series: allTableData.value.map((item: any) => {
|
|
|
|
+ return {
|
|
|
|
+ name: item.loginName,
|
|
|
|
+ type: 'line',
|
|
|
|
+ barWidth: 20,
|
|
|
|
+ // itemStyle: {
|
|
|
|
+ // color: '#3AD500',
|
|
|
|
+ // },
|
|
|
|
+ data: item.segmentScores.map((v: any) => v.rate),
|
|
|
|
+ }
|
|
|
|
+ }),
|
|
|
|
+ }
|
|
|
|
+})
|
|
const onSearch = () => {
|
|
const onSearch = () => {
|
|
console.log('search')
|
|
console.log('search')
|
|
|
|
+ fetch(fetchModel.value).then((res) => {
|
|
|
|
+ console.log('rrr', result.value)
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
+onOptionInit(onSearch)
|
|
</script>
|
|
</script>
|
|
-<style scoped lang="scss"></style>
|
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.personnel-compare-view {
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ .out-chart-box {
|
|
|
|
+ height: 300px;
|
|
|
|
+ }
|
|
|
|
+ .chart-box {
|
|
|
|
+ height: 300px;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|