Commit 15508d62 authored by sxl's avatar sxl 💬

add:安全人员管理菜单

parent f7600f1a
......@@ -7,5 +7,25 @@ export function getSafePeopleInfo(params = {}) {
params
})
}
export default { getSafePeopleInfo }
export function addPeopleInfo(data = {}) {
return request({
url: '/tab/safePeopleInfo',
method: 'post',
data
})
}
export function editPeopleInfo(data = {}) {
return request({
url: '/tab/safePeopleInfo',
method: 'put',
data
})
}
export function delPeopleInfo(ids) {
return request({
url: `/tab/safePeopleInfo`,
method: 'delete',
data: ids
})
}
export default { getSafePeopleInfo, addPeopleInfo, editPeopleInfo }
......@@ -4,7 +4,7 @@
<div slot="header" class="clearfix">
<span>新增安全人员信息</span>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
<el-row>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
......@@ -19,15 +19,15 @@
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="身份证" prop="idCard">
<el-input v-model="form.idCard" placeholder="请输入身份证" />
<el-form-item label="身份证号码" prop="identityCard">
<el-input v-model="form.identityCard" placeholder="请输入身份证号码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex">
<el-select v-model="form.sex" placeholder="请选择性别" style="width: 100%">
<el-option label="男" value="male" />
<el-option label="女" value="female" />
<el-option label="男" value="1" />
<el-option label="女" value="0" />
</el-select>
</el-form-item>
</el-col>
......@@ -59,8 +59,8 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职称" prop="title">
<el-input v-model="form.title" placeholder="请输入职称" />
<el-form-item label="职称" prop="jobTitle">
<el-input v-model="form.jobTitle" placeholder="请输入职称" />
</el-form-item>
</el-col>
</el-row>
......@@ -68,13 +68,13 @@
<el-col :span="12">
<el-form-item label="学历" prop="education">
<el-select v-model="form.education" placeholder="请选择学历" style="width: 100%">
<el-option label="小学" value="primary" />
<el-option label="初中" value="junior" />
<el-option label="高中" value="senior" />
<el-option label="大专" value="college" />
<el-option label="本科" value="bachelor" />
<el-option label="硕士" value="master" />
<el-option label="博士" value="doctor" />
<el-option label="小学" value="0" />
<el-option label="初中" value="1" />
<el-option label="高中" value="2" />
<el-option label="大专" value="3" />
<el-option label="本科" value="4" />
<el-option label="硕士" value="5" />
<el-option label="博士" value="6" />
</el-select>
</el-form-item>
</el-col>
......@@ -86,13 +86,13 @@
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="紧急联系人" prop="emergencyContact">
<el-input v-model="form.emergencyContact" placeholder="请输入紧急联系人" />
<el-form-item label="紧急联系人" prop="emergencyContactName">
<el-input v-model="form.emergencyContactName" placeholder="请输入紧急联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="紧急联系电话" prop="emergencyPhone">
<el-input v-model="form.emergencyPhone" placeholder="请输入紧急联系电话" />
<el-form-item label="紧急联系人手机号" prop="emergencyContactPhone">
<el-input v-model="form.emergencyContactPhone" placeholder="请输入紧急联系人手机号" />
</el-form-item>
</el-col>
</el-row>
......@@ -103,23 +103,30 @@
v-model="form.entryDate"
type="date"
placeholder="请选择日期"
value-format="yyyy-MM-dd"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="常住地址" prop="address">
<el-input v-model="form.address" placeholder="请输入常住地址" />
<el-form-item label="居住地址" prop="permanentAddress">
<el-input v-model="form.permanentAddress" placeholder="请输入居住地址" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="上传安全证书">
<el-form-item label="安全证书">
<el-upload
action="#"
ref="upload"
:action="uploadUrl"
:data="uploadData"
:headers="uploadHeaders"
:on-error="handleUploadError"
:before-upload="beforeUpload"
list-type="picture-card"
:auto-upload="false"
>
<i slot="default" class="el-icon-plus" />
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2MB</div>
</el-upload>
</el-form-item>
<el-form-item>
......@@ -135,41 +142,68 @@
import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { getDepts } from '@/api/system/dept'
import { getToken } from '@/utils/auth'
import { addPeopleInfo, editPeopleInfo } from '@/api/aqrf/safePersonnel'
import { isvalidPhone } from '@/utils/validate'
export default {
name: 'AddPersonnel',
components: { Treeselect },
data() {
// 自定义验证
const validPhone = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入电话号码'))
} else if (!isvalidPhone(value)) {
callback(new Error('请输入正确的11位手机号码'))
} else {
callback()
}
}
return {
form: {
name: null,
phone: null,
idCard: null,
identityCard: null, // 身份证号码
sex: null,
deptId: null,
job: null,
workType: null,
title: null,
jobTitle: null, // 职称
education: null,
major: null,
emergencyContact: null,
emergencyPhone: null,
major: null, // 专业
emergencyContactName: null, // 紧急联系人
emergencyContactPhone: null, // 紧急联系人手机号
entryDate: null,
address: null
permanentAddress: null // 居住地址
},
depts: [], // 部门数据
uploadUrl: process.env.VUE_APP_BASE_API + '/api/common/upload', // 上传接口
uploadData: {
modelName: 'safe' // 固定参数
},
uploadHeaders: {
'Authorization': getToken()
},
rules: {
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
phone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
idCard: [{ required: true, message: '请输入身份证', trigger: 'blur' }],
phone: [{ required: true, message: '请输入联系电话', validator: validPhone }],
identityCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
job: [{ required: true, message: '请输入职务', trigger: 'blur' }],
education: [{ required: true, message: '请选择学历', trigger: 'change' }]
}
}
},
created() {
this.getDepts()
this.form = this.$route.query.data ? this.$route.query.data : this.form
this.getDepts().then(() => {
// 如果是编辑模式,直接设置部门ID(因为所有数据已加载)
if (this.form.id && this.form.dept) {
this.form.deptId = this.form.dept.id
}
})
},
methods: {
// 数据格式化,将后端数据转换为 treeselect 需要的格式
......@@ -180,43 +214,186 @@ export default {
children: node.children
}
},
// 获取部门数据
getDepts() {
getDepts({ enabled: true }).then(res => {
this.depts = res.content.map(function(obj) {
if (obj.hasChildren) {
obj.children = null
// 获取部门数据(智能加载,只加载必要的层级)
async getDepts() {
// 获取目标部门ID(如果是编辑模式)
const targetDeptId = this.form && this.form.dept ? this.form.dept.id : null
// 先获取所有根部门
const rootRes = await getDepts({ enabled: true })
if (rootRes && rootRes.content) {
this.depts = await this.buildFullDeptTree(rootRes.content, targetDeptId)
}
return rootRes
},
// 构建完整的部门树(智能加载,只加载必要的层级)
async buildFullDeptTree(depts, targetDeptId = null) {
const result = []
// 如果没有指定目标部门ID,从表单中获取
if (!targetDeptId && this.form && this.form.dept) {
targetDeptId = this.form.dept.id
}
for (const dept of depts) {
const deptNode = {
id: dept.id,
name: dept.name,
label: dept.name,
hasChildren: dept.hasChildren
}
// 检查当前层级是否包含目标部门
const currentLevelHasTarget = depts.some(d => d.id === targetDeptId)
// 如果有子部门,判断是否需要递归加载
if (dept.hasChildren) {
// 如果当前层级已经包含目标部门,就不需要继续递归加载了
if (currentLevelHasTarget) {
// 不加载子部门,保持懒加载状态
deptNode.children = null
} else if (!targetDeptId) {
// 如果没有目标部门(新增模式),加载前两层以提供更好的用户体验
try {
const childRes = await getDepts({ enabled: true, pid: dept.id })
if (childRes && childRes.content && childRes.content.length > 0) {
// 只加载一层,不再递归
deptNode.children = childRes.content.map(obj => ({
id: obj.id,
name: obj.name,
label: obj.name,
hasChildren: obj.hasChildren,
children: obj.hasChildren ? null : undefined
}))
}
} catch (error) {
deptNode.children = null
}
} else {
// 编辑模式:为了确保能找到目标部门,采用更保守的策略
// 加载前几层,让懒加载处理更深层的部门
try {
const childRes = await getDepts({ enabled: true, pid: dept.id })
if (childRes && childRes.content && childRes.content.length > 0) {
// 检查直接子级是否包含目标部门
const hasTargetInChildren = childRes.content.some(child => child.id === targetDeptId)
if (hasTargetInChildren) {
deptNode.children = childRes.content.map(obj => ({
id: obj.id,
name: obj.name,
label: obj.name,
hasChildren: obj.hasChildren,
children: obj.hasChildren ? null : undefined
}))
} else {
// 没有在直接子级找到,继续递归一层
deptNode.children = await this.buildFullDeptTree(childRes.content, targetDeptId)
}
}
} catch (error) {
deptNode.children = null
}
}
return obj
})
})
}
result.push(deptNode)
}
return result
},
// 动态加载子部门
// 懒加载方法:用户手动展开时动态加载子部门
loadDepts({ action, parentNode, callback }) {
if (action === LOAD_CHILDREN_OPTIONS) {
getDepts({ enabled: true, pid: parentNode.id }).then(res => {
parentNode.children = res.content.map(function(obj) {
if (obj.hasChildren) {
obj.children = null
}
return obj
})
if (res && res.content) {
parentNode.children = res.content.map(obj => ({
id: obj.id,
name: obj.name,
label: obj.name,
hasChildren: obj.hasChildren,
children: obj.hasChildren ? null : undefined
}))
} else {
parentNode.children = []
}
callback()
}).catch(() => {
parentNode.children = []
callback()
})
}
},
// 统计所有部门数量
countAllDepts(depts) {
let count = 0
for (const dept of depts) {
count++
if (dept.children && dept.children.length > 0) {
count += this.countAllDepts(dept.children)
}
}
return count
},
// 文件上传前的校验
beforeUpload(file) {
const isJPGOrPNG = file.type === 'image/jpeg' || file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPGOrPNG) {
this.$message.error('上传文件只能是 JPG/PNG 格式!')
return false
}
if (!isLt2M) {
this.$message.error('上传文件大小不能超过 2MB!')
return false
}
return true
},
// 文件上传失败回调
handleUploadError(err) {
this.$message.error('文件上传失败')
console.error('Upload error:', err)
},
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
// 在这里处理表单提交逻辑
console.log('Form submitted:', this.form)
this.$message.success('提交成功')
// 检查是否有文件需要上传
if (this.$refs.upload.uploadFiles.length) {
this.uploadAndSave()
}
// 直接保存
this.saveForm()
} else {
this.$message.error('请填写所有必填项')
return false
}
})
},
// 上传文件并保存
uploadAndSave() {
this.$refs.upload.submit()
},
// 保存表单数据
saveForm() {
if (this.form.id) {
delete this.form.dept
editPeopleInfo(this.form).then(() => {
this.$message.success('编辑成功')
this.handleCancel()
}).catch(error => {
this.$message.error('编辑失败:' + (error.message || '未知错误'))
})
} else {
addPeopleInfo(this.form).then(() => {
this.$message.success('保存成功')
this.handleCancel()
}).catch(error => {
this.$message.error('保存失败:' + (error.message || '未知错误'))
})
}
},
handleCancel() {
this.$router.go(-1)
}
......
......@@ -33,9 +33,18 @@
<el-table :data="tableData" :loading="loading" style="width: 100%">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="name" label="姓名" />
<el-table-column prop="sex" label="性别" />
<el-table-column prop="sex" label="性别">
<template slot-scope="scope">
<span v-if="scope.row.sex == 1"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column prop="phone" label="联系方式" />
<el-table-column prop="deptId" label="部门" />
<el-table-column prop="deptId" label="部门">
<template slot-scope="scope">
<span>{{ scope.row.dept ? scope.row.dept.name : '' }}</span>
</template>
</el-table-column>
<el-table-column prop="job" label="职务" />
<el-table-column prop="workType" label="工种" />
<el-table-column prop="entryDate" label="入职时间" />
......@@ -63,7 +72,7 @@
</template>
<script>
import { getSafePeopleInfo } from '@/api/aqrf/safePersonnel'
import { getSafePeopleInfo, delPeopleInfo } from '@/api/aqrf/safePersonnel'
export default {
name: 'SafePersonnel',
......@@ -99,7 +108,7 @@ export default {
const response = await getSafePeopleInfo(params)
if (response && response.data) {
if (response && response.body) {
this.tableData = response.body.list || []
this.pagination.total = response.body.total || 0
} else {
......@@ -140,7 +149,9 @@ export default {
this.$router.push('/aqrf/add-personnel')
},
handleEdit(row) {
console.log('Edit:', row)
this.$router.push({
path: '/aqrf/add-personnel', query: { data: row }
})
},
handleDelete(row) {
this.$confirm('此操作将永久删除该条目, 是否继续?', '提示', {
......@@ -149,10 +160,15 @@ export default {
type: 'warning'
})
.then(() => {
console.log('Delete:', row)
this.$message({
type: 'success',
message: '删除成功!'
delPeopleInfo([row.id]).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
})
this.fetchData()
}).catch((error) => {
console.error('删除失败:', error)
this.$message.error('删除失败')
})
})
.catch(() => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment