<template> <!-- 人员详情 --> <div class="userDetailPage"> <!-- 左侧 --> <div class="leftInfo"> <div class="topInfo"> <div class="userImg"></div> <n-form label-align="right" :label-width="100" label-placement="left"> <n-space> <n-form-item label="姓名:" path="realName"> <n-input v-model:value="person.realName" placeholder="" size="tiny" style="width: 100px" :readonly="true"></n-input> </n-form-item> <n-form-item label="角色:" path="roleName"> <n-input v-model:value="person.roleName" placeholder="" style="width: 100px" size="tiny" :readonly="true"></n-input> </n-form-item> </n-space> <n-space> <n-form-item label="登陆账号:" path="userAccount"> <n-input v-model:value="person.userAccount" placeholder="" style="width: 100px" size="tiny" :readonly="true"></n-input> </n-form-item> <n-form-item label="手机号:" path="mobile"> <n-input v-model:value="person.mobile" placeholder="" size="tiny" style="width: 100px" :readonly="true"></n-input> </n-form-item> </n-space> <n-space> <n-form-item label="岗位:" path="jobType"> <n-input v-model:value="person.jobType" placeholder="" size="tiny" style="width: 100px" :readonly="true"></n-input> </n-form-item> <n-form-item label="绩效:" path="totalScore"> <n-input-number v-model:value="person.totalScore" placeholder="" :show-button="false" style="width: 100px" size="tiny" :readonly="true" ></n-input-number> </n-form-item> </n-space> </n-form> </div> <div class="leftcalendar"> <yearcalendar1></yearcalendar1> </div> </div> <!-- 中间 --> <div class="centerInfo"> <!-- 中上 --> <div class="centertop"> <div class="title">培训列表</div> <n-data-table :bordered="false" striped size="small" style="width: 800px" max-height="300px" :columns="columns" :data="tableData" :loading="tableLoading" :remote="true" :pagination="pagination" > </n-data-table> <div class="Line"></div> <div class="centerbottom"> <div class="title">绩效成绩</div> <n-data-table striped size="small" max-height="300px" style="width: 1000px; margin-left: 5px" :single-line="false" :columns="columns3" :data="tableData3" :loading="tableLoading3" :remote="true" > </n-data-table> </div> </div> </div> <!-- 右侧 --> <div class="rightInfo"> <!-- 右上 --> <div class="rightop"> <n-space> <div class="title">技能证书</div> <n-button type="warning" size="tiny" style="margin-top: 12px" circle @click="updataCertificate('1')"> <template #icon> <n-icon> <Add /> </n-icon> </template> </n-button> </n-space> <n-data-table :bordered="false" striped size="small" max-height="300px" style="width: 390px" :columns="columns4" :data="tableData4" :loading="tableLoading4" :remote="true" > </n-data-table> </div> <!-- 右下 --> <div class="rightbottom"> <n-space> <div class="title">师徒协议</div> <n-button type="warning" size="tiny" style="margin-top: 12px" circle @click="updataCertificate('2')"> <template #icon> <n-icon> <Add /> </n-icon> </template> </n-button> </n-space> <n-data-table :bordered="false" striped size="small" max-height="300px" style="width: 390px" :columns="columns5" :data="tableData5" :loading="tableLoading5" :remote="true" > </n-data-table> </div> </div> <!-- 添加技能证书弹窗 --> <n-modal :title="`上传附件${radioVal == '1' ? '证书资料' : '师徒协议'}`" :mask-closable="false" preset="dialog" :show-icon="false" :style="{ width: '450px' }" v-model:show="tableShow" > <n-form ref="formRef" label-align="right" require-mark-placement="left" :label-width="120" :rules="formInfo.rules" :model="formInfo.data" label-placement="left" style="margin-top: 30px" > <div v-if="radioVal == '1'"> <n-form-item label="竞赛名称:" path="competitionName"> <n-input v-model:value="formInfo.data.competitionName" /> </n-form-item> <n-form-item label="证书类型:" path="competitionType"> <n-select v-model:value="formInfo.data.competitionType" :options="competArr1" @update:value="changBookType"></n-select> </n-form-item> <n-form-item label="取得名次:" path="contestIntegralTermId"> <n-select v-model:value="formInfo.data.contestIntegralTermId" :options="competArr2"></n-select> </n-form-item> <n-form-item label="获奖时间:" path="awardTime"> <n-date-picker v-model:value="formInfo.data.awardTime" type="date" style="width: 100%" /> </n-form-item> </div> <div v-if="radioVal == '2'"> <n-form-item label="新人姓名:" path="userName"> <n-select v-model:value="formInfo.data.userName" :options="userList"></n-select> </n-form-item> <n-form-item label="入职时间:" path="inductionTime"> <n-date-picker v-model:value="formInfo.data.inductionTime" type="date" style="width: 100%" /> </n-form-item> <n-form-item label="转正时间:" path="formalTime"> <n-date-picker v-model:value="formInfo.data.formalTime" type="date" style="width: 100%" /> </n-form-item> </div> <n-form-item label="附件资料上传:" path="fileNo"> <n-upload v-model:file-list="uploadListZG" @change="changeFileZG"> <n-button>上传文件</n-button> </n-upload> </n-form-item> </n-form> <n-divider /> <template #action> <n-space style="margin-right: 10px"> <n-button type="primary" @click="saveBookData()">保存 </n-button> <n-button @click="() => (tableShow = false)">取消</n-button> </n-space> </template> </n-modal> </div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, ref } from 'vue'; import { getUserPxlist, getUserJxlist, getUserJnlist, getUserStlist, getUserBookList, fileUpload, fileDelete, getUserZsSave, getUserStSave, getUserData, } from '@/services'; import bus from '@/utils/util'; import { Search, Add } from '@vicons/ionicons5'; import yearcalendar1 from './yearcalendar1.vue'; import { formatDate } from '@/utils/util'; export default { name: 'userDetailPage', components: { yearcalendar1, Search, Add, }, props: { totalScore: Number, roleName: String, realName: String, jobType: String, mobile: String, userId: String, userAccount: String, }, setup(props, context) { const allData = reactive({ radioVal: '1', bookList: [], userList: [], competArr1: [], //证书类型 competArr2: [], //获得名次 searchValue1: null, searchValue2: null, year: new Date().getFullYear(), month: new Date().getMonth(), startTime: null, endTime: null, tableOptions: [], tableOptions2: [], tableShow: false, tableShow2: false, userId: props.userId, person: { totalScore: props.totalScore, roleName: props.roleName, realName: props.realName, jobType: props.jobType, mobile: props.mobile, userAccount: props.userAccount, }, tableLoading: true, tableLoading3: true, tableLoading4: false, tableLoading5: false, tableData: [], tableData2: [], tableData3: [], tableData4: [], tableData5: [], columns: [ { title: '序号', align: 'center', render(row, index) { return (paginationReactive.page - 1) * paginationReactive.pageSize + index + 1; }, }, { title: '培训主题', align: 'center', key: 'trainTopic' }, { title: '培训形式', align: 'center', key: 'trainType', render: (row) => { return row.trainType == '1' ? 'PPT' : row.trainType == '2' ? 'Word' : '实操'; }, }, { title: '培训开始时间', align: 'center', key: 'trainStartTime' }, { title: '培训结束时间', align: 'center', key: 'trainEndTime' }, { title: '培训内容', align: 'center', key: 'trainRemark' }, { title: '讲师', align: 'center', key: 'trainTeacher' }, { title: '培训课时', align: 'center', key: 'trainTime' }, ], columns3: [ { title: '年份', align: 'center', key: 'year' }, { title: '工作绩效', align: 'center', key: 'monthScore', children: [ { title: '1月', align: 'center', key: 'monthScore1' }, { title: '2月', align: 'center', key: 'monthScore2' }, { title: '3月', align: 'center', key: 'monthScore3' }, { title: '4月', align: 'center', key: 'monthScore4' }, { title: '5月', align: 'center', key: 'monthScore5' }, { title: '6月', align: 'center', key: 'monthScore6' }, { title: '7月', align: 'center', key: 'monthScore7' }, { title: '8月', align: 'center', key: 'monthScore8' }, { title: '9月', align: 'center', key: 'monthScore9' }, { title: '10月', align: 'center', key: 'monthScore10' }, { title: '11月', align: 'center', key: 'monthScore11' }, { title: '12月', align: 'center', key: 'monthScore12' }, ], }, { title: '理论知识', align: 'center', key: 'theoryScore' }, { title: '实际操作技能', align: 'center', key: 'practiceScore', children: [ { title: '安全成绩', align: 'center', key: 'securityScore' }, { title: '质量成绩', align: 'center', key: 'qualityScore' }, ], }, { title: '年度绩效', align: 'center', key: 'yearScore' }, ], columns4: [ { title: '竞赛名称', align: 'center', key: 'competitionName' }, { title: '证书类型', align: 'center', key: 'competitionType' }, { title: '取得名次', align: 'center', key: 'competitionRank' }, { title: '获奖时间', align: 'center', key: 'awardTime' }, ], columns5: [ { title: '新人姓名', align: 'center', key: 'userName' }, { title: '入职时间', align: 'center', key: 'inductionTime' }, { title: '转正时间', align: 'center', key: 'formalTime' }, ], tabletypeValue: { Type: 0, }, radioArr: [ { id: 0, name: '巡检工单' }, { id: 1, name: '保养工单' }, { id: 2, name: '维修工单' }, ], uploadListZG: [], imageZG: [], formInfo: { data: { awardTime: new Date().getTime(), contestIntegralTermId: '', formalTime: new Date().getTime(), inductionTime: new Date().getTime(), competitionType: null, competitionName: '', userName: '', fileNo: [], }, rules: {}, }, }); //分页 const paginationReactive = reactive({ page: 1, pageSize: 10, showSizePicker: true, pageSizes: [10, 20, 50], showQuickJumper: true, pageCount: 0, itemCount: 0, prefix: () => { return '共 ' + paginationReactive.itemCount + ' 项'; }, onChange: (page) => { paginationReactive.page = page; getTableData(); }, onPageSizeChange: (pageSize) => { paginationReactive.pageSize = pageSize; paginationReactive.page = 1; getTableData(); }, }); // 培训列表 async function getTableData() { allData.tableLoading = true; let params = { current: paginationReactive.page, size: paginationReactive.pageSize, data: { trainMonth: allData.month, trainYear: allData.year, userId: props.userId, }, }; let res = await getUserPxlist(params); if (res && res.code == 200) { allData.tableData = res.data.records; paginationReactive.itemCount = res.data.total; } allData.tableLoading = false; } // 绩效成绩列表 async function getJixiaoTableData() { allData.tableLoading3 = true; let params = { userId: props.userId, year: allData.year, }; allData.tableData3 = []; let res = await getUserJxlist(params); if (res && res.code == 200) { let datas = res.data; allData.tableData3 = datas; } allData.tableLoading3 = false; } // 技能证书列表 async function getJinengTableData() { allData.tableLoading4 = true; let params = { current: 1, data: { userId: props.userId, }, size: 99, }; let res = await getUserJnlist(params); if (res && res.code == 200) { allData.tableData4 = res.data.records; } allData.tableLoading4 = false; } // 师徒协议列表 async function getShituTableData() { allData.tableLoading5 = true; let params = { current: 1, data: { userId: props.userId, }, size: 99, }; let res = await getUserStlist(params); if (res && res.code == 200) { allData.tableData5 = res.data.records; } allData.tableLoading5 = false; } //获取用户 async function getUserList() { let res = await getUserData(); if (res && res.code == 200) { let datas = res.data; allData.userList = datas.map((item) => { return { value: item.id, label: item.realName, }; }); } } //获取证书列表 async function getBookList() { let res = await getUserBookList(); if (res && res.code == 200) { let datas = [...res.data]; allData.bookList = datas; allData.competArr1 = datas.map((item) => { return { value: item.id, label: item.typeName, }; }); } } // 证书类型点击 function changBookType(val) { allData.competArr2 = []; let arr = allData.bookList.find((item) => item.id == val).contestIntegralTermList; allData.competArr2 = arr.map((item) => { return { value: item.id, label: item.integralTermName, }; }); allData.formInfo.data.contestIntegralTermId = allData.competArr2[0].value; } //上传证书弹窗 function updataCertificate(val) { allData.radioVal = val; allData.tableShow = true; allData.formInfo.data.competitionName = ''; allData.formInfo.data.competitionType = ''; allData.formInfo.data.contestIntegralTermId = ''; allData.formInfo.data.userName = ''; allData.uploadListZG = []; } // 证书或协议上传和删除 const changeFileZG = async (file) => { $loadingBar.start(); if (file.event) { // 文件上传 let formdata = new FormData(); formdata.append('files', file.file.file); console.log(formdata); let config = { headers: { 'Content-Type': 'multipart/form-data' }, }; let res = await fileUpload(formdata, config); if (res && res.code === 200) { if (res.data.length > 0) { let datas = res.data[0]; allData.formInfo.data.fileNo.push(datas.fileNo); let param = { fileNo: datas.fileNo, name: datas.fileOriginalName, url: datas.fileCloudStorageKey, status: 'success', }; allData.imageZG.push(param); } } else { allData.uploadListZG = []; let param = { id: file.file.id, name: file.file.name, status: 'error', }; allData.uploadListZG.push(param); } $loadingBar.finish(); } else { // 文件删除,根据文件名进行匹配 let fileIndex = null; allData.imageZG.map((item, index) => { if (file.file.name == item.name) { fileIndex = index; } }); let fileNos = []; fileNos.push(allData.imageZG[fileIndex].fileNo); let res = await fileDelete(fileNos); if (res && res.code === 200) { allData.formInfo.data.fileNo.splice(fileIndex, 1); } } }; //获取证书类型、比赛名次label const getQuestLabel = (arry, Value) => { if (!!Value) { let listname = arry.filter((el) => el.value == Value); return listname[0].label; } }; // 证书资料保存 const saveBookData = async () => { if (allData.formInfo.data.fileNo.length < 1) { $message.error('请上传资料'); return false; } if (allData.radioVal == '1') { // 证书资料保存 let params = { awardTime: formatDate(allData.formInfo.data.awardTime), fileNos: allData.formInfo.data.fileNo, competitionName: allData.formInfo.data.competitionName, competitionType: getQuestLabel(allData.competArr1, allData.formInfo.data.competitionType), contestIntegralTermId: allData.formInfo.data.contestIntegralTermId, competitionRank: getQuestLabel(allData.competArr2, allData.formInfo.data.contestIntegralTermId), userId: props.userId, }; let res = await getUserZsSave(params); if (res && res.code == 200) { $message.success('保存成功'); allData.tableShow = false; getJinengTableData(); } } else { // 师徒协议保存 let params = { formalTime: formatDate(allData.formInfo.data.formalTime), fileNos: allData.formInfo.data.fileNo, inductionTime: formatDate(allData.formInfo.data.inductionTime), userId: allData.formInfo.data.userName, teacherId: props.userId, }; let res = await getUserStSave(params); if (res && res.code == 200) { $message.success('保存成功'); allData.tableShow = false; getShituTableData(); } } }; // 查询详情数据 function searchData() { getTableData(); //培训列表 getJixiaoTableData(); //绩效成绩 getJinengTableData(); //技能证书 getShituTableData(); //师徒协议 } onMounted(() => { getBookList(); getUserList(); bus.on('getCurrentData1', (e) => { allData.year = e.year; allData.month = e.month; allData.startTime = `${allData.year}-${allData.month}-01 00:00:00`; allData.endTime = `${allData.year}-${allData.month}-31 23:59:59`; getTableData(); getJixiaoTableData(); }); allData.startTime = `${allData.year}-${allData.month + 1}-01 00:00:00`; allData.endTime = `${allData.year}-${allData.month + 1}-31 23:59:59`; getTableData(); searchData(); getJixiaoTableData(); }); onBeforeMount(() => { bus.off('getCurrentData1'); }); return { ...toRefs(allData), pagination: paginationReactive, updataCertificate, getTableData, getJixiaoTableData, getJinengTableData, getShituTableData, changeFileZG, saveBookData, changBookType, }; }, }; </script> <style lang="less"> .userDetailPage { position: relative; height: 100%; width: 100%; display: flex; flex-wrap: wrap; .title { display: flex; align-items: center; padding-left: 20px; 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; } } .Line { height: 1px; margin-top: 15px; border: 1px solid rgba(57, 139, 198, 1); } .leftInfo { width: 440px; border: 1px solid rgba(57, 139, 198, 1); .topInfo { width: 440px; .userImg { width: 120px; height: 120px; margin-top: 10px; margin-left: 150px; margin-bottom: 20px; background: url('@/assets/newImgs/userJX/defaultperson.jpg') no-repeat center; background-size: 100% 100%; border-radius: 50%; } .n-space { height: 40px; } } .leftcalendar { height: 323px; width: 380px; margin-top: 15px; margin-left: 30px; margin-bottom: 20px; border: 1px solid #25d8f5; } } .centerInfo { width: 810px; border: 1px solid rgba(57, 139, 198, 1); margin-left: 20px; .centerbottom { overflow: auto; tbody, tfoot, thead, tr, th, td { vertical-align: middle; } } } .rightInfo { width: 400px; border: 1px solid rgba(57, 139, 198, 1); margin-left: 20px; } } </style>