<template> <!-- 年度考核 --> <div class="yearJXPage"> <div class="searchBoxs"> <n-space> <div class="name">厂站:</div> <n-select v-model:value="searchVal1" style="width: 200px" :options="clzOptions" clearable> </n-select> <div class="name">岗位:</div> <n-select v-model:value="searchVal2" style="width: 200px" :options="jueseOptions" clearable> </n-select> <div class="name">人员姓名:</div> <n-input v-model:value="realName" style="width: 200px" clearable> </n-input> <n-button type="success" @click="getPersonList(1, 12)"> <template #icon> <n-icon> <Search /> </n-icon> </template> 搜索 </n-button> </n-space> </div> <!-- 左侧 --> <div class="leftcontent"> <div class="leftcalendar"> <div class="BoxCentent"> <div class="BigYear"> <div class="BigYearList"> <span class="yearNum">{{ yearData.substring(0, 1) }}</span> </div> <div class="BigYearList"> <span class="yearNum">{{ yearData.substring(1, 2) }}</span> </div> <div class="BigYearList"> <span class="yearNum">{{ yearData.substring(2, 3) }}</span> </div> <div class="BigYearList BigYearList4"> <span class="yearNum">{{ yearData.substring(3, 4) }}</span> </div> </div> <div class="ChangeYear"> <div class="ChangeYearList" v-for="(item, index) in allyear" :key="index" :class="{ ChangeYearListCheck: isCheck == index }" @click="yearClick(item, index)" > {{ item.year }} </div> </div> </div> </div> <div class="leftbottom"> <div class="title">个人成绩综合得分排名</div> <n-data-table :bordered="false" striped :columns="columns" :data="tableData" :loading="tableLoading" :remote="true" max-height="480" > </n-data-table> </div> </div> <!-- 右侧 --> <div class="rightcontent"> <div class="contentPart"> <div class="person" @click.capture="getpersonInfo(item)" v-for="item in personArr" :key="item.id"> <div class="personImg"></div> <div class="personInfo" @click="getpersonShow()"> <div class="part"> <div class="titlelist">姓名:</div> <div class="contentlist">{{ item.realName }}</div> </div> <div class="part"> <div class="titlelist">岗位:</div> <div class="contentlist">{{ item.jobType }}</div> </div> <div class="part"> <div class="titlelist">角色:</div> <div class="contentlist">{{ item.roleName }}</div> </div> </div> <div class="Line"></div> <div class="jixiaoInfo"> <n-space> <div class="titlelist">绩效得分:</div> <div class="contentlist">{{ item.totalScore }}分</div> <div class="titlelist" style="margin-left: 20px" @click="getjixiaoInfo()"> 绩效考评: <n-icon :style="{ width: '25px', top: '2px' }"> <Book /> </n-icon> </div> </n-space> </div> </div> </div> <div id="DutyHoursFoot"> <n-pagination v-model:page="page" :page-count="total" @update:page="paginationChange" style="float: right; padding-right: 50px" /> </div> </div> <!--人员详情 --> <n-modal title="人员详情" :mask-closable="false" preset="dialog" :show-icon="false" :style="{ width: '1800px' }" v-model:show="InfoShow" > <peopleDetailInfo :totalScore="personInfo.totalScore" :roleName="personInfo.roleName" :realName="personInfo.realName" :jobType="personInfo.jobType" :userId="personInfo.id" :userAccount="personInfo.userAccount" > </peopleDetailInfo> </n-modal> <!--绩效弹窗 --> <n-modal title="编辑年度绩效" :mask-closable="false" preset="dialog" :show-icon="false" :style="{ width: '1200px' }" v-model:show="JXShow" > <n-data-table :bordered="true" :single-line="false" :max-height="700" :striped="true" :columns="Listcolumns" :data="tableListData" :loading="tableLoadingJX" :remote="true" > </n-data-table> <div class="JXwords" style="margin-top: 20px; color: red; margin-left: 380px"> *人员绩效计算公式:岗位任务得分求和*权重+卫生出勤*权重 </div> <template #action> <n-space style="margin-right: 500px"> <n-button type="primary" @click="updataMonthInfo()">保存</n-button> <n-button @click="() => (JXShow = false)">取消</n-button> </n-space> </template> </n-modal> </div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, ref, h } from 'vue'; import yearcalendar from './components/yearcalendar.vue'; import peopleDetailInfo from './components/peopleDetailInfo.vue'; import { Search, Add, Book } from '@vicons/ionicons5'; import { NInputNumber, NInput } from 'naive-ui'; import { getnormlogpersonal, getnormlogScore, getYearResaultInfo, getMonthResaultUpdata, getAllStationList } from '@/services'; import { formatDate } from '@/utils/util'; export default { name: 'yearJXPage', components: { Search, Add, yearcalendar, Book, peopleDetailInfo, }, setup() { const allData = reactive({ searchVal1: null, searchVal2: null, InfoShow: false, JXShow: false, realName: null, tableLoading: true, //表格数据加载状态,接入后端后修改为true tableLoadingJX: false, //表格数据加载状态,接入后端后修改为true tableData: [], tableListData: [], columns: [ { title: '排名', align: 'center', render: (row, index) => { return index + 1; }, }, { title: '姓名', align: 'center', key: 'realName' }, { title: '绩效', align: 'center', key: 'totalScore' }, ], Listcolumns: [ { title: '年度成绩组成部分', align: 'center', key: 'normName', ellipsis: { tooltip: true, lineClamp: 2 } }, { title: '考核项描述', align: 'center', key: 'normRemake', ellipsis: { tooltip: true, lineClamp: 2 } }, { title: '评分标准', align: 'center', key: 'evaluateStandard', ellipsis: { tooltip: true, lineClamp: 2 } }, { title: '权重', align: 'center', key: 'scoreRate', width: '80' }, { title: '分值', align: 'center', key: 'defScore', width: '80' }, { title: '评分', align: 'center', key: 'score', width: '150', render(row, index) { return h(NInputNumber, { value: row.score, min: 0, max: row.defScore, ['onUpdate:value']: (val) => { if (val < 0) { val = 0; } else if (val > Number(row.defScore)) { val = Number(row.score); } row.score = val; }, }); }, }, ], clzOptions: [], jueseOptions: [], personArr: [], page: 1, total: 0, personInfo: { totalScore: null, roleName: null, realName: null, jobType: null, mobile: null, userAccount: null, job: '', id: null, }, startTime: '', endTime: '', }); const yearData = reactive({ yearData: String(new Date().getFullYear()), //选中的年份 allyear: [ { year: String(new Date().getFullYear() - 3), isCheck: false, }, { year: String(new Date().getFullYear() - 2), isCheck: false, }, { year: String(new Date().getFullYear() - 1), isCheck: false, }, { year: String(new Date().getFullYear()), isCheck: true, }, { year: String(new Date().getFullYear() + 1), isCheck: false, }, ], //所有的年份 isCheck: 3, //选中的年份 }); // 分页 function paginationChange(value) { getPersonList(value, 12); } // 获取人员列表 const getPersonList = async (pageIndex, pageSize) => { $loadingBar.start(); let param = { current: pageIndex, size: pageSize, data: { companyId: allData.searchVal1, job: allData.searchVal2, userName: allData.realName, normType: 1, ymtime: yearData.yearData, }, }; let res = await getnormlogpersonal(param); if (res && res.code == 200) { let datas = res.data; allData.personArr = datas.records; allData.total = datas.pages; } getScore(allData.startTime, allData.endTime); $loadingBar.finish(); }; //获取人员详情弹窗 function getpersonInfo(index) { allData.personInfo = index; } //获取绩效编辑弹窗 function getjixiaoInfo() { allData.JXShow = true; getMonthInfo(); } //获取绩效详情 const getMonthInfo = async () => { allData.tableLoadingJX = true; let params = { startTime: allData.startTime, endTime: allData.endTime, normType: 1, userId: allData.personInfo.id, jobId: allData.personInfo.job, ymtime: '', }; let res = await getYearResaultInfo(params); if (res && res.code == 200) { allData.tableListData = res.data; } allData.tableLoadingJX = false; }; //绩效详情修改 const updataMonthInfo = async () => { let params = { normType: 1, userId: allData.personInfo.id, normlogBoList: allData.tableListData, dateTime: allData.startTime, }; let res = await getMonthResaultUpdata(params); if (res && res.code == 200) { $message.success('操作成功'); getMonthInfo(); getPersonList(); allData.JXShow = false; } }; // 点击年份 function yearClick(item, index) { yearData.isCheck = index; yearData.yearData = item.year; allData.startTime = `${yearData.yearData}-01-01 00:00:00`; allData.endTime = `${yearData.yearData}-12-31 23:59:59`; getPersonList(1, 12); } //获取人员详情弹窗 function getpersonShow() { allData.InfoShow = true; } //获取厂站及岗位 const getStation = async () => { let params1 = { distType: 'company', }; let params2 = { distType: 'job', }; let res1 = await getAllStationList(params1); if (res1 && res1.code == 200) { res1.data.forEach((element) => { let { distKey, distName } = element; allData.clzOptions.push({ value: distKey, label: distName }); }); } let res2 = await getAllStationList(params2); if (res2 && res2.code == 200) { res2.data.forEach((element) => { let { distKey, distName } = element; allData.jueseOptions.push({ value: distKey, label: distName }); }); } }; // 获取成绩综合得分 const getScore = async (startTime, endTime) => { allData.tableLoading = true; // 左侧成绩综合得分排名 let params = { companyId: allData.searchVal1, userName: allData.realName, startTime: startTime, endTime: endTime, normType: 1, }; let res = await getnormlogScore(params); if (res && res.code == 200) { allData.tableData = res.data; } allData.tableLoading = false; }; onMounted(() => { allData.startTime = `${yearData.yearData}-01-01 00:00:00`; allData.endTime = `${yearData.yearData}-12-31 23:59:59`; getPersonList(1, 12); getStation(); }); onBeforeMount(() => {}); return { ...toRefs(allData), ...toRefs(yearData), getpersonInfo, getjixiaoInfo, yearClick, paginationChange, getScore, getPersonList, getpersonShow, updataMonthInfo, getStation, }; }, }; </script> <style lang="less"> .yearJXPage { position: relative; height: 100%; display: flex; flex-wrap: wrap; padding: 10px; .searchBoxs { height: 50px; margin: 10px; .name { height: 34px; line-height: 34px; } } .title { display: flex; align-items: center; padding-left: 20px; width: 490px; height: 44px; line-height: 22px; font-size: 18px; font-family: Source Han Sans CN; font-weight: 400; color: #1bd9d7; &:before { display: block; content: ''; width: 2px; height: 17px; background: #0199d9; margin-right: 10px; } } .leftcontent { top: 60px; position: absolute; .leftcalendar { height: 223px; width: 380px; margin-top: 15px; margin-bottom: 20px; border: 1px solid #25d8f5; .BigYear { width: 100%; height: 120px; display: flex; justify-content: space-around; box-sizing: border-box; padding-top: 20px; box-sizing: border-box; padding: 20px 10px; .BigYearList { width: 75px; height: 75px; line-height: 75px; background: #46b3d3; border-radius: 10px; position: relative; } .BigYearList4 { position: relative; } .BigYearList4::after { content: ''; width: 75px; position: absolute; left: -5px; top: 37.5px; border-width: 0 5px 32px 5px; border-style: none solid solid; border-color: transparent transparent #27a7cd; border-radius: 5px; z-index: 1; } .yearNum { position: absolute; left: 0; top: 0; width: 75px; height: 75px; line-height: 75px; font-size: 48px; font-family: Arial; font-weight: bold; color: #f2f7f8; text-align: center; z-index: 2; } } .ChangeYear { display: flex; justify-content: space-around; width: 100%; height: calc(100% - 120px); box-sizing: border-box; padding-top: 30px; .ChangeYearList { width: 48px; height: 48px; background: #46b3d3; border-radius: 50%; font-size: 12px; font-family: Arial; font-weight: bold; color: #f2f7f8; text-align: center; line-height: 48px; cursor: pointer; position: relative; } .ChangeYearListCheck { width: 70px; height: 70px; line-height: 70px; font-size: 15px; font-family: Arial; font-weight: bold; color: #f2f7f8; margin-top: -11px; background: linear-gradient(269deg, #46b3d3 0%, #a58fe8 100%); } .ChangeYearList::after { position: absolute; content: ''; top: 50%; color: var(--color-Invert); left: -10px; width: 8px; font-size: 12px; border-bottom: 1px dashed; } .ChangeYearList::before { position: absolute; content: ''; top: 50%; color: var(--color-Invert); right: -10px; width: 8px; font-size: 12px; border-bottom: 1px dashed; } .ChangeYearList:hover { animation: move 0.5s linear infinite; animation-iteration-count: 1; } } } .leftbottom { width: 380px; height: 580px; border: 1px solid #25d8f5; } } .rightcontent { top: 75px; position: absolute; height: 820px; width: 75%; left: 400px; #DutyHoursFoot { width: 100%; height: 30px; } .contentPart { display: flex; flex-wrap: wrap; max-height: 790px; .person { display: flex; flex-wrap: wrap; width: 315px; height: 245px; padding: 10px 5px; margin-right: 7px; cursor: pointer; background: url('@/assets/newImgs/userJX/personback.png') no-repeat center; background-size: 100% 100%; .Line { height: 1px; width: 98%; margin: 10px 1%; border: 1px solid rgba(57, 139, 198, 1); } } .personImg { width: 90px; height: 90px; margin: 40px 10px 0 10px; background: url('@/assets/newImgs/userJX/defaultperson.jpg') no-repeat center; background-size: 100% 100%; border-radius: 50%; } .jixiaoInfo { margin-left: 20px; } .personInfo { width: 150; margin-left: 20px; margin-top: 25px; .part { align-items: center; display: flex; margin-top: 10px; .titlelist { font-size: 15px; } .contentlist { font-size: 15px; width: 110px; max-height: 30px; overflow: auto; } } } } } } </style>