hcm前端2版

This commit is contained in:
2025-12-22 16:54:11 +08:00
parent 007c450f63
commit 646b55048b
3 changed files with 863 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
<template>
<div class="hrm-page">
<el-card class="metal-panel" shadow="hover">
<div slot="header" class="panel-header">
<span>岗位与职级维护</span>
</div>
<el-tabs v-model="activeTab">
<el-tab-pane label="岗位" name="position">
<div class="actions-inline mb8">
<el-input v-model="posQuery.positionName" size="mini" placeholder="岗位名称" clearable style="width: 200px" @keyup.enter.native="loadPosition" />
<el-button size="mini" type="primary" icon="el-icon-search" @click="loadPosition">查询</el-button>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openPosDialog()">新增</el-button>
</div>
<el-table :data="positionList" v-loading="posLoading" height="480" stripe>
<el-table-column label="岗位名称" prop="positionName" min-width="160" />
<el-table-column label="岗位编码" prop="positionCode" min-width="140" />
<el-table-column label="职级" prop="gradeId" min-width="140">
<template slot-scope="scope">{{ renderGrade(scope.row.gradeId) }}</template>
</el-table-column>
<el-table-column label="备注" prop="remark" min-width="180" show-overflow-tooltip />
<el-table-column label="操作" width="160" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openPosDialog(scope.row)">编辑</el-button>
<el-button type="text" size="mini" @click="delPos(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="职级" name="grade">
<div class="actions-inline mb8">
<el-input v-model="gradeQuery.gradeName" size="mini" placeholder="职级名称" clearable style="width: 200px" @keyup.enter.native="loadGrade" />
<el-button size="mini" type="primary" icon="el-icon-search" @click="loadGrade">查询</el-button>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openGradeDialog()">新增</el-button>
</div>
<el-table :data="gradeList" v-loading="gradeLoading" height="480" stripe>
<el-table-column label="职级名称" prop="gradeName" min-width="160" />
<el-table-column label="职级编码" prop="gradeCode" min-width="140" />
<el-table-column label="等级" prop="gradeLevel" min-width="100" />
<el-table-column label="备注" prop="remark" min-width="180" show-overflow-tooltip />
<el-table-column label="操作" width="160" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openGradeDialog(scope.row)">编辑</el-button>
<el-button type="text" size="mini" @click="delGradeRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</el-card>
<!-- 岗位弹窗 -->
<el-dialog :visible.sync="posDialogVisible" title="岗位" width="420px" append-to-body>
<el-form ref="posFormRef" :model="posForm" :rules="posRules" label-width="90px" size="small">
<el-form-item label="岗位名称" prop="positionName">
<el-input v-model="posForm.positionName" />
</el-form-item>
<el-form-item label="岗位编码" prop="positionCode">
<el-input v-model="posForm.positionCode" />
</el-form-item>
<el-form-item label="职级" prop="gradeId">
<el-select v-model="posForm.gradeId" placeholder="选择职级" filterable style="width: 100%">
<el-option v-for="g in gradeList" :key="g.gradeId" :label="g.gradeName || g.gradeId" :value="g.gradeId" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="posForm.remark" type="textarea" :rows="2" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="posDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="posSubmitting" @click="submitPos">保存</el-button>
</div>
</el-dialog>
<!-- 职级弹窗 -->
<el-dialog :visible.sync="gradeDialogVisible" title="职级" width="420px" append-to-body>
<el-form ref="gradeFormRef" :model="gradeForm" :rules="gradeRules" label-width="90px" size="small">
<el-form-item label="职级名称" prop="gradeName">
<el-input v-model="gradeForm.gradeName" />
</el-form-item>
<el-form-item label="职级编码" prop="gradeCode">
<el-input v-model="gradeForm.gradeCode" />
</el-form-item>
<el-form-item label="等级" prop="gradeLevel">
<el-input-number v-model="gradeForm.gradeLevel" :min="1" :max="20" controls-position="right" style="width: 100%" />
</el-form-item>
<el-form-item label="备注">
<el-input v-model="gradeForm.remark" type="textarea" :rows="2" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="gradeDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="gradeSubmitting" @click="submitGrade">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listPosition,
addPosition,
updatePosition,
delPosition,
listGrade,
addGrade,
updateGrade,
delGrade
} from '@/api/hrm'
export default {
name: 'HrmPosition',
data() {
return {
activeTab: 'position',
positionList: [],
posLoading: false,
posQuery: { positionName: '' },
posDialogVisible: false,
posSubmitting: false,
posForm: {},
posRules: {
positionName: [{ required: true, message: '请输入岗位名称', trigger: 'blur' }],
positionCode: [{ required: true, message: '请输入岗位编码', trigger: 'blur' }]
},
gradeList: [],
gradeLoading: false,
gradeQuery: { gradeName: '' },
gradeDialogVisible: false,
gradeSubmitting: false,
gradeForm: {},
gradeRules: {
gradeName: [{ required: true, message: '请输入职级名称', trigger: 'blur' }],
gradeCode: [{ required: true, message: '请输入职级编码', trigger: 'blur' }]
}
}
},
created() {
this.loadGrade()
this.loadPosition()
},
methods: {
renderGrade(id) {
const g = this.gradeList.find(i => i.gradeId === id)
return g ? `${g.gradeName || ''}${g.gradeCode ? ` (${g.gradeCode})` : ''}` : id
},
// 职位
loadPosition() {
this.posLoading = true
listPosition({ ...this.posQuery, pageNum: 1, pageSize: 200 })
.then(res => {
this.positionList = res.rows || []
})
.finally(() => {
this.posLoading = false
})
},
openPosDialog(row) {
this.posForm = row ? { ...row } : { positionName: '', positionCode: '', gradeId: undefined, remark: '' }
this.posDialogVisible = true
this.$nextTick(() => this.$refs.posFormRef && this.$refs.posFormRef.clearValidate())
},
submitPos() {
this.$refs.posFormRef.validate(valid => {
if (!valid) return
this.posSubmitting = true
const api = this.posForm.positionId ? updatePosition : addPosition
api(this.posForm)
.then(() => {
this.$message.success('已保存')
this.posDialogVisible = false
this.loadPosition()
})
.finally(() => {
this.posSubmitting = false
})
})
},
delPos(row) {
this.$confirm('确认删除该岗位吗?', '提示', { type: 'warning' }).then(() => {
delPosition(row.positionId).then(() => {
this.$message.success('已删除')
this.loadPosition()
})
})
},
// 职级
loadGrade() {
this.gradeLoading = true
listGrade({ ...this.gradeQuery, pageNum: 1, pageSize: 200 })
.then(res => {
this.gradeList = res.rows || []
})
.finally(() => {
this.gradeLoading = false
})
},
openGradeDialog(row) {
this.gradeForm = row ? { ...row } : { gradeName: '', gradeCode: '', gradeLevel: 1, remark: '' }
this.gradeDialogVisible = true
this.$nextTick(() => this.$refs.gradeFormRef && this.$refs.gradeFormRef.clearValidate())
},
submitGrade() {
this.$refs.gradeFormRef.validate(valid => {
if (!valid) return
this.gradeSubmitting = true
const api = this.gradeForm.gradeId ? updateGrade : addGrade
api(this.gradeForm)
.then(() => {
this.$message.success('已保存')
this.gradeDialogVisible = false
this.loadGrade()
this.loadPosition() // 更新岗位职级展示
})
.finally(() => {
this.gradeSubmitting = false
})
})
},
delGradeRow(row) {
this.$confirm('确认删除该职级吗?', '提示', { type: 'warning' }).then(() => {
delGrade(row.gradeId).then(() => {
this.$message.success('已删除')
this.loadGrade()
this.loadPosition()
})
})
}
}
}
</script>
<style lang="scss" scoped>
.hrm-page {
padding: 16px 20px 32px;
background: #f8f9fb;
}
.metal-panel {
border: 1px solid #d7d9df;
border-radius: 10px;
background: #fff;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 600;
color: #303133;
}
.actions-inline {
display: flex;
gap: 8px;
align-items: center;
}
.mb8 {
margin-bottom: 8px;
}
</style>