(人员管理)离退休-离退休人员管理:新增手机h5端查询页;

This commit is contained in:
dd3s_206
2026-06-13 10:37:01 +08:00
parent 5a42a139d6
commit 38441b30f6
3 changed files with 425 additions and 10 deletions
@@ -1,6 +1,7 @@
package com.budwk.app.zhgh.staffmanage.retired.user.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.staffmanage.retired.group.service.RetiredGroupService;
@@ -36,8 +37,14 @@ public class RetiredListController {
public void index() {
}
@At("/h5")
@Ok("beetl:/platform/zhghh5/staffmanage/retired/list/index.html")
@SaCheckPermission("h5.retired.list")
public void h5Index() {
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result pageData(PageForm pageForm,
@Param("unitId") String unitId,
@Param("unionId") String unionId,
@@ -48,34 +55,34 @@ public class RetiredListController {
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result changeToDie(String userId, Date deathDate) {
retiredUserService.changeToDie(userId, deathDate);
return Result.success();
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result nonRetiredUserPageData(PageForm pageForm) {
return Result.success(retiredUserService.nonRetiredUserPageData(pageForm));
}
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result doBatchJoinRetire(@Param("userIds") String[] userIds) {
retiredUserService.batchJoinRetire(userIds);
return Result.success();
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result retiredGroup() {
return Result.success(retiredGroupService.options());
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result retiredPartyBranch() {
return Result.success(retiredPartyBranchService.options());
}
@@ -88,28 +95,28 @@ public class RetiredListController {
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result userInfo(String userId) {
return Result.success(retiredUserService.userInfo(userId));
}
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result doSubmit(@Param("user") String user, @Param("userId") String userId) {
retiredUserService.submit(user, userId);
return Result.success();
}
@At
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result getInfo(String id) {
return Result.success(retiredUserService.getInfo(id));
}
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retired.list")
@SaCheckPermission(value = {"retired.list", "h5.retired.list"}, mode = SaMode.OR)
public Result doDelete(String id) {
retiredUserService.deleteRetired(id);
return Result.success();
@@ -0,0 +1,18 @@
-- 离退休人员档案手机端初始化脚本
-- 说明:PC端离退休人员档案已部署时,只需要执行本脚本新增手机端入口和权限,菜单挂载到H5端已有的人员管理模块。
SET @now := CAST(UNIX_TIMESTAMP(NOW()) * 1000 AS UNSIGNED);
INSERT INTO `sys_menu` (`id`, `parentId`, `path`, `name`, `initialPinyinName`, `aliasName`, `type`, `href`, `target`, `icon`, `picIcon`, `showit`, `disabled`, `permission`, `note`, `location`, `hasChildren`, `createdBy`, `createdAt`, `updatedBy`, `updatedAt`, `delFlag`, `platform`, `moduleId`, `isRecommendApp`, `isRecommendService`)
SELECT 'b1f00006000000000000000000000003', '', 'H9913', '离退休人员档案', 'L', NULL, 'menu', '/platform/retired/list/h5', 'data-pjax', 'manager-o', NULL, 1, 0, 'h5.retired.list', NULL, 9913, 0, '', @now, '', @now, 0, 'H5', module.`id`, 0, 0
FROM `sys_module` module
WHERE module.`platform` = 'H5'
AND module.`name` = '人员管理'
AND NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `permission` = 'h5.retired.list' OR `path` = 'H9913');
INSERT INTO `sys_role_menu` (`roleId`, `menuId`)
SELECT r.`id`, m.`id`
FROM `sys_role` r
JOIN `sys_menu` m ON m.`permission` = 'h5.retired.list'
WHERE r.`code` IN ('SYSADMIN', 'SCHOOL_UNION_ADMIN')
AND NOT EXISTS (SELECT 1 FROM `sys_role_menu` rm WHERE rm.`roleId` = r.`id` AND rm.`menuId` = m.`id`);
@@ -0,0 +1,390 @@
<!--#
layout("/layouts/platform_h5.html"){
#-->
<div id="app" v-cloak>
<van-nav-bar title="离退休人员档案" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
<van-sticky offset-top="46px">
<van-search v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号搜索" show-action input-align="left" @search="doSearch">
<template #action>
<div @click="doSearch">搜索</div>
</template>
</van-search>
<div class="retired-toolbar">
<van-button size="small" type="primary" block @click="openAdd">新增退休人员</van-button>
<van-button size="small" type="info" block @click="openSet">设置退休人员</van-button>
</div>
</van-sticky>
<table-list api="/platform/retired/list/pageData" :page_form.sync="pageForm" ref="tableListRef" title="username" @ready="onReady">
<template v-slot="{row}">
<table-column label="工号">{{row.loginname}}</table-column>
<table-column label="性别">{{row.sex}}</table-column>
<table-column label="联系电话">{{row.mobile}}</table-column>
<table-column label="出生日期">{{formatDate(row.birthday)}}</table-column>
<table-column label="在职状态">{{row.userState}}</table-column>
<table-column label="人员类型">{{row.personType}}</table-column>
<table-column label="所属单位">{{row.unitname}}</table-column>
<table-column label="退休小组">{{row.retiredGroupName || '暂无'}}</table-column>
</template>
<template #actions="{row}">
<div class="action-btn" @click="openView(row)">
<i class="fa fa-eye"></i>
<span>查看</span>
</div>
<div class="action-btn" @click="openEdit(row)">
<i class="fa fa-edit"></i>
<span>编辑</span>
</div>
<div class="action-btn delete" @click="doDelete(row)">
<i class="fa fa-trash"></i>
<span>删除</span>
</div>
</template>
</table-list>
<van-action-sheet v-model="infoVisible" title="人员档案详情">
<div class="detail-container">
<van-cell-group title="基本信息">
<van-cell title="工号">{{emptyText(viewData.loginname)}}</van-cell>
<van-cell title="姓名">{{emptyText(viewData.username)}}</van-cell>
<van-cell title="性别">{{emptyText(viewData.sex)}}</van-cell>
<van-cell title="出生日期">{{formatDate(viewData.birthday) || '暂无'}}</van-cell>
<van-cell title="身份证号">{{emptyText(viewData.idCard)}}</van-cell>
<van-cell title="政治面貌">{{emptyText(viewData.political)}}</van-cell>
<van-cell title="籍贯">{{emptyText(viewData.nativePlace)}}</van-cell>
<van-cell title="联系电话">{{emptyText(viewData.mobile)}}</van-cell>
<van-cell title="参加工作时间">{{emptyText(viewData.arrivalAtSchoolDate)}}</van-cell>
<van-cell title="工龄">{{workAgeText(viewData.arrivalAtSchoolDate) || '暂无'}}</van-cell>
<van-cell title="退休时间">{{formatDate(viewData.retireDate) || '暂无'}}</van-cell>
<van-cell title="职务">{{emptyText(viewData.position)}}</van-cell>
<van-cell title="职称">{{emptyText(viewData.professionalTitle)}}</van-cell>
<van-cell title="在职状态">{{emptyText(viewData.userState)}}</van-cell>
<van-cell title="人员类型">{{emptyText(viewData.personType)}}</van-cell>
<van-cell title="所属工会">{{emptyText(viewData.unionName)}}</van-cell>
<van-cell title="所属单位">{{emptyText(viewData.unitName)}}</van-cell>
<van-cell title="退休小组">{{emptyText(viewData.retiredGroupName)}}</van-cell>
<van-cell title="退休党支部">{{emptyText(viewData.retiredPartyBranchName)}}</van-cell>
</van-cell-group>
</div>
</van-action-sheet>
<van-action-sheet v-model="formVisible" :title="formUserId ? '编辑退休人员' : '新增退休人员'">
<van-form ref="formRef" class="h5-form-sheet">
<van-field v-model="formData.loginname" name="loginname" label="工号" maxlength="120" placeholder="请输入工号" required :rules="[{required:true,message:'请输入工号'}]"></van-field>
<van-field v-model="formData.username" name="username" label="姓名" maxlength="100" placeholder="请输入姓名" required :rules="[{required:true,message:'请输入姓名'}]"></van-field>
<van-field v-model="formData.nativePlace" label="籍贯" maxlength="100" placeholder="请输入籍贯"></van-field>
<van-field v-model="formData.sex" name="sex" label="性别" placeholder="请选择性别" readonly is-link required :rules="[{required:true,message:'请选择性别'}]" @click="showSexPicker = true"></van-field>
<van-field v-model="formData.birthday" label="出生日期" type="date" placeholder="请选择出生日期"></van-field>
<van-field v-model="formData.idCard" label="身份证号" maxlength="30" placeholder="请输入身份证号"></van-field>
<van-field v-model="formData.political" label="政治面貌" maxlength="100" placeholder="请输入政治面貌"></van-field>
<van-field v-model="formData.arrivalAtSchoolDate" label="参加工作时间" maxlength="20" placeholder="请输入参加工作时间"></van-field>
<van-field :value="workAgeText(formData.arrivalAtSchoolDate)" label="工龄" readonly placeholder="系统自动计算"></van-field>
<van-field v-model="formData.unitName" label="单位" placeholder="请选择单位" readonly is-link @click="showUnitPicker = true"></van-field>
<van-field v-model="formData.unionName" label="工会" readonly placeholder="系统自动显示"></van-field>
<van-field v-model="formData.position" label="职务" maxlength="50" placeholder="请输入职务"></van-field>
<van-field v-model="formData.professionalTitle" label="职称" maxlength="50" placeholder="请输入职称"></van-field>
<van-field v-model="formData.retireDate" label="退休时间" type="date" placeholder="请选择退休时间"></van-field>
<van-field v-model="formData.mobile" label="电话" maxlength="32" placeholder="请输入电话"></van-field>
<van-field v-model="formData.userState" name="userState" label="在职状态" placeholder="请选择在职状态" readonly is-link required :rules="[{required:true,message:'请选择在职状态'}]" @click="showUserStatePicker = true"></van-field>
<van-field v-model="formData.personType" name="personType" label="人员类型" placeholder="请选择人员类型" readonly is-link required :rules="[{required:true,message:'请选择人员类型'}]" @click="showPersonTypePicker = true"></van-field>
</van-form>
<div class="h5-form-actions">
<van-button block @click="formVisible = false">取消</van-button>
<van-button block type="primary" @click="submitForm">确定</van-button>
</div>
</van-action-sheet>
<van-action-sheet v-model="setVisible" title="设置退休人员">
<van-search v-model="nonRetiredUserPageForm.searchKeyword" placeholder="请输入姓名或工号搜索" show-action @search="searchNonRetiredUsers">
<template #action>
<div @click="searchNonRetiredUsers">搜索</div>
</template>
</van-search>
<van-checkbox-group v-model="selectedUserIds" class="retired-user-list">
<van-cell v-for="item in nonRetiredUserList" :key="item.id" :title="item.username + '(' + item.loginname + ')'" :label="nonRetiredUserLabel(item)" clickable @click="toggleUser(item.id)">
<template #right-icon>
<van-checkbox :name="item.id" ref="userCheckboxes" @click.stop></van-checkbox>
</template>
</van-cell>
</van-checkbox-group>
<van-empty v-if="!nonRetiredUserList.length" description="暂无人员"></van-empty>
<div class="retired-page-actions">
<van-button size="small" :disabled="nonRetiredUserPageForm.pageNumber <= 1" @click="changeNonRetiredPage(-1)">上一页</van-button>
<span>第{{nonRetiredUserPageForm.pageNumber}}页 / 共{{nonRetiredUserPageForm.totalCount}}人</span>
<van-button size="small" :disabled="nonRetiredUserPageForm.pageNumber * nonRetiredUserPageForm.pageSize >= nonRetiredUserPageForm.totalCount" @click="changeNonRetiredPage(1)">下一页</van-button>
</div>
<div class="h5-form-actions">
<van-button block @click="setVisible = false">取消</van-button>
<van-button block type="primary" @click="doBatchJoinRetire">确定</van-button>
</div>
</van-action-sheet>
<van-popup v-model="showSexPicker" position="bottom">
<van-picker show-toolbar :columns="sexOptions" @confirm="(value)=>{formData.sex=value;showSexPicker=false}" @cancel="showSexPicker = false"></van-picker>
</van-popup>
<van-popup v-model="showUserStatePicker" position="bottom">
<van-picker show-toolbar :columns="userStateOptions" @confirm="(value)=>{formData.userState=value;showUserStatePicker=false}" @cancel="showUserStatePicker = false"></van-picker>
</van-popup>
<van-popup v-model="showPersonTypePicker" position="bottom">
<van-picker show-toolbar :columns="personTypeOptions" @confirm="(value)=>{formData.personType=value;showPersonTypePicker=false}" @cancel="showPersonTypePicker = false"></van-picker>
</van-popup>
<van-popup v-model="showUnitPicker" position="bottom">
<van-picker show-toolbar :columns="unitColumns" @confirm="onUnitConfirm" @cancel="showUnitPicker = false"></van-picker>
</van-popup>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
data() {
return {
pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0},
infoVisible: false,
formVisible: false,
setVisible: false,
showSexPicker: false,
showUserStatePicker: false,
showPersonTypePicker: false,
showUnitPicker: false,
viewData: {},
formData: {},
formUserId: "",
units: [],
sexOptions: ["男", "女"],
userStateOptions: ["退休", "离休", "离退休"],
personTypeOptions: ["离退休人员"],
nonRetiredUserPageForm: {pageNumber: 1, pageSize: 10, totalCount: 0},
nonRetiredUserList: [],
selectedUserIds: []
}
},
computed: {
unitColumns() {
return this.units.map((item) => item.name)
}
},
methods: {
onReady() {
this.doSearch()
},
doSearch() {
this.$nextTick(() => {
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.$refs.tableListRef.doSearch()
})
},
openView(row) {
this.$axios.post("/platform/retired/list/userInfo", {userId: row.id}).then((res) => {
if (res.code === 0) {
this.viewData = this.normalizeUserData(res.data || row)
this.infoVisible = true
}
})
},
openAdd() {
this.formUserId = ""
this.formData = this.defaultFormData()
this.formVisible = true
},
openEdit(row) {
this.$axios.post("/platform/retired/list/userInfo", {userId: row.id}).then((res) => {
if (res.code === 0) {
this.formUserId = row.id
this.formData = this.normalizeUserData(res.data || row)
this.formVisible = true
}
})
},
submitForm() {
this.$refs.formRef.validate().then(() => {
this.$axios.post("/platform/retired/list/doSubmit", {
user: JSON.stringify(this.formData),
userId: this.formUserId
}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.formVisible = false
this.doSearch()
}
})
})
},
doDelete(row) {
this.$dialog.confirm({title: "提示", message: "您确定要删除吗?"}).then(() => {
this.$axios.post("/platform/retired/list/doDelete", {id: row.id}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.doSearch()
}
})
}).catch(() => {})
},
openSet() {
this.setVisible = true
this.selectedUserIds = []
this.nonRetiredUserPageForm = {pageNumber: 1, pageSize: 10, totalCount: 0}
this.nonRetiredUserPageData()
},
searchNonRetiredUsers() {
this.nonRetiredUserPageForm.pageNumber = 1
this.nonRetiredUserPageData()
},
changeNonRetiredPage(step) {
this.nonRetiredUserPageForm.pageNumber = this.nonRetiredUserPageForm.pageNumber + step
this.nonRetiredUserPageData()
},
nonRetiredUserPageData() {
this.$axios.post("/platform/retired/list/nonRetiredUserPageData", this.nonRetiredUserPageForm).then((res) => {
if (res.code === 0) {
this.nonRetiredUserList = (res.data && res.data.list) || []
this.$set(this.nonRetiredUserPageForm, "totalCount", (res.data && res.data.totalCount) || 0)
}
})
},
toggleUser(id) {
const index = this.selectedUserIds.indexOf(id)
if (index >= 0) {
this.selectedUserIds.splice(index, 1)
} else {
this.selectedUserIds.push(id)
}
},
doBatchJoinRetire() {
if (!this.selectedUserIds.length) {
this.$toast("请先选择需要设置为退休的人员")
return
}
this.$axios.post("/platform/retired/list/doBatchJoinRetire", {userIds: JSON.stringify(this.selectedUserIds)}).then((res) => {
if (res.code === 0) {
this.$toast.success(res.msg)
this.setVisible = false
this.doSearch()
}
})
},
onUnitConfirm(value) {
const unit = this.units.find((item) => item.name === value)
this.$set(this.formData, "unitName", unit ? unit.name : "")
this.$set(this.formData, "unitId", unit ? unit.id : "")
this.$set(this.formData, "unionName", unit ? (unit.unionName || unit.unionname || "") : "")
this.$set(this.formData, "unionId", unit ? (unit.unionId || unit.unionid || "") : "")
this.showUnitPicker = false
},
defaultFormData() {
return {
userState: "退休",
personType: "离退休人员",
families: []
}
},
normalizeUserData(user) {
const data = Object.assign(this.defaultFormData(), user)
const fieldMap = {
idcard: "idCard",
nativeplace: "nativePlace",
professionaltitle: "professionalTitle",
arrivalatschooldate: "arrivalAtSchoolDate",
userstate: "userState",
persontype: "personType",
retiredate: "retireDate",
unitid: "unitId",
unitname: "unitName",
unionid: "unionId",
unionname: "unionName",
retiredgroupname: "retiredGroupName",
retiredpartybranchname: "retiredPartyBranchName"
}
Object.keys(fieldMap).forEach((key) => {
if ((data[fieldMap[key]] === undefined || data[fieldMap[key]] === null) && user[key] !== undefined) {
this.$set(data, fieldMap[key], user[key])
}
})
data.birthday = this.formatDate(data.birthday)
data.retireDate = this.formatDate(data.retireDate)
if (typeof data.families === "string") {
try {
data.families = JSON.parse(data.families)
} catch (e) {
data.families = []
}
}
return data
},
formatDate(value) {
return value ? this.$moment(value).format("YYYY-MM-DD") : ""
},
emptyText(value) {
return value === undefined || value === null || value === "" ? "暂无" : value
},
nonRetiredUserLabel(item) {
return [item.sex, item.mobile, item.unitname].filter(Boolean).join(" / ")
},
workAgeText(value) {
const start = this.parseWorkDate(value)
if (!start) return ""
const today = new Date()
let years = today.getFullYear() - start.getFullYear()
if (today.getMonth() < start.getMonth() || (today.getMonth() === start.getMonth() && today.getDate() < start.getDate())) {
years = years - 1
}
return Math.max(years, 0) + "年"
},
parseWorkDate(value) {
if (!value) return null
const parts = String(value).split("-")
const year = Number(parts[0])
const month = parts.length > 1 ? Number(parts[1]) : 1
const day = parts.length > 2 ? Number(parts[2]) : 1
if (!year || !month || !day) return null
const date = new Date(year, month - 1, day)
return isNaN(date.getTime()) ? null : date
},
async loadUnits() {
this.units = await this.$businessTool.listUnit()
}
},
created() {
this.loadUnits()
}
})
</script>
<style>
.retired-toolbar {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
padding: 8px 10px;
background: #fff;
}
.h5-form-sheet {
max-height: 70vh;
overflow-y: auto;
}
.h5-form-actions {
display: flex;
column-gap: 10px;
padding: 10px;
}
.retired-user-list {
max-height: 55vh;
overflow-y: auto;
}
.retired-page-actions {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
color: #666;
font-size: 13px;
}
</style>
<!--#
}
#-->