人员管理

This commit is contained in:
2026-10-30 14:02:26 +08:00
parent fad8a37dfb
commit 7dacfd7e5a
21 changed files with 110 additions and 50 deletions
@@ -1,6 +1,5 @@
package com.budwk.app.sys.services.impl;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.sys.services.SysHomeNewsService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
@@ -35,7 +34,7 @@ public class SysHomeNewsServiceImpl implements SysHomeNewsService {
/**
* 无需参数,一次抓取首页中的三个栏目,并保留原有一天有效期的缓存写入。
*
* @return label/value 栏目列表,文章包含 text/time/href;正常空栏目返回空列表。
* @return label/value 栏目列表,文章包含 text/time/href;无文章的栏目保留空列表,抓取失败返回空栏目列表。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
@@ -51,7 +50,8 @@ public class SysHomeNewsServiceImpl implements SysHomeNewsService {
return news;
} catch (IOException e) {
log.warn("获取重庆工贸职业技术学院工会首页失败", e);
throw new BaseException("学校工会网站暂时无法访问,请稍后重试");
// 学校网站连接失败或超时时返回空列表,让首页展示空状态,不向用户报错,也不覆盖已有缓存。
return new ArrayList<>();
}
}
@@ -120,6 +120,18 @@ layout("/layouts/v4/baseLayout.html"){
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20261028-2" />
<!-- 登录资料仅在 HTML 属性中输出并转义;放在 Vue 挂载区域外,避免名称被当作模板表达式解析。 -->
<div id="v4-home-profile-data" hidden
data-username="${@auth.getPrincipalProperty('username'),escape}"
data-loginname="${@auth.getPrincipalProperty('loginname'),escape}"
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
data-unit-name="${@auth.getPrincipalProperty('unit').getName(),escape}"
<!--#}#-->
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
data-union-name="${@auth.getPrincipalProperty('union').getName(),escape}"
<!--#}#-->
></div>
<div class="v4-container home-portal" id="v4-home-app">
<!-- 首页banner -->
<div class="portal-top">
@@ -140,7 +152,7 @@ layout("/layouts/v4/baseLayout.html"){
</div>
</div>
</div>
<user class="portal-member" :profile-only="true"></user>
<user class="portal-member" :profile-only="true" :profile="memberProfile"></user>
</div>
<div class="portal-content">
@@ -181,7 +193,15 @@ layout("/layouts/v4/baseLayout.html"){
new Vue({
el: '#v4-home-app',
data(){
// 浏览器读取属性时还原 HTML 转义;未配置单位或工会时使用空字符串,不访问空对象。
const profileData = document.getElementById('v4-home-profile-data').dataset
return{
memberProfile: {
username: profileData.username || '',
loginname: profileData.loginname || '',
unitName: profileData.unitName || '',
unionName: profileData.unionName || ''
},
websiteNews: [],
activityBrowse: {enabled: false, label: '活动加载中'}
}
@@ -9,7 +9,7 @@ const user = {
<div class="user-details">
<div class="portal-member-heading">
<span class="portal-member-avatar"><i class="fa fa-user" aria-hidden="true"></i></span>
<div><div class="portal-member-welcome">欢迎回来</div><div class="user-name">${@auth.getPrincipalProperty('username')}</div></div>
<div><div class="portal-member-welcome">欢迎回来</div><div class="user-name">{{ profile.username }}</div></div>
</div>
<div class="user-meta-grid">
@@ -17,7 +17,7 @@ const user = {
<span class="meta-icon"><i class="fa fa-id-card-o" aria-hidden="true"></i></span>
<div>
<span class="meta-label">工号</span>
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
<span class="meta-value">{{ profile.loginname }}</span>
</div>
</div>
@@ -26,14 +26,7 @@ const user = {
<div>
<span class="meta-label">单位信息</span>
<span class="meta-value">
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
${@auth.getPrincipalProperty('unit').getName()}
<!--#}#-->
(
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
${@auth.getPrincipalProperty('union').getName()}
<!--#}#-->
)
{{ profile.unitName }} ({{ profile.unionName }})
</span>
</div>
</div>
@@ -108,7 +101,12 @@ const user = {
mixins: [initTableMixins],
// 同一组件分别承载会员卡和待办卡,各自只加载需要的数据。
props: {
profileOnly: { type: Boolean, default: false }
profileOnly: { type: Boolean, default: false },
// 首页传入显示资料:username 姓名、loginname 工号、unitName 单位、unionName 工会;缺项显示空文本。
profile: {
type: Object,
default: () => ({username: '', loginname: '', unitName: '', unionName: ''})
}
},
data() {
return {
@@ -403,6 +403,12 @@ const PROPOSAL_INFO = {
},
openChart(){
// 仅保存的提案尚未创建 WF 实例,按提案流程 KEY 预览流程定义图。
if (!this.row.instanceId) {
this.$refs.snakerChartRef.onOpen("JDHTA_NC")
return
}
// 已提交提案使用实例对应的流程版本,保留实际办理节点和审批进度。
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
}
},
@@ -40,7 +40,8 @@
<dict-select v-model="pageForm.aidFundMemberUserType" code="AIDFUND_MEMBER_USER_TYPE"
style="width: 100%"></dict-select>
</search-item>-->
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-if="userAttributeMultiple" v-model="pageForm.userAttributes" code="USER_ATTRIBUTE"
multiple collapse-tags clearable style="width: 100%"></dict-select>
<dict-select v-else v-model="pageForm.userAttribute" code="USER_ATTRIBUTE"
@@ -32,7 +32,9 @@ const COMMON_QUERY = {
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$emit('search', pageForm)
},
async initData(){
@@ -29,7 +29,8 @@
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>-->
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-if="userAttributeMultiple" v-model="pageForm.userAttributes"
placeholder="请选择人员属性" @change="doSearch" code="USER_ATTRIBUTE"
multiple collapse-tags clearable></dict-select>
@@ -32,8 +32,10 @@ const COMMON_QUERY = {
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
// 多选人员属性沿用现有数组查询参数的JSON提交方式。
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 保持其他业务筛选条件,排除已屏蔽字段。
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$emit('search', pageForm)
},
async initData(){
@@ -149,7 +149,8 @@ const MEMBER_CHANGE = {
:disabled="allowFields('personType')" style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="人员属性">
<!-- 屏蔽人员属性展示和编辑,保留回填值以免保存时覆盖历史数据。 -->
<el-descriptions-item label="人员属性" v-if="false">
<el-form-item prop="userAttribute">
<dict-select v-model="formData.userAttribute" code="USER_ATTRIBUTE"
style="width: 100%"></dict-select>
@@ -50,7 +50,8 @@ layout("/layouts/platform.html"){
<!-- <dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"-->
<!-- code="AIDFUND_MEMBER_USER_TYPE"></dict-select>-->
<!-- </search-item>-->
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" multiple collapse-tags clearable></dict-select>
</search-item>
@@ -76,7 +77,7 @@ layout("/layouts/platform.html"){
设置人员分类
</el-button>
<el-button :disabled="!checkUsers.length" @click="openBatchEditUserAttribute" class="ml5" icon="el-icon-edit"
<el-button v-if="false" :disabled="!checkUsers.length" @click="openBatchEditUserAttribute" class="ml5" icon="el-icon-edit"
size="small" type="primary">
设置人员属性
</el-button>
@@ -240,6 +241,7 @@ layout("/layouts/platform.html"){
<el-drawer
:before-close="handleClose"
v-if="false"
:visible.sync="batchEditUserAttributeVisible"
size="1000px" title="批量设置人员属性">
<el-timeline style="margin-right: 40px">
@@ -569,7 +571,8 @@ layout("/layouts/platform.html"){
{ prop: "personType", label: "人员类型", width: 120, sortable: true },
// 临时屏蔽“人员分类”列表字段,不删除配置,后续需要可恢复。
// { prop: "aidFundMemberUserType", label: "人员分类", width: 120, sortable: true },
{ prop: "userAttribute", label: "人员属性", width: 120, sortable: true },
// 屏蔽人员属性列,同时从导出可选列中排除。
// { prop: "userAttribute", label: "人员属性", width: 120, sortable: true },
{ prop: "idCardType", label: "证件类型", width: 120, sortable: true, checked: 0 },
{ prop: "idCard", label: "证件号码", width: 120, sortable: true, checked: 0 },
{ prop: "marriage", label: "婚姻状况", width: 120, sortable: true, checked: 0 },
@@ -597,13 +600,15 @@ layout("/layouts/platform.html"){
"member-all-change": MEMBER_ALL_CHANGE_INFO,
},
methods: {
// 分页和导出共用该参数构建方法,保证人员属性多选值始终按 JSON 数组提交。
// 分页和导出共用查询参数,排除已屏蔽的人员属性条件。
buildQueryPageForm(source = this.pageForm) {
const pageForm = clone(source)
pageForm.userAttributes = JSON.stringify(source.userAttributes || [])
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
return pageForm
},
// 覆盖公共分页方法,使后端按人员属性集合执行查询。
// 复用公共分页方法,提交已清理的业务查询参数。
pageData(data = null) {
return initTableMixins.methods.pageData.call(this, this.buildQueryPageForm(data || this.pageForm))
},
@@ -42,7 +42,8 @@ layout("/layouts/platform.html"){
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>-->
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" multiple collapse-tags clearable></dict-select>
</search-item>
@@ -198,8 +199,10 @@ layout("/layouts/platform.html"){
pageForm.personTypes = JSON.stringify(pageForm.personTypes)
pageForm.changeTypes = JSON.stringify(pageForm.changeTypes)
pageForm.changeOrigins = JSON.stringify(pageForm.changeOrigins)
// 人员属性为多选条件,提交前转换为后端可解析的 JSON 数组。
pageForm.userAttributes = JSON.stringify(pageForm.userAttributes)
// 人员属性已停用,不参与变更记录筛选。
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$axios.post(loc() + '/pageData', pageForm)
.then(res => {
@@ -73,7 +73,8 @@ const MEMBER_INFO = {
<el-descriptions-item label="人员类型">{{ viewData.personType }}</el-descriptions-item>
<!-- 第 4 行 -->
<el-descriptions-item label="人员属性">{{ viewData.userAttribute }}</el-descriptions-item>
<!-- 屏蔽人员属性展示和编辑,保留回填值以免保存时覆盖历史数据。 -->
<el-descriptions-item label="人员属性" v-if="false">{{ viewData.userAttribute }}</el-descriptions-item>
<el-descriptions-item label="职称">{{ viewData.professionalTitle }}</el-descriptions-item>
<el-descriptions-item label="职级">{{ viewData.professionalLevel }}</el-descriptions-item>
@@ -85,6 +86,7 @@ const MEMBER_INFO = {
<el-descriptions-item label="行政岗级">{{ viewData.administrativePositionLevel }}</el-descriptions-item>
<el-descriptions-item label="人员分类" v-if="false">{{ viewData.aidFundMemberUserType }}</el-descriptions-item>
</el-descriptions>
<slot></slot>
</div>
`,
store,
@@ -43,7 +43,8 @@
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch"
code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>-->
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" multiple collapse-tags clearable></dict-select>
</search-item>
@@ -37,8 +37,10 @@ const COMMON_QUERY = {
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
// 人员属性多选值按现有数组查询参数口径提交。
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 保持其他业务筛选条件,排除已屏蔽字段。
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$emit('search', pageForm)
},
handleUnionChange() {
@@ -102,7 +102,8 @@
style="width: 100%"></dict-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="人员属性">
<!-- 屏蔽人员属性展示和编辑,保留回填值以免保存时覆盖历史数据。 -->
<el-descriptions-item label="人员属性" v-if="false">
<el-form-item prop="userAttribute">
<dict-select v-model="formData.userAttribute" code="USER_ATTRIBUTE"
style="width: 100%"></dict-select>
@@ -49,7 +49,8 @@ layout("/layouts/platform.html"){
<search-item label="人员分类" v-if="false">
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch" code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" multiple collapse-tags clearable></dict-select>
</search-item>
@@ -133,13 +134,15 @@ layout("/layouts/platform.html"){
"member-info": MEMBER_INFO
},
methods: {
// 分页和导出共用该参数构建方法,保证人员属性多选值始终按 JSON 数组提交。
// 分页和导出共用查询参数,排除已屏蔽的人员属性条件。
buildQueryPageForm() {
const pageForm = clone(this.pageForm)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes || [])
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
return pageForm
},
// 覆盖公共分页方法,使后端按人员属性集合执行查询。
// 复用公共分页方法,提交已清理的业务查询参数。
pageData() {
return initTableMixins.methods.pageData.call(this, this.buildQueryPageForm())
},
@@ -49,7 +49,8 @@ layout("/layouts/platform.html"){
<search-item label="人员分类" v-if="false">
<dict-select v-model="pageForm.aidFundMemberUserType" placeholder="请选择人员分类" @change="doSearch" code="AIDFUND_MEMBER_USER_TYPE"></dict-select>
</search-item>
<search-item label="人员属性">
<!-- 会员模块屏蔽人员属性查询入口。 -->
<search-item label="人员属性" v-if="false">
<dict-select v-model="pageForm.userAttributes" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE" multiple collapse-tags clearable></dict-select>
</search-item>
@@ -141,10 +142,12 @@ layout("/layouts/platform.html"){
"member-add-form": MEMBER_ADD_FORM
},
methods: {
// 人员属性为多选条件,分页查询前统一转换为后端可接收的 JSON 数组。
// 分页查询前排除已屏蔽的人员属性条件。
pageData(data = null) {
const pageForm = clone(data || this.pageForm)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes || [])
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
return initTableMixins.methods.pageData.call(this, pageForm)
},
openAdd() {
@@ -129,7 +129,7 @@ layout("/layouts/platform.html"){
</span>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-row type="flex" align="middle" class="query-row query-row-tag" v-if="false">
<el-col class="query-row-title">人员属性:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag class="query-tag-item"
@@ -280,7 +280,9 @@ layout("/layouts/platform.html"){
const pageForm = clone(this.pageForm)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.aidFundMemberUserTypes = JSON.stringify(this.pageForm.aidFundMemberUserTypes)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$axios.post(loc() + "/pageData", pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data
@@ -165,7 +165,8 @@ layout("/layouts/platform.html"){
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
// 临时屏蔽“人员分类”列表字段,不删除配置,后续需要可恢复。
// { prop: "aidFundMemberUserType", label: "人员分类", width: 120, sortable: true },
{ prop: "userAttribute", label: "人员属性", width: 120, sortable: true },
// 屏蔽人员属性列,同时从导出可选列中排除。
// { prop: "userAttribute", label: "人员属性", width: 120, sortable: true },
{ prop: "idCardType", label: "证件类型", width: 120, sortable: true, checked: 0 },
{ prop: "idCard", label: "证件号码", width: 120, sortable: true, checked: 0 },
{ prop: "marriage", label: "婚姻状况", width: 120, sortable: true, checked: 0 },
@@ -205,7 +206,9 @@ layout("/layouts/platform.html"){
pageForm.memberTypes = JSON.stringify(this.pageForm.memberTypes)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.aidFundMemberUserTypes = JSON.stringify(this.pageForm.aidFundMemberUserTypes)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
const data = this.tableColumns.filter(item => this.checkedFields.includes(item.prop)).map(item => {
return {prop: item.prop, label: item.label}
@@ -230,7 +233,9 @@ layout("/layouts/platform.html"){
pageForm.memberTypes = JSON.stringify(this.pageForm.memberTypes)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.aidFundMemberUserTypes = JSON.stringify(this.pageForm.aidFundMemberUserTypes)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
pageForm.memberStatus = JSON.stringify(this.pageForm.memberStatus)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
@@ -113,7 +113,7 @@ const MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM = {
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-row type="flex" align="middle" class="query-row query-row-tag" v-if="false">
<el-col class="query-row-title">人员属性:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag
@@ -129,7 +129,7 @@ layout("/layouts/platform.html"){
</span>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row query-row-tag">
<el-row type="flex" align="middle" class="query-row query-row-tag" v-if="false">
<el-col class="query-row-title">人员属性:</el-col>
<el-col class="query-row-content query-row-content-tag">
<el-tag class="query-tag-item"
@@ -265,7 +265,9 @@ layout("/layouts/platform.html"){
// 统计接口按 JSON 字符串接收多选条件,这里把人员分类和人员属性统一成同一提交口径。
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.aidFundMemberUserTypes = JSON.stringify(this.pageForm.aidFundMemberUserTypes)
pageForm.userAttributes = JSON.stringify(this.pageForm.userAttributes)
// 人员属性已屏蔽,查询和导出均不再按该字段过滤。
pageForm.userAttribute = ""
pageForm.userAttributes = "[]"
this.$axios.post(loc() + "/pageData", pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data