人员库详情

This commit is contained in:
cwchen 2025-10-21 15:06:03 +08:00
parent 622e91e6d3
commit 9c85942ffb
7 changed files with 688 additions and 4 deletions

View File

@ -232,6 +232,20 @@ export const dynamicRoutes = [
meta: { title: '新增人员', activeMenu: '/enterpriseLibrary/personnel', noCache: true }
}
]
},
{
path: '/personnelDetail/',
component: Layout,
hidden: true,
permissions: ['enterpriseLibrary:personnel:detail'],
children: [
{
path: 'index',
component: () => import('@/views/enterpriseLibrary/personnel/components/PersonnelDetail'),
name: 'PersonnelDetail',
meta: { title: '人员详情', activeMenu: '/enterpriseLibrary/personnel', noCache: true }
}
]
}
]

View File

@ -0,0 +1,175 @@
<!-- 人员详情 -->
<template>
<div class="app-container">
<div class="content-header">
<el-button class="reset-btn" @click="handleClose()">返回</el-button>
<!-- <el-button class="search-btn" @click="handleSave()">保存</el-button> -->
</div>
<div class="content-body">
<el-row :gutter="24" class="content-row">
<!-- 基本信息 -->
<el-col :span="6" class="pane-left">
<BasicInfoPersonnelDetail ref="basicInfoPersonnel" @handlePersonnelPosition="handlePersonnelPosition" />
</el-col>
<!-- 资质信息 -->
<el-col :span="6" class="pane-center" v-if="!isProjectChiefEngineer">
<QualificationInfoPersonnelDetail ref="qualificationInfoPersonnel" :personnelPosition="personnelPosition" />
</el-col>
<!-- 其他信息 -->
<el-col :span="6" class="pane-right">
<OtherInfoPersonnelDetail ref="otherInfoPersonnel" />
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import { decryptWithSM4 } from '@/utils/sm'
import BasicInfoPersonnelDetail from './child/BasicInfoDetail.vue'
import QualificationInfoPersonnelDetail from './child/QualificationInfoDetail.vue'
import OtherInfoPersonnelDetail from './child/OtherInfoDetail.vue'
export default {
name: 'PersonnelDetail',
components: {
BasicInfoPersonnelDetail,
QualificationInfoPersonnelDetail,
OtherInfoPersonnelDetail
},
data() {
return {
id: decryptWithSM4(this.$route.query.id),
type: decryptWithSM4(this.$route.query.type),
//
personnelPosition: {
label: '项目经理',
value: 'project_manager',
qualification:'建造师证书、安全考核B证'
},
}
},
methods: {
//
handleClose() {
const obj = { path: "/enterpriseLibrary/enterprise" }
this.$tab.closeOpenPage(obj)
},
//
handlePersonnelPosition(data) {
this.personnelPosition = data;
},
//
async handleSave() {
try {
//
const [basicInfoPersonnelData, qualificationInfoPersonnelData, otherInfoPersonnelData] = await Promise.all([
this.$refs.basicInfoPersonnel.validate(),
this.$refs.qualificationInfoPersonnel.validate(),
this.$refs.otherInfoPersonnel.validate()
])
//
const formData = {
...basicInfoPersonnelData,
...qualificationInfoPersonnelData,
...otherInfoPersonnelData
}
console.log('所有表单校验通过,完整数据:', formData)
//
// await this.saveEnterprise(formData)
this.$message.success('保存成功')
} catch (error) {
// console.error(':', error)
this.$message.error(error.message || '请完善表单信息')
}
}
},
computed: {
//
isProjectChiefEngineer() {
return this.personnelPosition.value === 'project_chief_engineer';
}
}
}
</script>
<style scoped lang="scss">
.app-container {
padding: 24px;
background: linear-gradient(180deg, #F1F6FF 20%, #E5EFFF 100%);
min-height: 100vh;
overflow-y: auto;
}
.content-body {
margin-top: 20px;
}
.content-row {
margin: 0;
display: flex;
flex-wrap: nowrap;
gap: 16px;
}
.pane-left,
.pane-center,
.pane-right {
background: #fff;
border-radius: 16px 16px 16px 16px;
min-height: 600px;
box-shadow: 0px 4px 20px 0px rgba(31, 35, 55, 0.1);
// border: 1px solid #e8f4ff;
padding: 0;
margin-bottom: 20px;
flex: 1;
min-width: 0;
}
.content-header {
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 20px;
gap: 12px;
}
.search-btn {
width: 98px;
height: 36px;
background: #1F72EA;
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
border-radius: 4px;
border: none;
color: #fff;
font-size: 14px;
transition: all 0.3s ease;
&:hover {
background: #4A8BFF;
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
}
}
.reset-btn {
width: 98px;
height: 36px;
background: #FFFFFF;
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
border-radius: 4px;
border: none;
color: #666;
font-size: 14px;
transition: all 0.3s ease;
&:hover {
background: #f5f5f5;
color: #409EFF;
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
}
}
</style>

View File

@ -1,4 +1,4 @@
<!-- 企业主体库表单 -->
<!-- 新增人员表单 -->
<template>
<div class="app-container">
<div class="content-header">

View File

@ -0,0 +1,168 @@
<template>
<div>
<div class="basic-info-title">
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="基本信息">
<span>基本信息</span>
</div>
<el-form :model="form" :rules="rules" ref="basicInfoForm" label-width="110px" label-position="top">
<el-form-item label="人员职位" prop="personnelPosition">
<el-select class="form-item" v-model="form.personnelPosition" placeholder="请选择人员职位" @change="handlePersonnelPositionChange">
<el-option v-for="item in dict.type.personnel_position" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<!-- 身份证人面像 -->
<el-form-item label="身份证人面像" prop="fileList">
<UploadFile :fileList="form.fileList" />
</el-form-item>
<!-- 身份证国徽面 -->
<el-form-item label="身份证国徽面" prop="fileList2">
<UploadFile :fileList="form.fileList2" />
</el-form-item>
<el-form-item label="人员姓名" prop="personnelName">
<el-input v-model="form.personnelName" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="入职时间" prop="employmentDate">
<el-date-picker class="form-item" v-model="form.employmentDate" placeholder="请选择入职时间"
value-format="yyyy-MM-dd" type="date"></el-date-picker>
</el-form-item>
<el-form-item label="从业年限" prop="employmentYears">
<el-input min="0" max="60" type="number" v-model="form.employmentYears" placeholder="请输入从业年限"></el-input>
</el-form-item>
<!-- 学历证书 -->
<el-form-item label="学历证书" prop="fileList3">
<UploadFile :fileList="form.fileList3" uploadType="png、jpg、jpeg、pdf" />
</el-form-item>
<el-form-item label="毕业院校" prop="graduateSchool">
<el-input v-model="form.graduateSchool" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="毕业专业" prop="graduationMajor">
<el-input v-model="form.graduationMajor" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="学历" prop="qualification">
<el-input v-model="form.qualification" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="毕业时间" prop="graduationDate">
<el-date-picker class="form-item" v-model="form.graduationDate" placeholder="自动提取"
value-format="yyyy-MM-dd" type="date"></el-date-picker>
</el-form-item>
<el-form-item label="联系方式" prop="personnelPhone">
<el-input v-model="form.personnelPhone" placeholder="请输入联系方式"></el-input>
</el-form-item>
<el-form-item label="劳动合同" prop="fileList4">
<UploadFile :fileList="form.fileList4" uploadType="pdf、doc、docx" maxFileTips="100MB"/>
</el-form-item>
</el-form>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'BasicInfoPersonnelDetail',
dicts: ['personnel_position'],
components: {
UploadFile
},
data() {
return {
form: {
personnelPosition: '',
personnelName: '',
employmentDate: '',
employmentYears:'',
graduateSchool: '',
graduationMajor: '',
qualification:'',
graduationDate:'',
personnelPhone:'',
fileList: [],
fileList2: [],
fileList3: [],
fileList4: []
},
rules: {
personnelPosition: [
{ required: true, message: '请选择人员职位', trigger: 'blur' }
],
personnelName: [
{ required: true, message: '请输入人员姓名', trigger: 'blur' }
],
employmentDate: [
{ required: true, message: '请选择入职时间', trigger: 'change' }
],
employmentYears: [
{ required: true, message: '请输入从业年限', trigger: 'blur' }
],
graduateSchool: [
{ required: true, message: '请输入毕业院校', trigger: 'blur' }
],
graduationMajor: [
{ required: true, message: '请输入毕业专业', trigger: 'blur' }
],
qualification: [
{ required: true, message: '请输入学历', trigger: 'blur' }
],
graduationDate: [
{ required: true, message: '请选择毕业时间', trigger: 'change' }
],
personnelPhone: [
{ required: true, message: '请输入联系方式', trigger: 'blur' }
],
fileList: [
{ required: true, message: '请上传身份证人面像', trigger: 'blur' }
],
fileList2: [
{ required: true, message: '请上传身份证国徽面', trigger: 'blur' }
],
fileList3: [
{ required: true, message: '请上传学历证书', trigger: 'blur' }
],
fileList4: [
{ required: true, message: '请上传劳动合同', trigger: 'blur' }
],
}
}
},
methods: {
//
validate() {
return new Promise((resolve, reject) => {
this.$refs.basicInfoForm.validate((valid) => {
if (valid) {
resolve(this.form) //
} else {
reject(new Error('基本信息未填写完整'))
}
})
})
},
//
handlePersonnelPositionChange(){
const data = this.dict.type.personnel_position.find(item => item.value === this.form.personnelPosition);
const obj = {
label: data.label,
value: data.value,
qualification:data.raw.remark
}
this.$emit('handlePersonnelPosition', obj);
}
},
}
</script>
<style scoped lang="scss">
.basic-info-title {
display: flex;
align-items: center;
margin: 10px 0;
span {
margin: 0 5px;
font-size: 20px;
}
}
.form-item {
width: 100%;
}
</style>

