feat: 岗位管理模块前端实现
前端实现:
- post.js: API接口封装(86行,8个接口)
- getPostList(): 分页查询
- getPostListByDept(): 按部门查询
- getPostListEnabled(): 获取启用的岗位
- getPostById(): 查询详情
- createPost(): 创建岗位
- updatePost(): 更新岗位
- deletePost(): 删除岗位
- updatePostStatus(): 更新状态
- post.vue: 岗位管理页面(416行)
- 搜索功能:岗位编码、名称、所属部门(树选择)、状态
- 表格展示:编码、名称、部门、职责、排序、状态、时间
- 状态开关:el-switch直接切换状态
- 新增/编辑对话框:
* 岗位编码、名称(必填)
* 所属部门(树选择器)
* 岗位职责、岗位要求(多行文本)
* 排序号、状态、备注
技术特点:
- 部门树选择器(el-tree-select)
- 状态开关(el-switch)
- 表单验证(必填项)
- 删除确认
模块状态:✅ 完整(前端+后端)
This commit is contained in:
parent
2b7c43366b
commit
84adda022e
85
fund-admin/src/api/post.js
Normal file
85
fund-admin/src/api/post.js
Normal file
@ -0,0 +1,85 @@
|
||||
import request from '../utils/request'
|
||||
|
||||
/**
|
||||
* 获取岗位列表(分页)
|
||||
*/
|
||||
export const getPostList = (params) => {
|
||||
return request({
|
||||
url: '/sys/api/v1/post/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据部门ID获取岗位列表
|
||||
*/
|
||||
export const getPostListByDept = (deptId) => {
|
||||
return request({
|
||||
url: `/sys/api/v1/post/list/dept/${deptId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有启用的岗位列表
|
||||
*/
|
||||
export const getPostListEnabled = () => {
|
||||
return request({
|
||||
url: '/sys/api/v1/post/list/enabled',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取岗位详情
|
||||
*/
|
||||
export const getPostById = (postId) => {
|
||||
return request({
|
||||
url: `/sys/api/v1/post/${postId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建岗位
|
||||
*/
|
||||
export const createPost = (data) => {
|
||||
return request({
|
||||
url: '/sys/api/v1/post',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新岗位
|
||||
*/
|
||||
export const updatePost = (postId, data) => {
|
||||
return request({
|
||||
url: `/sys/api/v1/post/${postId}`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除岗位
|
||||
*/
|
||||
export const deletePost = (postId) => {
|
||||
return request({
|
||||
url: `/sys/api/v1/post/${postId}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新岗位状态
|
||||
*/
|
||||
export const updatePostStatus = (postId, status) => {
|
||||
return request({
|
||||
url: `/sys/api/v1/post/${postId}/status`,
|
||||
method: 'put',
|
||||
params: { status }
|
||||
})
|
||||
}
|
||||
415
fund-admin/src/views/system/post.vue
Normal file
415
fund-admin/src/views/system/post.vue
Normal file
@ -0,0 +1,415 @@
|
||||
<template>
|
||||
<div class="post-container">
|
||||
<el-card>
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :inline="true" :model="searchForm">
|
||||
<el-form-item label="岗位编码">
|
||||
<el-input v-model="searchForm.postCode" placeholder="请输入岗位编码" clearable style="width: 150px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位名称">
|
||||
<el-input v-model="searchForm.postName" placeholder="请输入岗位名称" clearable style="width: 150px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门">
|
||||
<el-tree-select
|
||||
v-model="searchForm.deptId"
|
||||
:data="deptTreeOptions"
|
||||
placeholder="请选择部门"
|
||||
clearable
|
||||
check-strictly
|
||||
:render-after-expand="false"
|
||||
style="width: 200px;"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="searchForm.status" placeholder="请选择状态" clearable style="width: 120px;">
|
||||
<el-option label="启用" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作栏 -->
|
||||
<el-row style="margin-bottom: 15px;">
|
||||
<el-button type="primary" @click="handleAdd">新增岗位</el-button>
|
||||
</el-row>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table :data="tableData" border v-loading="loading" stripe>
|
||||
<el-table-column prop="postId" label="岗位ID" width="80" />
|
||||
<el-table-column prop="postCode" label="岗位编码" width="120" />
|
||||
<el-table-column prop="postName" label="岗位名称" width="150" />
|
||||
<el-table-column prop="deptId" label="所属部门" width="150">
|
||||
<template #default="{ row }">
|
||||
{{ getDeptName(row.deptId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="postDuty" label="岗位职责" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="sortOrder" label="排序" width="80" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="handleStatusChange(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createdTime" label="创建时间" width="180" />
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<el-pagination
|
||||
v-model:current-page="page.current"
|
||||
v-model:page-size="page.size"
|
||||
:total="page.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="fetchData"
|
||||
@current-change="fetchData"
|
||||
style="margin-top: 20px; justify-content: flex-end;"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="form.postId ? '编辑岗位' : '新增岗位'"
|
||||
width="600px"
|
||||
>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位编码" prop="postCode">
|
||||
<el-input v-model="form.postCode" placeholder="请输入岗位编码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="岗位名称" prop="postName">
|
||||
<el-input v-model="form.postName" placeholder="请输入岗位名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="所属部门" prop="deptId">
|
||||
<el-tree-select
|
||||
v-model="form.deptId"
|
||||
:data="deptTreeOptions"
|
||||
placeholder="请选择部门"
|
||||
clearable
|
||||
check-strictly
|
||||
:render-after-expand="false"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="岗位职责">
|
||||
<el-input
|
||||
v-model="form.postDuty"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入岗位职责描述"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="岗位要求">
|
||||
<el-input
|
||||
v-model="form.postRequirement"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入岗位要求"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排序号">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" style="width: 100%;" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :value="1">启用</el-radio>
|
||||
<el-radio :value="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
getPostList,
|
||||
createPost,
|
||||
updatePost,
|
||||
deletePost,
|
||||
updatePostStatus
|
||||
} from '../../api/post'
|
||||
import { getDeptTree } from '../../api/dept'
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
postCode: '',
|
||||
postName: '',
|
||||
deptId: null,
|
||||
status: null
|
||||
})
|
||||
|
||||
// 表格数据
|
||||
const tableData = ref([])
|
||||
const loading = ref(false)
|
||||
|
||||
// 分页
|
||||
const page = reactive({
|
||||
current: 1,
|
||||
size: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 对话框
|
||||
const dialogVisible = ref(false)
|
||||
const formRef = ref(null)
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
postId: null,
|
||||
postCode: '',
|
||||
postName: '',
|
||||
postDuty: '',
|
||||
postRequirement: '',
|
||||
deptId: null,
|
||||
sortOrder: 0,
|
||||
status: 1,
|
||||
remark: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = {
|
||||
postCode: [
|
||||
{ required: true, message: '请输入岗位编码', trigger: 'blur' }
|
||||
],
|
||||
postName: [
|
||||
{ required: true, message: '请输入岗位名称', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
// 部门树选项
|
||||
const deptTreeOptions = ref([])
|
||||
|
||||
// 部门映射(用于显示部门名称)
|
||||
const deptMap = ref({})
|
||||
|
||||
// 加载部门树
|
||||
const loadDeptTree = async () => {
|
||||
try {
|
||||
const data = await getDeptTree()
|
||||
deptTreeOptions.value = convertToTreeSelect(data)
|
||||
buildDeptMap(data)
|
||||
} catch (error) {
|
||||
console.error('加载部门树失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为TreeSelect格式
|
||||
const convertToTreeSelect = (data) => {
|
||||
return data.map(item => ({
|
||||
value: item.deptId,
|
||||
label: item.deptName,
|
||||
children: item.children ? convertToTreeSelect(item.children) : []
|
||||
}))
|
||||
}
|
||||
|
||||
// 构建部门映射
|
||||
const buildDeptMap = (data) => {
|
||||
data.forEach(item => {
|
||||
deptMap.value[item.deptId] = item.deptName
|
||||
if (item.children && item.children.length > 0) {
|
||||
buildDeptMap(item.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取部门名称
|
||||
const getDeptName = (deptId) => {
|
||||
return deptMap.value[deptId] || '-'
|
||||
}
|
||||
|
||||
// 加载数据
|
||||
const fetchData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
current: page.current,
|
||||
size: page.size,
|
||||
postCode: searchForm.postCode || undefined,
|
||||
postName: searchForm.postName || undefined,
|
||||
deptId: searchForm.deptId || undefined,
|
||||
status: searchForm.status !== null && searchForm.status !== '' ? searchForm.status : undefined
|
||||
}
|
||||
const res = await getPostList(params)
|
||||
tableData.value = res.records
|
||||
page.total = res.total
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
ElMessage.error(error.message || '加载数据失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
page.current = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
searchForm.postCode = ''
|
||||
searchForm.postName = ''
|
||||
searchForm.deptId = null
|
||||
searchForm.status = null
|
||||
page.current = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
// 新增
|
||||
const handleAdd = () => {
|
||||
Object.assign(form, {
|
||||
postId: null,
|
||||
postCode: '',
|
||||
postName: '',
|
||||
postDuty: '',
|
||||
postRequirement: '',
|
||||
deptId: null,
|
||||
sortOrder: 0,
|
||||
status: 1,
|
||||
remark: ''
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑
|
||||
const handleEdit = (row) => {
|
||||
Object.assign(form, {
|
||||
postId: row.postId,
|
||||
postCode: row.postCode,
|
||||
postName: row.postName,
|
||||
postDuty: row.postDuty,
|
||||
postRequirement: row.postRequirement,
|
||||
deptId: row.deptId,
|
||||
sortOrder: row.sortOrder,
|
||||
status: row.status,
|
||||
remark: row.remark
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
} catch (error) {
|
||||
ElMessage.warning('请检查表单填写是否完整')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (form.postId) {
|
||||
await updatePost(form.postId, form)
|
||||
ElMessage.success('更新成功')
|
||||
} else {
|
||||
await createPost(form)
|
||||
ElMessage.success('创建成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
await fetchData()
|
||||
} catch (error) {
|
||||
console.error('保存失败:', error)
|
||||
ElMessage.error(error.message || '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 状态变更
|
||||
const handleStatusChange = async (row) => {
|
||||
try {
|
||||
await updatePostStatus(row.postId, row.status)
|
||||
ElMessage.success('状态更新成功')
|
||||
} catch (error) {
|
||||
console.error('状态更新失败:', error)
|
||||
ElMessage.error(error.message || '状态更新失败')
|
||||
// 回滚状态
|
||||
row.status = row.status === 1 ? 0 : 1
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除该岗位吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
await deletePost(row.postId)
|
||||
ElMessage.success('删除成功')
|
||||
|
||||
// 如果是最后一条且不是第一页,返回上一页
|
||||
if (tableData.value.length === 1 && page.current > 1) {
|
||||
page.current--
|
||||
}
|
||||
|
||||
await fetchData()
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error)
|
||||
ElMessage.error(error.message || '删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
loadDeptTree()
|
||||
fetchData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.post-container {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user