1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177 |
- <template>
- <div style="height: 100%;" :class="{ bg_fff: skeletonLoad }">
- <van-nav-bar title="结果分析" left-text="返回" left-arrow @click-left="$route_back" />
- <VanSkeleton :skeLoad="skeletonLoad" v-if="isYou">
- <template>
- <header>
- <div style="border-bottom: 1px solid #f1f1f1;" class="selector flex-box-ce flex-center-center" @click="openPanel()">
- <icon name="YMPicker_item_icon" style="margin-right: 6px;width: 0.3rem;height: 0.3rem;" class="fontColorC"></icon>
- <div>{{ paramsText }}</div>
- <van-icon name="arrow-down" />
- </div>
- </header>
- <scroller ref="me_scroller" class="all">
- <div style="padding-bottom: 1.5rem;">
- <div class="statementFoot">
- <van-tabs v-model="active" @change="statementTabs">
- <van-tab v-for="(item, index) in statementVanTabs" :key="index" :title="item.name"></van-tab>
- </van-tabs>
- <!-- 等级分布 -->
- <div class="statmentAnalysePie" v-show="active == 0">
- <div style="width: 7.5rem; height: 5rem;" id="statmentAnalysePie" ref="statmentAnalysePie"></div>
- <div class="PiePropNum">
- <div>总人数</div>
- <div>{{ userTotal }}人</div>
- </div>
- </div>
- <!-- 正态分布 -->
- <div v-show="active == 1">
- <div class="statementHnum">
- <div class="Hnumvfor">
- <span class="smHnLtit">总人数</span>
- <br />
- <span class="smHnLnum">{{ userTotal }}</span>
- <br />
- <span{{ userComplete }}人已完成</span>
- </div>
- <div v-for="(item, index) in scoreList" class="Hnumvfor" :key="index">
- <span class="smHnLtit">{{ item.name }}</span>
- <br />
- <span class="smHnLnum">{{users.filter(user => user.scoreResult === item.name).length}}</span>
- <br />
- </div>
- </div>
- </div>
- <div>
- <div>
- <!-- <van-search placeholder="请输入姓名" v-model="keyword" @input="keyVal()" /> -->
- <div class="flex-box-ce" style="border-bottom: 0.02rem solid #f1f1f1;">
- <div class="selectItem flex-1 font-flex-word fontColorC" style="border-right: 0.02rem solid #f1f1f1;" @click="showDept = true">
- <span>{{ deptName }}</span>
- <van-icon name="arrow-down" size="12"/>
- </div>
- <div class="selectItem flex-1 font-flex-word fontColorC" @click="showStatus = true">
- <span>{{ statusName }}</span>
- <van-icon name="arrow-down" size="12"/>
- </div>
- </div>
- <ol v-if="filterUsers && filterUsers.length > 0">
- <li @click="openDetail(item)" v-for="(item, index) in filterUsers" :key="index" class="flex-ce-box flex-d-center statmentperson" :style="index != 0 ? 'border-top: 0.02rem solid #e6e6e6;' : ''">
- <div class="flex-1 flex-box" style="align-items: center; justify-content: space-between;">
- <!-- <div class="score-result">{{ item.scoreResult }}</div> -->
- <div class="flex-box-ce flex-1">
- <userImage :id="item.employeeId" :user_name="item.employeeName" fontSize="0.15" width="0.63rem" height="0.63rem" style="margin-top:.08rem;"></userImage>
- <div style="padding-left:.2rem;">
- <span style="font-size:.3rem;">{{ item.employeeName }}</span>
- <br />
- <span class="font-flex-word" style="width: 3.8rem;display:inline-block;" v-if="item.dept_list && item.dept_list.length > 0">
- <span style="font-size:.25rem;" v-for="(arr, att) in item.dept_list" :key="att">
- {{ arr.dept_name }}
- <span v-if="item.dept_list.length - att > 1">,</span>
- </span>
- </span>
- </div>
- </div>
- <div style="display: flex; align-items: center; flex-direction: column;">
- <div v-if="item.status == 0" class="review-status">进行中</div>
- <div v-if="item.status == 1" class="review-status" style="background-color: #FF9600;">已结束</div>
- <div style="display: flex; align-items: center; white-wrap: no-wrap; font-size:.26rem; text-align:center; overflow: hidden;">
- <span>{{ item.score == undefined || item.score == null || item.score == '' ? '-' : item.score }}</span>
- /
- <span v-if="active == 1" style="color:#ffad67;">{{ item.scoreResult || '-' }}</span>
- <span v-if="active == 0" style="color:#ffad67;">{{ item.level ? item.level : '--'}}</span>
- </div>
- </div>
- </div>
- </li>
- </ol>
- <noData v-else content="无考核记录"></noData>
- </div>
- </div>
- </div>
- <template>
- <div class="indicator-list-title">指标分析</div>
- <div class="indicator-list">
- <div class="indicator-item" v-for="(item, index) in tableData2" :key="index">
- <div class="indicator-item-info">
- <div class="indicator-info-label">指标名称</div>
- <div class="indicator-info-value">{{ item.title }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">目标</div>
- <div class="indicator-info-value">{{ item.target }} {{ item.unit ? item.unit : '' }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">均值</div>
- <div class="indicator-info-value">{{ item.avgResult }} {{ item.unit ? item.unit : '' }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">超出目标比例</div>
- <div v-if="parseInt(item.standardResultRate) > 0" class="color-green">{{ item.standardResultRate }}</div>
- <div v-else-if="parseInt(item.standardResultRate) < 0" class="color-red">{{ item.standardResultRate }}</div>
- <div v-else class="color-gray">{{ item.standardResultRate }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">达标数</div>
- <div class="indicator-info-value">{{ item.standardCount }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">达标率</div>
- <div v-if="parseInt(item.standardRate) > 0" class="color-green" >{{ item.standardRate }}</div>
- <div v-else-if="parseInt(item.standardRate) < 0" class="color-red" >{{ item.standardRate }}</div>
- <div v-else class="color-gray" >{{ item.standardRate }}</div>
- </div>
- <div class="indicator-item-info">
- <div class="indicator-info-label">平均分</div>
- <div class="indicator-info-value">{{ item.avgScore }}</div>
- </div>
- </div>
- </div>
- </template>
- </div>
- </scroller>
- </template>
- </VanSkeleton>
- <noData content="无考核记录" v-else></noData>
- <!-- 周期选择 -->
- <van-action-sheet v-model="pullonThePanel" :closeable="false">
- <div class="content">
- <van-picker ref="van_picker" show-toolbar :columns="cycleOptions" @cancel="pullonThePanel = false" value-key="name" @confirm="onConfirm" confirm-button-text="完成" />
- </div>
- </van-action-sheet>
- <!-- 部门搜索 -->
- <van-dialog v-model="showDept" width="300" confirm-button-text="确定" @confirm="handleConfirm" @cancel="handleCancel" :show-confirm-button="true" closeOnClickOverlay>
- <div style="max-height: 8rem; overflow: auto;" class="scroll-bar">
- <div class="dept-list">
- <div class="checkbox-wrapper" v-for="(item, index) in department_list" :key="index">
- <input type="checkbox" :id="'dept' + (index+1)" class="hidden-checkbox" v-model="item.select">
- <label :for="'dept' + (index+1)" class="custom-checkbox"></label>
- <label :for="'dept' + (index+1)" class="checkbox-label">
- {{ item.dept_name }}
- </label>
- </div>
- </div>
- </div>
- </van-dialog>
- <!-- 状态 -->
- <van-dialog v-model="showStatus" title="" width="300" confirm-button-text="确定" @confirm="handleStatusConfirm" @cancel="handleStatusCancel" :show-confirm-button="true" closeOnClickOverlay>
- <van-radio-group v-model="statusId">
- <div v-for="(item, index) in statusList" :key="index">
- <van-radio :name="item.value" style="margin:.3rem 0 .3rem .4rem;font-size:.3rem" icon-size="16px">
- <span style="margin-left:.3rem">{{ item.text }}</span>
- </van-radio>
- </div>
- </van-radio-group>
- </van-dialog>
- </div>
- </template>
- <script>
- import Vue from 'vue';
- import VanSkeleton from '@/performance/components/public/VanSkeleton';
- import { Picker, ActionSheet, Circle, Tab, Tabs, Skeleton, DropdownMenu, DropdownItem, Progress, Calendar } from 'vant';
- import { _debounce } from '@/utils/auth';
- import _ from "lodash"
- Vue.use(Picker)
- .use(ActionSheet)
- .use(Circle)
- .use(Tab)
- .use(Tabs)
- .use(Skeleton)
- .use(DropdownMenu)
- .use(DropdownItem)
- .use(Progress)
- .use(Calendar);
- export default {
- data() {
- return {
- isYou: true,
- skeletonLoad: true, // 骨架屏
- statementtabshow: false,
- statementperson: [],
- statementResult: [],
- allStatementResult: [],
- statementVanTabs: [{ name: '等级分布' }, { name: '正态分布' }],
- active: 0,
- detailInfo: null,
- startTime: "",
- endTime: "",
- deptIds: [],
- rank: "",
- rankList: [],
- deptList: [],
- scoreList: [],
- users: [], //考核人员列表
- filterUsers: [],
- tableData1: [], // 考核中的指标列表,
- tableData2: [], // 按单位/目标/聚合指标列表,
- filterTableData1: [],
- filterTableData2: [],
- distributionId: '',
- userTotal: 0,
- userComplete: 0,
- userIncomplete: 0,
- infos: [],
- paramsText: '',
- selectPftiTheEcho: [0, 0], // 选项回显
- pullonThePanel: false, // 选项面板
- keyword: "",
- deptName: '全部部门',
- department_list: [],
- showDept: false,
- statusList: [
- {
- id: 0, text: "全部", value: "-1"
- },
- {
- id: 1, text: "进行中", value: "0"
- },
- {
- id: 2, text: "已结束", value: "1"
- },
- ],
- showStatus: false,
- statusId: "-1",
- statusName: "状态",
- recordList: [],
- userInfo: this.$userInfo(),
- gradeLevels: [], // 全局等级配置
- cycleOptions: [
- { name: "月度", value: "4", id: "4", text: "月度", children: [], className: 'column-1' },
- { name: "季度", value: "3", id: "3", text: "季度", children: [], className: 'column-2' },
- { name: "半年度", value: "2", id: "2", text: "半年度", children: [], className: 'column-3' },
- { name: "年度", value: "1", id: "1", text: "年度", children: [], className: 'column-4' },
- { name: "自定义", value: "0", id: "0", text: "自定义", children: [], className: 'column-5' },
- ],
- headValue: [],
- isYou: true,
- };
- },
- components: { VanSkeleton },
- watch: {
- detailInfo(v) {
- this.$nextTick(() => {
- this.initData();
- })
- },
- headValue(v) {
- let value = ''
- if (this.headValue[0] && this.headValue[0] == '0') value = "自定义 / "
- if (this.headValue[0] && this.headValue[0] == '1') value = "年度 / "
- if (this.headValue[0] && this.headValue[0] == '2') value = "半年度 / "
- if (this.headValue[0] && this.headValue[0] == '3') value = "季度 / "
- if (this.headValue[0] && this.headValue[0] == '4') value = "月度 / "
- let currentOption = this.cycleOptions.find(item => item.value == this.headValue[0])
- let optionIndex = this.cycleOptions.findIndex(item => item.value == this.headValue[0])
- let childIndex = 0
- if(currentOption.children && currentOption.children.length > 0) {
- childIndex = currentOption.children.findIndex(child => child.value == this.headValue[1])
- value += currentOption.children.find(child => child.value == this.headValue[1]).text;
- }
- // value += this.cycleOptions.find(item => item.value == this.headValue[1]).label || ''
- this.paramsText = value;
- this.selectPftiTheEcho = [optionIndex, childIndex] // 周期选项回显
- this.getResultAnalyze();
- }
- },
- methods: {
- openDetail(item){
- this.$router.push({ path: '/newMe', query: { reviewId: item.reviewId, employeeId: item.employeeId } });
- },
- async initData() {
- // this.activeName = '1'
- this.deptName = '全部部门'
- this.deptIds = [];
- this.department_list = [];
- this.users = [];
- this.filterUsers = [];
- this.tableData1 = [];
- this.tableData2 = [];
- this.filterTableData1 = [];
- this.filterTableData2 = [];
- let { indicators, startTime, endTime, distribution: { items }, users } = this.detailInfo
- this.startTime = startTime;
- this.endTime = endTime;
- this.scoreList = items;
- this.distributionId = this.scoreList[0].id
- this.users = users;
- this.tableData1 = indicators;
- this.tableData1.forEach(item => {
- this.users.forEach(user => {
- if (user.employeeId == item.employeeId) {
- item.departments = user.departments
- }
- })
- if (item.target && item.result) {
- item.difference = item.result - item.target
- } else {
- item.difference = '--'
- }
- })
- this.filterTableData1 = this.tableData1;
- if(this.tableData1 && this.tableData1.length > 0) {
- let groups = _.groupBy(this.tableData1, item => `${item.title}(_)${item.target === null || item.target === '' ? 'null' : item.target}(_)${item.unit === null || item.unit === '' ? 'null' : item.unit}`);
- Object.keys(groups).forEach(key => {
- let group = {
- title: '',
- target: '',
- unit: '',
- departments: [],
- userCount: 0,
- scoredCount: 0,
- standardCount: 0,
- failCount: 0,
- standardRate: '--',
- totalScore: 0,
- totalResult: 0,
- avgScore: 0,
- avgResult: 0,
- standardResultRate: '--'
- };
- groups[key].forEach(indicator => {
- group.title = indicator.title; // 指标名称
- group.target = indicator.target; // 目标
- group.unit = indicator.unit; // 单位
- group.departments = indicator.departments; // 单位
- let standardCount = indicator.difference !== '--' && indicator.difference >= 0 ? 1 : 0; //
- group.userCount += 1;
- group.scoredCount += indicator.score !== null ? 1 : 0;
- group.standardCount += standardCount;
- group.failCount += standardCount === 1 ? 0 : 1;
- if (indicator.score !== null) group.totalScore += indicator.score;
- if (indicator.result !== null) group.totalResult += indicator.result;
- });
- group.standardCount = group.standardCount;
- if (group.userCount > 0) {
- let rate = Math.floor(group.standardCount / group.userCount * 100 * 0.01);
- let avgScore = Math.floor(group.totalScore / group.userCount * 100 * 0.01);
- let avgResult = Math.floor(group.totalResult / group.userCount * 100 * 0.01);
- group.standardRate = rate > 0 ? `${rate}%` : '--';
- group.avgScore = avgScore !== 0 ? avgScore : '--';
- group.avgResult = avgResult !== 0 ? avgResult : '--';
- if (group.target !== null && group.avgResult !== '--') {
- let standardResultRate = Math.floor((group.avgResult - group.target) / group.target * 100 * 0.01 * 100);
- group.standardResultRate = standardResultRate !== 0 ? `${standardResultRate}%` : '--';
- }
- }
- this.tableData2.push(group);
- this.filterTableData2 = this.tableData2;
- })
- }
- this.userTotal = 0;
- this.userComplete = 0;
- this.userIncomplete = 0;
- let distribution = [];
- let userScores = []
- this.scoreList.forEach(item => {
- item.level = item.name;
- item.ratio = item.scale / 100
- distribution.push(item)
- })
- if (this.users && this.users.length > 0) {
- this.isYou = true;
- this.users.forEach(user => {
- this.userTotal++;
- this.userComplete += user.status === 1 ? 1 : 0;
- user.level = this.findGrade(user.score, this.gradeLevels);
- // this.rankList.push(user.level || '未评分')
- if(user.score !== null ) {
- userScores.push(user.score)
- }
- })
- this.infos = [
- { label: "总人数", num: this.userTotal },
- { label: "已完成", num: this.userComplete },
- { label: "未评分", num: this.userIncomplete },
- ]
- let scoreResult = this.assignLevels(userScores, distribution); //正态分布
- this.users.forEach(item => {
- item.dept_list = this.$getEmployeeMapItem(item.employeeId).employee_detail.dept_list
- if(item.dept_list && item.dept_list.length > 0) {
- item.dept_list.forEach(dept => {
- dept.id = dept.dept_id
- item.select = false
- this.department_list.push(dept)
- })
- this.department_list = Array.from(
- new Set(this.department_list.map(item => JSON.stringify(item)))
- ).map(item => JSON.parse(item));
- }
- scoreResult.forEach(result => {
- if (result.scores.includes(item.score)) {
- item.scoreResult = result.level
- }
- })
- })
- // 按分数排序
- this.users = this.users.slice().sort((a, b) => b.score - a.score);
- // this.filterUsers = cloneDeep(this.users)
- this.filterUsers = this.users
- // this.getResult();
- let pieData = []
- if(this.users && this.users.length > 0) {
- pieData = this.gradeLevels.map(item => ({
- name: item.name + ' ' + this.users.filter(user => user.level === item.name).length + '人',
- value: this.users.filter(user => user.level === item.name).length
- }))
- this.statmentAnalysesPie(pieData)
- }
- }else {
- this.isYou = false;
- }
- },
- statmentAnalysesPie(data) {
- let colors = ['rgb(38, 162, 255)', '#f36f2a', '#fecb09', '#00b6bd', '#e85d53', '#fecb09'];
- let legendDataLeng = data.length;
- if (legendDataLeng > colors.length) {
- let colorsLeng = colors.length;
- for (let i = 0; i <= legendDataLeng - colorsLeng; i++) {
- colors.push('rgb(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ')');
- }
- }
- // 是否全部 0
- const isEmpty = data.every(v => v.value == 0)
- if(isEmpty) {
- data.forEach(item => item.itemStyle = { color: '#E5E5E5' })
- }
- const chart = this.$refs.statmentAnalysePie;
- if (chart) {
- const myChart = this.$echarts.init(chart);
- const option = {
- legend: [
- {
- type: 'scroll',
- orient: 'vertical',
- icon: 'square',
- left: '55%',
- align: 'left',
- top: 'center',
- itemGap: 20,
- itemWidth: 5, // 图形宽度。
- itemHeight: 5, // 图形高度。
- // bottom:'50%',
- textStyle: {
- fontSize: 14,
- color: 'rgb(48, 49, 51)'
- }
- // data: Name
- }
- ],
- color: colors,
- emphasis: {
- scale: true,
- scaleSize: 10,
- label: {
- formatter: '总人数',
- show: true,
- fontSize: '20'
- }
- },
- series: [
- {
- type: 'pie',
- radius: ['43%', '53%'],
- center: ['30%', '50%'],
- avoidLabelOverlap: false,
- itemStyle: {
- borderRadius: 10,
- borderColor: '#fff',
- borderWidth: 2
- },
- label: {
- show: false,
- position: 'center'
- },
- labelLine: {
- show: false
- },
- data: data.reverse()
- }
- ]
- };
- myChart.setOption(option);
- setTimeout(() => {
- myChart.resize();
- }, 200);
- }
- },
- // 查找分数对应的等级
- findGrade(score, gradeLevels) {
- for (let i = 0; i < gradeLevels.length; i++) {
- if (score && score >= gradeLevels[i].min && score && score <= gradeLevels[i].max) {
- return gradeLevels[i].name; // 返回对应的等级描述
- } else if (score && score <= gradeLevels[0].min) {
- return gradeLevels[0].name; // 返回对应的等级描述
- } else if (score && score >= gradeLevels[gradeLevels.length - 1].max) {
- return gradeLevels[gradeLevels.length - 1].name; // 返回对应的等级描述
- }
- }
- return "未评级"; // 如果分数不在任何范围内
- },
- assignLevels(scores, levelConfigs) {
- // 降序排序并去重(假设分数不重复,可省略去重)
- const sortedScores = [...scores].sort((a, b) => b - a);
- const total = sortedScores.length;
- if (total === 0) return [];
- // 是否全部 0
- const isEmpty = sortedScores.every(v => v == 0 || v == null)
- if(isEmpty) return [];
- // 归一化处理比例
- const totalRatio = levelConfigs.reduce((sum, cfg) => sum + cfg.ratio, 0);
- const normalized = levelConfigs.map(cfg => cfg.ratio / totalRatio);
- // 计算每个等级的初始人数
- let counts = normalized.map(ratio => Math.floor(total * ratio));
- let remainder = total - counts.reduce((sum, c) => sum + c, 0);
- // 分配剩余人数,按优先级顺序
- let idx = 0;
- while (remainder > 0 && idx < counts.length) {
- counts[idx]++;
- remainder--;
- idx++;
- }
- // 构建结果:按人数切割数组
- let start = 0;
- return counts.map((count, i) => {
- const end = start + count;
- const levelScores = sortedScores.slice(start, end);
- start = end;
- return {
- level: levelConfigs[i].level,
- scores: levelScores
- };
- });
- },
- statementTabs() {},
- openPanel(){
- this.pullonThePanel = true;
- this.$nextTick(() => {
- this.theEchoVanPicker()
- })
- },
- // 考核包搜索
- onConfirm (data, list) { // 确认
- this.selectPftiTheEcho = list
- let cycle = this.cycleOptions[list[0]].value
- let time = this.cycleOptions[list[0]].children[list[1]].value
- this.headValue = [cycle, time]
- this.pullonThePanel = false
- },
- // 获取全局等级设置
- async getAllLevelSet() {
- let res = await this.$axiosUser('get', 'api/pro/per/user/base_config')
- let data = res.data.data;
- let levels = data.level_scope.levels;
- let gradeLevels = [];
- let max = 0;//最大值
- let colorList = ['#5F7294', '#08EEA1', '#f56c6c', '#0887EE', '#92EE08', '#f56c6c']
- if (levels && levels.length > 0) {
- levels.forEach((item, index) => {
- var obj;
- if (index == 0) {
- obj = { name: item.name, max: Number(item.value), min: 0 };
- } else {
- obj = { name: item.name, max: Number(item.value), min: max };//当不是第一个等级时,最小值为上一个的最大值
- }
- obj.color = colorList[index]
- max = item.value;
- gradeLevels.push(obj);
- })
- this.gradeLevels = gradeLevels;
- }
- },
- // 获取结果分析数据
- getResultAnalyze() {
- let url = `/performance/statistics/cycle/${this.$userInfo().site_id}/${this.headValue[0]}`
- if (!this.headValue[1]) return
- this.$axiosUser("get", url, { value: this.headValue[1] }).then(res => {
- this.detailInfo = res.data.data
- this.skeletonLoad = false
- })
- },
- getRecords(cycle) {
- if (cycle < 0) {
- cycle = 0
- return
- }
- // 周期种类 0-自定义 1-年度 2-半年度 3-季度 4-月度
- let url = `/performance/statistics/cycle/info/${this.$userInfo().site_id}/${cycle}`
- this.$axiosUser("get", url, {}).then(res => {
- let { data: { data: { items, cycleType } } } = res
- if (items && items.length > 0) {
- items.forEach(item => {
- item.name = item.remark
- item.text = item.remark
- item.id = item.value
- })
- let index = parseInt(4 - cycle)
- this.cycleOptions[index].children = items
- this.headValue = [cycle + '', this.cycleOptions[index].children[[0]].value]
- // if (this.headValue[1]) this.placeholder = this.options[parseInt(cycle)].children[[0]].label || ''
- } else {
- this.getRecords(parseInt(cycle) - 1) // 递归周期类型,获取考核数据,优先按月,季,半年度,年度来调用
- }
- })
- },
- theEchoVanPicker() {
- // 回显
- this.$refs.van_picker.setIndexes(this.selectPftiTheEcho);
- },
- onCancel() {
- // 取消
- this.pullonThePanel = false;
- },
- keyVal: _debounce(function() {
- if(!this.keyword) this.filterUsers = this.recordList
- // let filterUsers = []
- if(this.recordList && this.recordList.length > 0) {
- this.filterUsers = this.recordList.filter(item => item.employeeName.includes(this.keyword.trim()))
- }
- }),
- handleConfirm() {
- this.deptIds = this.department_list.filter(item => item.select).map(item => item.dept_id)
- if(this.deptIds && this.deptIds.length > 0) {
- this.deptName = ''
- this.department_list.filter(item => item.select).forEach(dept => {
- this.deptName += dept.dept_name + ","
- })
- this.deptName = this.deptName.substring(0, this.deptName.length - 1)
- // this.filterUsers = this.users.filter((item) => {
- // const departmentMatch = this.deptIds.length === 0 || this.deptIds.some((depId) => item.departments.some(dep => dep.id == depId));
- // return departmentMatch;
- // });
- }else {
- this.deptName = '全部部门'
- }
- this.filteredData()
- this.showDept = false;
- },
- // 实时过滤后数据
- filteredData() {
- this.filterUsers = this.users.filter((item) => {
- // 部门筛选:如果选了部门,则过滤;没选则不过滤
- const departmentMatch = this.deptIds.length === 0 || this.deptIds.some((depId) => item.departments.some(dep => dep.id == depId));
- // 状态筛选:如果选了“全部”,则不过滤;否则按状态过滤
- const statusMatch = this.statusId == '-1' || item.status == this.statusId;
- return departmentMatch && statusMatch;
- });
- },
- handleCancel() {
- this.showDept = false;
- },
- handleStatusConfirm() {
- this.filteredData();
- this.statusName = this.statusList.find(item => item.value == this.statusId).text || '状态'
- this.showStatus = false
- },
- handleStatusCancel() {
- this.showStatus = false;
- },
- getColumnsInfo(cycle) {
- if (cycle < 0) {
- cycle = 0
- return
- }
- // this.loading = true
- // 周期种类 0-自定义 1-年度 2-半年度 3-季度 4-月度
- let url = `/performance/statistics/cycle/info/${this.$userInfo().site_id}/${cycle}`
- this.$axiosUser("get", url, {}).then(res => {
- // this.loading = false;
- let { data: { data: { items, cycleType } } } = res
- let index = parseInt(4 - cycle)
- this.cycleOptions[index].children = items
- if (items && items.length > 0) {
- items.forEach(item => {
- item.name = item.remark
- item.text = item.remark
- item.id = item.value
- })
- let cycle = this.cycleOptions[index].value
- let time = this.cycleOptions[index].children[[0]].value
- } else {
- this.cycleOptions[index].children = [
- {name: '', text: '', value: '', id: ''}
- ]
- }
- })
- },
- },
- mounted() {
- this.$nextTick(async () => {
- // 获取全局等级
- await this.getAllLevelSet();
- // 获取周期列表数据
- await this.getColumnsInfo(4); // 月度
- await this.getColumnsInfo(3);
- await this.getColumnsInfo(2);
- await this.getColumnsInfo(1);
- await this.getColumnsInfo(0);
- this.getRecords(4);
- })
- },
- created() {
- }
- };
- </script>
- <style scoped lang="less">
- /* 父容器:垂直居中的关键 */
- .checkbox-wrapper {
- display: flex;
- align-items: center; /* 垂直居中 */
- gap: 8px; /* 图标与文字间距 */
- margin-bottom: 0.2rem;
- font-size: 0.28rem;
- color: #89919F;
- }
- /* 隐藏原生的 checkbox */
- .hidden-checkbox {
- position: absolute;
- opacity: 0;
- width: 0;
- height: 0;
- }
- /* 自定义 checkbox 框 */
- .custom-checkbox {
- position: relative;
- width: 14px;
- height: 14px;
- border: 1px solid #dcdfe6;
- border-radius: 4px;
- cursor: pointer;
- transition: all .2s;
- flex-shrink: 0; /* 防止被压缩 */
- }
- /* 选中背景 */
- .hidden-checkbox:checked + .custom-checkbox {
- background: #409eff;
- border-color: #409eff;
- }
- /* 选中对勾 */
- .hidden-checkbox:checked + .custom-checkbox::after {
- content: "";
- position: absolute;
- left: 0.06rem;
- top: 0.02rem;
- width: 5px;
- height: 8px;
- border: solid #fff;
- border-width: 0 2px 2px 0;
- transform: rotate(45deg);
- }
- /* label 文字样式(可选) */
- .checkbox-label {
- cursor: pointer;
- user-select: none;
- line-height: 1.4;
- }
- .van-action-sheet__content /deep/ .van-picker-column.column-1 {
- flex: 0 0 240px !important;
- max-width: 240px !important;
- }
- .color-red {
- padding: 0.05rem 0.2rem;
- box-sizing: border-box;
- background-color: #fef0f0;
- border: 0.02rem solid #fde2e2;
- color: #f56c6c !important;
- }
- .color-green {
- padding: 0.05rem 0.2rem;
- box-sizing: border-box;
- background-color: #f0f9eb;
- border: 0.02rem solid #e1f3d8;
- color: #67c23a !important;
- }
- .color-gray {
- padding: 0.05rem 0.2rem;
- box-sizing: border-box;
- background-color: #f4f4f5;
- border: 0.02rem solid #e9e9eb;
- color: #909399 !important;
- }
- .dept-list {
- padding: 0.2rem;
- box-sizing: border-box;
- .dept-item {
- box-sizing: border-box;
- padding-left: 0.3rem;
- height: 0.8rem;
- &-name {
- font-size: 0.28rem;
- color: #89919F;
- }
- }
- }
- .statementHnum {
- display: flex;
- flex-wrap: wrap;
- width: 100%;
- padding: 0 0.2rem;
- margin-top: 0.2rem;
- .Hnumvfor {
- flex: 0 0 calc((100% - 1rem) / 4);
- position: relative;
- background-color: #ECF5FF;
- border-radius: 3px;
- text-align: center;
- margin: 0 0.2rem 0.2rem 0;
- padding: 0.1rem 0.2rem;
- box-sizing: border-box;
- &:nth-child(4n) {
- /* 去除第5n个的margin-right */
- margin-right: 0;
- }
- .smHnLnum {
- font-size: 0.42rem;
- color: #00a1ff;
- }
- .smHnLtit {
- font-size: 0.26rem;
- color: #8a8a8a;
- }
- }
- }
- .selectItem {
- height: 0.8rem;
- line-height: 0.8rem;
- background-color: #fff;
- border-top: 0.02rem solid #f1f1f1;
- text-align: center;
- font-size: 0.28rem;
- i {
- margin: 0.23rem 0 0 0.1rem;
- }
- }
- header {
- .selector {
- z-index: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100%;
- height: 0.8rem;
- line-height: 0.8rem;
- background-color: #fff;
- text-align: center;
- font-size: 0.28rem;
- i {
- margin: 0 0 0 0.1rem;
- color: #c3c3c3;
- }
- span {
- max-width: 3.5rem;
- overflow: hidden;
- }
- }
- }
- .all {
- height: calc(100% - 1.92rem) !important;
- position: relative !important;
- background-color: #f5f7fa;
- .statementHead {
- width: 100%;
- text-align: center;
- // padding-top: 0.35rem;
- background-color: #fff;
- .statementpropnum {
- background-color: #f5f7fa;
- padding: 0.3rem 0 0.1rem;
- .propnumrel1 {
- /deep/ .van-progress__pivot {
- margin-left: -0.11rem;
- }
- }
- .propnumrel {
- position: relative;
- padding: 0 0.15rem;
- /deep/ .van-progress {
- border-radius: 0.5rem;
- .van-progress__portion {
- border-radius: 0.14rem;
- .van-progress__pivot {
- border-radius: 50%;
- min-width: 0.33rem !important;
- height: 0.33rem;
- right: 0;
- // margin-left: -.11rem;
- }
- }
- }
- .propnumcol {
- position: absolute;
- top: 0;
- right: 0.4rem;
- font-size: 0.25rem;
- color: #fff;
- }
- .numelzi {
- font-size: 0.26rem;
- margin: 0.25rem 0;
- .numelzh {
- color: #000000;
- }
- .numelzl {
- color: #0597ff;
- display: flex;
- align-items: center;
- justify-content: center;
- i {
- margin: 0.06rem 0 0 0.02rem;
- }
- }
- }
- }
- }
- .circle {
- margin-top: 0.7rem;
- .circletit {
- font-size: 0.24rem;
- color: #6f6f6f;
- }
- .circleclic {
- color: #4ba0f1;
- .circleclics1 {
- font-size: 0.42rem;
- display: inline-block;
- margin: 0.1rem 0;
- }
- .circleclics2 {
- font-size: 0.25rem;
- display: flex;
- justify-content: center;
- i {
- margin: 0.06rem 0 0 0.02rem;
- }
- }
- }
- }
- }
- .statementFoot {
- background-color: #fff;
- margin-top: 0.2rem;
- .statmentperson {
- padding: 0.25rem 0.2rem;
- font-size: 0.32rem;
- box-sizing: border-box;
- .score-result {
- width: 0.4rem;
- height: 0.4rem;
- border: 0.02rem solid #409EFF;
- color: #409EFF;
- border-radius: 50%;
- font-size: 0.26rem;
- text-align: center;
- line-height: 0.4rem;
- margin-right: 0.1rem;
- }
- }
- }
- }
- .takI {
- font-size: 0.27rem;
- color: #f7b461;
- i {
- margin: 0.1rem 0.05rem 0 0;
- }
- }
- .statmentAnalysePie {
- position: relative;
- .PiePropNum {
- width: 1.5rem;
- text-align: center;
- position: absolute;
- left: 20%;
- top: 42%;
- font-size: 0.3rem;
- }
- }
- .review-status {
- // padding: 0.01rem 0.1rem;
- width: 1.2rem;
- height: 0.4rem;
- text-align: center;
- line-height: 0.4rem;
- color: #fff;
- border-radius: 2px;
- font-size: 0.26rem;
- background-color: #67c23a;
- margin-right: 0.14rem;
- margin-bottom: 0.1rem;
- }
- .indicator-list-title {
- padding: 0.2rem 0.2rem 0 0.2rem;
- box-sizing: border-box;
- font-size: 0.28rem;
- }
- .indicator-list {
- padding: 0.2rem;
- box-sizing: border-box;
- .indicator-item {
- background-color: white;
- margin-bottom: 0.2rem;
- padding: 0.2rem;
- box-sizing: border-box;
- border-radius: 8px;
- .indicator-item-info {
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 0.28rem;
- margin-bottom: 0.2rem;
- .indicator-info-label {
- width: 2rem;
- color: black;
- }
- .indicator-info-value {
- flex: 1;
- text-align: right;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- color: #89919F;
- }
- }
- }
- }
- .van-picker__columns .van-picker-column:nth-child(2) {
- background-color: red !important;
- }
- </style>
|