View File

@ -0,0 +1,94 @@
<template>
<div>
<div class="basic-info-title">
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="其他信息">
<span>其他信息</span>
</div>
<el-form :model="form" :rules="rules" ref="accountOpeningCertificateForm" label-width="110px"
label-position="top">
<el-form-item label="职称证" prop="fileList">
<UploadFile :fileList="form.fileList" uploadType="png、jpg、jpeg、pdf"/>
</el-form-item>
<el-form-item label="职称名称" prop="titleName">
<el-input v-model="form.titleName" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="专业名称" prop="professionalName">
<el-input v-model="form.professionalName" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="证书编号" prop="certificateCode">
<el-input v-model="form.certificateCode" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="人员简介" prop="personnelIntroduction">
<el-input type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" class="form-item"
v-model="form.personnelIntroduction" clearable show-word-limit placeholder="请输入人员简介" maxlength="255"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'OtherInfoPersonnelDetail',
components: { UploadFile },
data() {
return {
form: {
fileList: [],
titleName: '',
professionalName: '',
certificateCode: '',
personnelIntroduction: '',
},
rules: {
fileList: [
{ required: true, message: '请上传职称证', trigger: 'blur' }
],
titleName: [
{ required: true, message: '请输入职称名称', trigger: 'blur' }
],
professionalName: [
{ required: true, message: '请输入专业名称', trigger: 'blur' }
],
certificateCode: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
personnelIntroduction: [
{ required: true, message: '请输入人员简介', trigger: 'blur' }
],
}
}
},
methods: {
//
validate() {
return new Promise((resolve, reject) => {
this.$refs.accountOpeningCertificateForm.validate((valid) => {
if (valid) {
resolve(this.form) //
} else {
reject(new Error('其他信息未填写完整'))
}
})
})
},
},
}
</script>
<style scoped lang="scss">
.basic-info-title {
display: flex;
align-items: center;
margin: 10px 0;
span {
margin: 0 5px;
font-size: 20px;
}
}
.form-item {
width: 100%;
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div>
<div class="basic-info-title">
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="资质信息">
<span>资质信息</span>
</div>
<el-form :model="form" :rules="rules" ref="legalPersonForm" label-width="110px" label-position="top">
<!-- 建造师证书 -->
<template v-if="isProjectManager">
<el-form-item label="建造师证书" prop="fileList">
<UploadFile :fileList="form.fileList" uploadType="png、jpg、jpeg、pdf"/>
</el-form-item>
<el-form-item label="专业类型" prop="professionalType">
<el-input v-model="form.professionalType" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="证书编号" prop="certificateCode">
<el-input v-model="form.certificateCode" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="级别" prop="certificateLevel">
<el-input v-model="form.certificateLevel" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="证书有效期" prop="certificateValidityPeriod">
<el-input v-model="form.certificateValidityPeriod" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="使用有效期" prop="useValidityPeriod">
<el-input v-model="form.useValidityPeriod" placeholder="自动提取"></el-input>
</el-form-item>
</template>
<!-- 安全考核B证安全考核C证其他人员证书 -->
<template>
<el-form-item :label="certificateName" prop="fileList2">
<UploadFile :fileList="form.fileList2" uploadType="png、jpg、jpeg、pdf"/>
</el-form-item>
<el-form-item label="证书编号" prop="certificateCode2">
<el-input v-model="form.certificateCode2" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="证书有效期" prop="certificateValidityPeriod2">
<el-input v-model="form.certificateValidityPeriod2" placeholder="自动提取"></el-input>
</el-form-item>
<el-form-item label="注册专业" prop="registerProfessional">
<el-input v-model="form.registerProfessional" placeholder="自动提取"></el-input>
</el-form-item>
</template>
</el-form>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'QualificationInfoPersonnelDetail',
components: { UploadFile },
props: {
personnelPosition: {
type: Object,
default: () => ({
label: '项目经理',
value: 'project_manager',
qualification: '建造师证书、安全考核B证'
})
},
},
data() {
return {
form: {
professionalType: '',
certificateCode: '',
certificateLevel: '',
certificateValidityPeriod: '',
useValidityPeriod: '',
certificateCode2: '',
certificateValidityPeriod2: '',
registerProfessional: '',
fileList: [],
fileList2: [],
},
rules: {
professionalType: [
{ required: true, message: '请输入专业类型', trigger: 'blur' }
],
certificateCode: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateLevel: [
{ required: true, message: '请输入证书级别', trigger: 'blur' }
],
certificateValidityPeriod: [
{ required: true, message: '请输入证书有效期', trigger: 'blur' }
],
useValidityPeriod: [
{ required: true, message: '请输入使用有效期', trigger: 'blur' }
],
certificateCode2: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateValidityPeriod2: [
{ required: true, message: '请输入证书有效期', trigger: 'blur' }
],
registerProfessional: [
{ required: true, message: '请输入注册专业', trigger: 'blur' }
],
fileList: [
{ required: true, message: '请上传建造师证书', trigger: 'blur' }
],
fileList2: [
{ required: true, message: '请上传安全考核B证', trigger: 'blur' }
],
}
}
},
methods: {
//
switchValidate(newVal) {
if (newVal.value === 'project_manager') {
this.rules = {
professionalType: [
{ required: true, message: '请输入专业类型', trigger: 'blur' }
],
certificateCode: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateLevel: [
{ required: true, message: '请输入证书级别', trigger: 'blur' }
],
certificateValidityPeriod: [
{ required: true, message: '请输入证书有效期', trigger: 'blur' }
],
useValidityPeriod: [
{ required: true, message: '请输入使用有效期', trigger: 'blur' }
],
certificateCode2: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateValidityPeriod2: [
{ required: true, message: '请输入证书有效期', trigger: 'blur' }
],
registerProfessional: [
{ required: true, message: '请输入注册专业', trigger: 'blur' }
],
fileList: [
{ required: true, message: '请上传建造师证书', trigger: 'blur' }
],
fileList2: [
{ required: true, message: '请上传安全考核B证', trigger: 'blur' }
],
}
}else{
this.rules = {
certificateCode2: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateValidityPeriod2: [
{ required: true, message: '请输入证书有效期', trigger: 'blur' }
],
registerProfessional: [
{ required: true, message: '请输入注册专业', trigger: 'blur' }
],
fileList2: [
{ required: true, message: '请上传' + this.certificateName, trigger: 'blur' }
],
}
}
//
this.$nextTick(() => {
this.$refs.legalPersonForm.clearValidate();
})
},
//
validate() {
return new Promise((resolve, reject) => {
this.$refs.legalPersonForm.validate((valid) => {
if (valid) {
resolve(this.form) //
} else {
reject(new Error('资质信息未填写完整'))
}
})
})
},
},
watch: {
personnelPosition: {
handler(newVal) {
console.log(newVal);
this.switchValidate(newVal);
},
immediate: true
},
},
computed: {
//
isProjectManager() {
console.log(this.personnelPosition.value === 'project_manager');
return this.personnelPosition.value === 'project_manager';
},
//
certificateName() {
const result = this.personnelPosition.qualification.split('、').filter(item => !item.includes('建造师证书'));
return result[0];
},
}
}
</script>
<style scoped lang="scss">
.basic-info-title {
display: flex;
align-items: center;
margin: 10px 0;
span {
margin: 0 5px;
font-size: 20px;
}
}
</style>

View File

@ -229,10 +229,15 @@ export default {
})
},
//
//
handleDetail(personnel) {
console.log('查看详情', personnel)
this.$message.info(`查看${personnel.name}的详情`)
this.$router.push({
name: 'PersonnelDetail',
query: {
type: encryptWithSM4('detail'),
id: encryptWithSM4(''),
}
})
},
//