hcm前端2版
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
<el-button size="mini" type="primary" icon="el-icon-search" @click="loadEmployee">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="employeeList" v-loading="empLoading" height="700" stripe>
|
||||
<el-table :data="employeeList" v-loading="empLoading" height="700" stripe @row-click="openDetail">
|
||||
<el-table-column label="工号" prop="empNo" min-width="110" />
|
||||
<el-table-column label="姓名" prop="empName" min-width="120" />
|
||||
<el-table-column label="性别" prop="gender" min-width="80" />
|
||||
@@ -66,11 +66,248 @@
|
||||
</el-table>
|
||||
</el-card>
|
||||
</section>
|
||||
|
||||
<el-drawer
|
||||
title="员工档案"
|
||||
:visible.sync="detailVisible"
|
||||
size="60%"
|
||||
append-to-body
|
||||
>
|
||||
<div v-if="detailEmp" class="detail-wrap">
|
||||
<div class="basic-grid">
|
||||
<el-card shadow="hover" class="metal-panel">
|
||||
<div slot="header" class="panel-header">基础信息</div>
|
||||
<el-descriptions :column="2" size="small" border>
|
||||
<el-descriptions-item label="工号">{{ detailEmp.empNo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detailEmp.empName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detailEmp.gender }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机">{{ detailEmp.mobile }}</el-descriptions-item>
|
||||
<el-descriptions-item label="雇佣类型">{{ detailEmp.employmentType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="statusType(detailEmp.status)">{{ detailEmp.status }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="入职日期">{{ formatDate(detailEmp.hireDate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ detailEmp.remark || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="metal-panel" style="margin-top:12px">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>组织/岗位关系</span>
|
||||
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openRelDialog()">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="relList" v-loading="relLoading" size="mini">
|
||||
<el-table-column label="组织" prop="orgId" min-width="160">
|
||||
<template slot-scope="scope">
|
||||
{{ renderOrg(scope.row.orgId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="岗位" prop="positionId" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ renderPosition(scope.row.positionId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="主岗" prop="isPrimary" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="mini" :type="scope.row.isPrimary ? 'success' : 'info'">{{ scope.row.isPrimary ? '是' : '否' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开始" prop="startDate" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.startDate, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束" prop="endDate" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.endDate, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="remark" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" @click="openRelDialog(scope.row)">编辑</el-button>
|
||||
<el-button size="mini" type="text" @click="delRel(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" class="metal-panel" style="margin-top:12px">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>劳动合同</span>
|
||||
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openContractDialog()">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="contractList" v-loading="contractLoading" size="mini">
|
||||
<el-table-column label="编号" prop="contractNo" min-width="120" />
|
||||
<el-table-column label="类型" prop="contractType" min-width="120" />
|
||||
<el-table-column label="开始" prop="startDate" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.startDate, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束" prop="endDate" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.endDate, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" prop="status" min-width="100" />
|
||||
<el-table-column label="备注" prop="remark" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" @click="openContractDialog(scope.row)">编辑</el-button>
|
||||
<el-button size="mini" type="text" @click="delContractRow(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" class="metal-panel" style="margin-top:12px">
|
||||
<div slot="header" class="panel-header">
|
||||
<span>证书</span>
|
||||
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openCertDialog()">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="certList" v-loading="certLoading" size="mini">
|
||||
<el-table-column label="名称" prop="certName" min-width="140" />
|
||||
<el-table-column label="证书编号" prop="certNo" min-width="140" />
|
||||
<el-table-column label="签发机构" prop="issuedBy" min-width="140" />
|
||||
<el-table-column label="有效期自" prop="validFrom" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.validFrom, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="有效期至" prop="validTo" min-width="120">
|
||||
<template slot-scope="scope">{{ formatDate(scope.row.validTo, 'date') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" prop="remark" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" @click="openCertDialog(scope.row)">编辑</el-button>
|
||||
<el-button size="mini" type="text" @click="delCertRow(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<div v-else class="preview-placeholder">请选择员工查看档案</div>
|
||||
</el-drawer>
|
||||
|
||||
<el-dialog
|
||||
title="合同"
|
||||
:visible.sync="contractDialogVisible"
|
||||
width="480px"
|
||||
append-to-body
|
||||
>
|
||||
<el-form :model="contractForm" label-width="100px" size="small">
|
||||
<el-form-item label="合同编号">
|
||||
<el-input v-model="contractForm.contractNo" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-input v-model="contractForm.contractType" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker v-model="contractForm.startDate" type="date" placeholder="开始" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="contractForm.endDate" type="date" placeholder="结束" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-input v-model="contractForm.status" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="contractForm.remark" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="contractDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="contractSubmitting" @click="submitContract">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="证书"
|
||||
:visible.sync="certDialogVisible"
|
||||
width="480px"
|
||||
append-to-body
|
||||
>
|
||||
<el-form :model="certForm" label-width="100px" size="small">
|
||||
<el-form-item label="证书名称">
|
||||
<el-input v-model="certForm.certName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="证书编号">
|
||||
<el-input v-model="certForm.certNo" />
|
||||
</el-form-item>
|
||||
<el-form-item label="签发机构">
|
||||
<el-input v-model="certForm.issuedBy" />
|
||||
</el-form-item>
|
||||
<el-form-item label="有效期自">
|
||||
<el-date-picker v-model="certForm.validFrom" type="date" placeholder="开始" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="有效期至">
|
||||
<el-date-picker v-model="certForm.validTo" type="date" placeholder="结束" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="certForm.remark" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="certDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="certSubmitting" @click="submitCert">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="组织/岗位关系"
|
||||
:visible.sync="relDialogVisible"
|
||||
width="480px"
|
||||
append-to-body
|
||||
>
|
||||
<el-form ref="relFormRef" :model="relForm" :rules="relRules" label-width="100px" size="small">
|
||||
<el-form-item label="组织" prop="orgId">
|
||||
<el-select v-model="relForm.orgId" filterable placeholder="选择组织" style="width: 100%">
|
||||
<el-option
|
||||
v-for="org in flatOrgOptions"
|
||||
:key="org.orgId"
|
||||
:label="org.label"
|
||||
:value="org.orgId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位" prop="positionId">
|
||||
<el-select v-model="relForm.positionId" filterable placeholder="选择岗位" style="width: 100%">
|
||||
<el-option v-for="pos in positionOptions" :key="pos.positionId" :label="pos.positionName || pos.positionId" :value="pos.positionId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="主岗" prop="isPrimary">
|
||||
<el-switch v-model="relForm.isPrimary" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker v-model="relForm.startDate" type="date" placeholder="开始" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="relForm.endDate" type="date" placeholder="结束" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="relForm.remark" type="textarea" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="relDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="relSubmitting" @click="submitRel">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOrg, listEmployee } from '@/api/hrm'
|
||||
import {
|
||||
listOrg,
|
||||
listEmployee,
|
||||
listPosition,
|
||||
listEmpOrgPosition,
|
||||
addEmpOrgPosition,
|
||||
updateEmpOrgPosition,
|
||||
delEmpOrgPosition,
|
||||
listContract,
|
||||
addContract,
|
||||
updateContract,
|
||||
delContract,
|
||||
listCertificate,
|
||||
addCertificate,
|
||||
updateCertificate,
|
||||
delCertificate
|
||||
} from '@/api/hrm'
|
||||
|
||||
export default {
|
||||
name: 'HrmOrgEmployee',
|
||||
@@ -81,22 +318,54 @@ export default {
|
||||
orgSelected: null,
|
||||
employeeList: [],
|
||||
empLoading: false,
|
||||
empQuery: { empName: '', status: undefined, mainOrgId: undefined }
|
||||
empQuery: { empName: '', status: undefined, mainOrgId: undefined },
|
||||
detailVisible: false,
|
||||
detailEmp: null,
|
||||
contractList: [],
|
||||
contractLoading: false,
|
||||
contractDialogVisible: false,
|
||||
contractSubmitting: false,
|
||||
contractForm: {},
|
||||
certList: [],
|
||||
certLoading: false,
|
||||
certDialogVisible: false,
|
||||
certSubmitting: false,
|
||||
certForm: {},
|
||||
relList: [],
|
||||
relLoading: false,
|
||||
relDialogVisible: false,
|
||||
relSubmitting: false,
|
||||
relForm: {},
|
||||
relRules: {
|
||||
orgId: [{ required: true, message: '请选择组织', trigger: 'change' }],
|
||||
positionId: [{ required: true, message: '请选择岗位', trigger: 'change' }],
|
||||
isPrimary: [{ required: true, message: '请选择是否主岗', trigger: 'change' }]
|
||||
},
|
||||
positionOptions: [],
|
||||
positionLoading: false,
|
||||
flatOrgOptions: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadOrg()
|
||||
this.loadEmployee()
|
||||
this.loadPositions()
|
||||
},
|
||||
methods: {
|
||||
loadTree() {
|
||||
// 兼容旧调用,直接复用 loadOrg
|
||||
this.loadOrg()
|
||||
},
|
||||
statusType(status) {
|
||||
if (!status) return 'info'
|
||||
const map = { pending: 'warning', draft: 'info', approved: 'success', rejected: 'danger', active: 'success', inactive: 'info' }
|
||||
return map[status] || 'info'
|
||||
},
|
||||
formatDate(val) {
|
||||
formatDate(val, mode = 'datetime') {
|
||||
if (!val) return ''
|
||||
const d = new Date(val)
|
||||
const p = n => (n < 10 ? `0${n}` : n)
|
||||
if (mode === 'date') return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
||||
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
|
||||
},
|
||||
loadOrg() {
|
||||
@@ -107,6 +376,7 @@ export default {
|
||||
this.orgTree = this.buildTree(rows)
|
||||
if (!this.orgSelected && this.orgTree.length) this.orgSelected = this.orgTree[0].orgId
|
||||
this.empQuery.mainOrgId = this.orgSelected
|
||||
this.buildFlatOrgOptions(this.orgTree)
|
||||
this.loadEmployee()
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -126,6 +396,17 @@ export default {
|
||||
})
|
||||
return roots
|
||||
},
|
||||
buildFlatOrgOptions(orgs) {
|
||||
const flat = []
|
||||
const walk = list => {
|
||||
list.forEach(o => {
|
||||
flat.push({ orgId: o.orgId, label: `${o.orgName || o.orgId}${o.parentName ? ` / ${o.parentName}` : ''}` })
|
||||
if (o.children && o.children.length) walk(o.children)
|
||||
})
|
||||
}
|
||||
walk(orgs || [])
|
||||
this.flatOrgOptions = flat
|
||||
},
|
||||
handleOrgClick(node) {
|
||||
this.orgSelected = node.orgId
|
||||
this.empQuery.mainOrgId = node.orgId
|
||||
@@ -141,6 +422,147 @@ export default {
|
||||
.finally(() => {
|
||||
this.empLoading = false
|
||||
})
|
||||
},
|
||||
openDetail(row) {
|
||||
this.detailEmp = row
|
||||
this.detailVisible = true
|
||||
this.loadContracts(row.empId)
|
||||
this.loadCertificates(row.empId)
|
||||
this.loadEmpOrgRel(row.empId)
|
||||
},
|
||||
loadContracts(empId) {
|
||||
this.contractLoading = true
|
||||
listContract({ empId, pageNum: 1, pageSize: 50 })
|
||||
.then(res => {
|
||||
this.contractList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.contractLoading = false
|
||||
})
|
||||
},
|
||||
openContractDialog(row) {
|
||||
this.contractForm = row ? { ...row } : { empId: this.detailEmp?.empId, status: 'active' }
|
||||
this.contractDialogVisible = true
|
||||
},
|
||||
submitContract() {
|
||||
if (!this.detailEmp) return
|
||||
this.contractSubmitting = true
|
||||
const api = this.contractForm.contractId ? updateContract : addContract
|
||||
api({ ...this.contractForm, empId: this.detailEmp.empId })
|
||||
.then(() => {
|
||||
this.$message.success('已保存')
|
||||
this.contractDialogVisible = false
|
||||
this.loadContracts(this.detailEmp.empId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.contractSubmitting = false
|
||||
})
|
||||
},
|
||||
delContractRow(row) {
|
||||
this.$confirm('确认删除该合同吗?', '提示', { type: 'warning' }).then(() => {
|
||||
delContract(row.contractId).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadContracts(this.detailEmp.empId)
|
||||
})
|
||||
})
|
||||
},
|
||||
loadCertificates(empId) {
|
||||
if (!empId) return
|
||||
this.certLoading = true
|
||||
listCertificate({ empId, pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.certList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.certLoading = false
|
||||
})
|
||||
},
|
||||
loadPositions() {
|
||||
this.positionLoading = true
|
||||
listPosition({ pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.positionOptions = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.positionLoading = false
|
||||
})
|
||||
},
|
||||
loadEmpOrgRel(empId) {
|
||||
if (!empId) return
|
||||
this.relLoading = true
|
||||
listEmpOrgPosition({ empId, pageNum: 1, pageSize: 200 })
|
||||
.then(res => {
|
||||
this.relList = res.rows || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.relLoading = false
|
||||
})
|
||||
},
|
||||
openRelDialog(row) {
|
||||
if (!this.detailEmp) return
|
||||
this.relForm = row
|
||||
? { ...row }
|
||||
: {
|
||||
empId: this.detailEmp.empId,
|
||||
orgId: this.detailEmp.mainOrgId || this.orgSelected || (this.orgTree[0] && this.orgTree[0].orgId),
|
||||
positionId: '',
|
||||
isPrimary: 0,
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
remark: ''
|
||||
}
|
||||
this.relDialogVisible = true
|
||||
this.$nextTick(() => this.$refs.relFormRef && this.$refs.relFormRef.clearValidate())
|
||||
},
|
||||
submitRel() {
|
||||
this.$refs.relFormRef.validate(valid => {
|
||||
if (!valid) return
|
||||
this.relSubmitting = true
|
||||
const api = this.relForm.relId ? updateEmpOrgPosition : addEmpOrgPosition
|
||||
api(this.relForm)
|
||||
.then(() => {
|
||||
this.$message.success('已保存')
|
||||
this.relDialogVisible = false
|
||||
this.loadEmpOrgRel(this.detailEmp.empId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.relSubmitting = false
|
||||
})
|
||||
})
|
||||
},
|
||||
delRel(row) {
|
||||
this.$confirm('确认删除该关系吗?', '提示', { type: 'warning' }).then(() => {
|
||||
delEmpOrgPosition(row.relId).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadEmpOrgRel(this.detailEmp.empId)
|
||||
})
|
||||
})
|
||||
},
|
||||
openCertDialog(row) {
|
||||
this.certForm = row ? { ...row } : { empId: this.detailEmp?.empId }
|
||||
this.certDialogVisible = true
|
||||
},
|
||||
submitCert() {
|
||||
if (!this.detailEmp) return
|
||||
this.certSubmitting = true
|
||||
const api = this.certForm.certId ? updateCertificate : addCertificate
|
||||
api({ ...this.certForm, empId: this.detailEmp.empId })
|
||||
.then(() => {
|
||||
this.$message.success('已保存')
|
||||
this.certDialogVisible = false
|
||||
this.loadCertificates(this.detailEmp.empId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.certSubmitting = false
|
||||
})
|
||||
},
|
||||
delCertRow(row) {
|
||||
this.$confirm('确认删除该证书吗?', '提示', { type: 'warning' }).then(() => {
|
||||
delCertificate(row.certId).then(() => {
|
||||
this.$message.success('已删除')
|
||||
this.loadCertificates(this.detailEmp.empId)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,6 +595,22 @@ export default {
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.detail-wrap {
|
||||
padding-right: 4px;
|
||||
}
|
||||
.basic-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
.preview-placeholder {
|
||||
color: #a0a3ad;
|
||||
font-size: 13px;
|
||||
padding: 12px;
|
||||
background: #fafafa;
|
||||
border: 1px dashed #ebeef5;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.custom-tree-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user