Commit 15508d62 authored by sxl's avatar sxl 💬

add:安全人员管理菜单

parent f7600f1a
...@@ -7,5 +7,25 @@ export function getSafePeopleInfo(params = {}) { ...@@ -7,5 +7,25 @@ export function getSafePeopleInfo(params = {}) {
params params
}) })
} }
export function addPeopleInfo(data = {}) {
export default { getSafePeopleInfo } 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 @@ ...@@ -4,7 +4,7 @@
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>新增安全人员信息</span> <span>新增安全人员信息</span>
</div> </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-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="姓名" prop="name"> <el-form-item label="姓名" prop="name">
...@@ -19,15 +19,15 @@ ...@@ -19,15 +19,15 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="身份证" prop="idCard"> <el-form-item label="身份证号码" prop="identityCard">
<el-input v-model="form.idCard" placeholder="请输入身份证" /> <el-input v-model="form.identityCard" placeholder="请输入身份证号码" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="性别" prop="sex"> <el-form-item label="性别" prop="sex">
<el-select v-model="form.sex" placeholder="请选择性别" style="width: 100%"> <el-select v-model="form.sex" placeholder="请选择性别" style="width: 100%">
<el-option label="男" value="male" /> <el-option label="男" value="1" />
<el-option label="女" value="female" /> <el-option label="女" value="0" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
...@@ -59,8 +59,8 @@ ...@@ -59,8 +59,8 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="职称" prop="title"> <el-form-item label="职称" prop="jobTitle">
<el-input v-model="form.title" placeholder="请输入职称" /> <el-input v-model="form.jobTitle" placeholder="请输入职称" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
...@@ -68,13 +68,13 @@ ...@@ -68,13 +68,13 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="学历" prop="education"> <el-form-item label="学历" prop="education">
<el-select v-model="form.education" placeholder="请选择学历" style="width: 100%"> <el-select v-model="form.education" placeholder="请选择学历" style="width: 100%">
<el-option label="小学" value="primary" /> <el-option label="小学" value="0" />
<el-option label="初中" value="junior" /> <el-option label="初中" value="1" />
<el-option label="高中" value="senior" /> <el-option label="高中" value="2" />
<el-option label="大专" value="college" /> <el-option label="大专" value="3" />
<el-option label="本科" value="bachelor" /> <el-option label="本科" value="4" />
<el-option label="硕士" value="master" /> <el-option label="硕士" value="5" />
<el-option label="博士" value="doctor" /> <el-option label="博士" value="6" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
...@@ -86,13 +86,13 @@ ...@@ -86,13 +86,13 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="紧急联系人" prop="emergencyContact"> <el-form-item label="紧急联系人" prop="emergencyContactName">
<el-input v-model="form.emergencyContact" placeholder="请输入紧急联系人" /> <el-input v-model="form.emergencyContactName" placeholder="请输入紧急联系人" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="紧急联系电话" prop="emergencyPhone"> <el-form-item label="紧急联系人手机号" prop="emergencyContactPhone">
<el-input v-model="form.emergencyPhone" placeholder="请输入紧急联系电话" /> <el-input v-model="form.emergencyContactPhone" placeholder="请输入紧急联系人手机号" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
...@@ -103,23 +103,30 @@ ...@@ -103,23 +103,30 @@
v-model="form.entryDate" v-model="form.entryDate"
type="date" type="date"
placeholder="请选择日期" placeholder="请选择日期"
value-format="yyyy-MM-dd"
style="width: 100%" style="width: 100%"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="常住地址" prop="address"> <el-form-item label="居住地址" prop="permanentAddress">
<el-input v-model="form.address" placeholder="请输入常住地址" /> <el-input v-model="form.permanentAddress" placeholder="请输入居住地址" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="上传安全证书"> <el-form-item label="安全证书">
<el-upload <el-upload
action="#" ref="upload"
:action="uploadUrl"
:data="uploadData"
:headers="uploadHeaders"
:on-error="handleUploadError"
:before-upload="beforeUpload"
list-type="picture-card" list-type="picture-card"
:auto-upload="false" :auto-upload="false"
> >
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2MB</div>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
...@@ -135,41 +142,68 @@ ...@@ -135,41 +142,68 @@
import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect' import Treeselect, { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css' import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { getDepts } from '@/api/system/dept' 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 { export default {
name: 'AddPersonnel', name: 'AddPersonnel',
components: { Treeselect }, components: { Treeselect },
data() { data() {
// 自定义验证
const validPhone = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入电话号码'))
} else if (!isvalidPhone(value)) {
callback(new Error('请输入正确的11位手机号码'))
} else {
callback()
}
}
return { return {
form: { form: {
name: null, name: null,
phone: null, phone: null,
idCard: null, identityCard: null, // 身份证号码
sex: null, sex: null,
deptId: null, deptId: null,
job: null, job: null,
workType: null, workType: null,
title: null, jobTitle: null, // 职称
education: null, education: null,
major: null, major: null, // 专业
emergencyContact: null, emergencyContactName: null, // 紧急联系人
emergencyPhone: null, emergencyContactPhone: null, // 紧急联系人手机号
entryDate: null, entryDate: null,
address: null permanentAddress: null // 居住地址
}, },
depts: [], // 部门数据 depts: [], // 部门数据
uploadUrl: process.env.VUE_APP_BASE_API + '/api/common/upload', // 上传接口
uploadData: {
modelName: 'safe' // 固定参数
},
uploadHeaders: {
'Authorization': getToken()
},
rules: { rules: {
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
phone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }], phone: [{ required: true, message: '请输入联系电话', validator: validPhone }],
idCard: [{ required: true, message: '请输入身份证', trigger: 'blur' }], identityCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
deptId: [{ required: true, message: '请选择部门', trigger: 'change' }], deptId: [{ required: true, message: '请选择部门', trigger: 'change' }],
job: [{ required: true, message: '请输入职务', trigger: 'blur' }], job: [{ required: true, message: '请输入职务', trigger: 'blur' }],
education: [{ required: true, message: '请选择学历', trigger: 'change' }] education: [{ required: true, message: '请选择学历', trigger: 'change' }]
} }
} }
}, },
created() { 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: { methods: {
// 数据格式化,将后端数据转换为 treeselect 需要的格式 // 数据格式化,将后端数据转换为 treeselect 需要的格式
...@@ -180,43 +214,186 @@ export default { ...@@ -180,43 +214,186 @@ export default {
children: node.children children: node.children
} }
}, },
// 获取部门数据 // 获取部门数据(智能加载,只加载必要的层级)
getDepts() { async getDepts() {
getDepts({ enabled: true }).then(res => { // 获取目标部门ID(如果是编辑模式)
this.depts = res.content.map(function(obj) { const targetDeptId = this.form && this.form.dept ? this.form.dept.id : null
if (obj.hasChildren) {
obj.children = 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 }) { loadDepts({ action, parentNode, callback }) {
if (action === LOAD_CHILDREN_OPTIONS) { if (action === LOAD_CHILDREN_OPTIONS) {
getDepts({ enabled: true, pid: parentNode.id }).then(res => { getDepts({ enabled: true, pid: parentNode.id }).then(res => {
parentNode.children = res.content.map(function(obj) { if (res && res.content) {
if (obj.hasChildren) { parentNode.children = res.content.map(obj => ({
obj.children = null id: obj.id,
} name: obj.name,
return obj label: obj.name,
}) hasChildren: obj.hasChildren,
children: obj.hasChildren ? null : undefined
}))
} else {
parentNode.children = []
}
callback()
}).catch(() => {
parentNode.children = []
callback() 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() { handleSubmit() {
this.$refs.form.validate(valid => { this.$refs.form.validate(valid => {
if (valid) { if (valid) {
// 在这里处理表单提交逻辑 // 检查是否有文件需要上传
console.log('Form submitted:', this.form) if (this.$refs.upload.uploadFiles.length) {
this.$message.success('提交成功') this.uploadAndSave()
}
// 直接保存
this.saveForm()
} else { } else {
this.$message.error('请填写所有必填项') this.$message.error('请填写所有必填项')
return false 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() { handleCancel() {
this.$router.go(-1) this.$router.go(-1)
} }
......
...@@ -33,9 +33,18 @@ ...@@ -33,9 +33,18 @@
<el-table :data="tableData" :loading="loading" style="width: 100%"> <el-table :data="tableData" :loading="loading" style="width: 100%">
<el-table-column type="index" label="序号" width="60" /> <el-table-column type="index" label="序号" width="60" />
<el-table-column prop="name" label="姓名" /> <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="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="job" label="职务" />
<el-table-column prop="workType" label="工种" /> <el-table-column prop="workType" label="工种" />
<el-table-column prop="entryDate" label="入职时间" /> <el-table-column prop="entryDate" label="入职时间" />
...@@ -63,7 +72,7 @@ ...@@ -63,7 +72,7 @@
</template> </template>
<script> <script>
import { getSafePeopleInfo } from '@/api/aqrf/safePersonnel' import { getSafePeopleInfo, delPeopleInfo } from '@/api/aqrf/safePersonnel'
export default { export default {
name: 'SafePersonnel', name: 'SafePersonnel',
...@@ -99,7 +108,7 @@ export default { ...@@ -99,7 +108,7 @@ export default {
const response = await getSafePeopleInfo(params) const response = await getSafePeopleInfo(params)
if (response && response.data) { if (response && response.body) {
this.tableData = response.body.list || [] this.tableData = response.body.list || []
this.pagination.total = response.body.total || 0 this.pagination.total = response.body.total || 0
} else { } else {
...@@ -140,7 +149,9 @@ export default { ...@@ -140,7 +149,9 @@ export default {
this.$router.push('/aqrf/add-personnel') this.$router.push('/aqrf/add-personnel')
}, },
handleEdit(row) { handleEdit(row) {
console.log('Edit:', row) this.$router.push({
path: '/aqrf/add-personnel', query: { data: row }
})
}, },
handleDelete(row) { handleDelete(row) {
this.$confirm('此操作将永久删除该条目, 是否继续?', '提示', { this.$confirm('此操作将永久删除该条目, 是否继续?', '提示', {
...@@ -149,10 +160,15 @@ export default { ...@@ -149,10 +160,15 @@ export default {
type: 'warning' type: 'warning'
}) })
.then(() => { .then(() => {
console.log('Delete:', row) delPeopleInfo([row.id]).then(() => {
this.$message({ this.$message({
type: 'success', type: 'success',
message: '删除成功!' message: '删除成功!'
})
this.fetchData()
}).catch((error) => {
console.error('删除失败:', error)
this.$message.error('删除失败')
}) })
}) })
.catch(() => { .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