前端去掉人员属性字段;优化活动基础单位查询

This commit is contained in:
2026-09-16 20:59:53 +08:00
parent 4288a97bee
commit 9d99c1758a
27 changed files with 371 additions and 125 deletions
@@ -381,9 +381,9 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
String decodePwd = Base64Decoder.decodeStr(passowrd);
String hashedPassword = PwdUtil.getPassword(decodePwd, user.getSalt());
if (!Strings.sNull(hashedPassword).equalsIgnoreCase(user.getPassword())) {
if (Globals.sso) {
throw new BaseException("用户名或者密码不正确");
}
// if (Globals.sso) {
throw new BaseException("用户名或者密码不正确");
// }
}
user = this.fetchLinks(user, "unit");
if (Lang.isNotEmpty(user.getUnit()) && StrUtil.isNotBlank(user.getUnit().getUnionId())) {
@@ -1,35 +1,24 @@
package com.budwk.app.zhgh.activity.basic.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicUnitService;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @ClassName ActivityBasicUnitController
@@ -42,8 +31,10 @@ import java.util.Map;
@Ok("json:full")
public class ActivityBasicUnitController {
private static final Log log = Logs.get();
@Inject
private BaseService baseService;
private ActivityBasicUnitService activityBasicUnitService;
@Inject
private Dao dao;
@@ -54,47 +45,29 @@ public class ActivityBasicUnitController {
public void index() {
}
/**
* @param parentId 树中选中的活动单位 ID,为空时返回空列表。
* @param pageForm 分页参数和名称/编码筛选条件。
* @return Result.data 为直属下级分页,包含 list、totalCount 等分页字段。
*/
@At
@SaCheckPermission("activity.basic.unit")
public Result pageData(@Param(value = "parentId") String parentId, PageForm pageForm) {
Cnd cnd = Cnd.NEW();
if (StrUtil.isBlank(parentId)) {
cnd.and("parentId", "=", "1");
} else {
cnd.and("parentId", "=", parentId);
}
if (StrUtil.isNotBlank(pageForm.getSearchName()) && StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
cnd.and(Cnd.likeEX(pageForm.getSearchName(), pageForm.getSearchKeyword()));
}
Sql sql = Sqls.create("select id,parentId,name,unitcode,unitLevel,unionId from activity_basic_unit $condition");
cnd.asc("unitcode");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
public Result pageData(@Param("parentId") String parentId, PageForm pageForm) {
return Result.success(activityBasicUnitService.getUnitPage(parentId, pageForm));
}
/**
* @param pid 可选的活动单位 ID;不传时获取完整组织树。
* @return Result.data 为节点数组,子节点统一放在 children 中。
*/
@At
@SaCheckPermission("activity.basic.unit")
public Result tree(@Param("pid") String pid) {
try {
Cnd cnd = Cnd.NEW();
cnd.andEX("id", "=", pid);
cnd.asc("unitcode");
List<ActivityBasicUnit> list = baseService.dao().query(ActivityBasicUnit.class, cnd);
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
for (int i = 0; i < list.size(); i++) {
nodeList.add(new TreeNode<>(list.get(i).getId(), list.get(i).getParentId(), list.get(i).getName(), i)
.setExtra(
Map.of(
"unitTypeCode", list.get(i).getUnitTypeCode()
)
));
}
List<Tree<String>> treeList = TreeUtil.build(nodeList, StrUtil.blankToDefault(pid, "0"));
return Result.success(treeList);
return Result.success(activityBasicUnitService.getUnitTree(pid));
} catch (Exception e) {
return Result.error();
log.error("加载活动单位树失败,pid=" + pid, e);
return Result.error("加载活动单位树失败,请稍后重试");
}
}
@@ -0,0 +1,26 @@
package com.budwk.app.zhgh.activity.basic.service;
import cn.hutool.core.lang.tree.Tree;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import org.nutz.lang.util.NutMap;
import java.util.List;
/** 活动单位的组织树及直属下级查询,数据来源为 activity_basic_unit。 */
public interface ActivityBasicUnitService extends BaseService<ActivityBasicUnit> {
/**
* @param pid 可选的活动单位 ID;为空返回全部根节点,否则返回该单位及其后代。
* @return 树节点列表,包含 id、parentId、name、unitTypeCode 和 children;不存在的 ID 返回空列表。
*/
List<Tree<String>> getUnitTree(String pid);
/**
* @param parentId 当前选中的活动单位 ID;为空返回空分页,避免查询到其他单位。
* @param pageForm 页码、每页条数及查询条件;searchName 仅支持 name、unitcode。
* @return 直属下级分页,list 包含 id、parentId、name、unitcode、unitLevel、unionId。
*/
Pagination<NutMap> getUnitPage(String parentId, PageForm pageForm);
}
@@ -0,0 +1,90 @@
package com.budwk.app.zhgh.activity.basic.service.impl;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicUnitService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/** 按系统单位页的虚拟根规则组织活动单位,不修改数据库中的父级及工会归属。 */
@IocBean(args = {"refer:dao"})
public class ActivityBasicUnitServiceImpl extends BaseServiceImpl<ActivityBasicUnit> implements ActivityBasicUnitService {
public ActivityBasicUnitServiceImpl(Dao dao) {
super(dao);
}
@Override
public List<Tree<String>> getUnitTree(String pid) {
List<ActivityBasicUnit> units = query(Cnd.NEW().asc("unitcode"));
Set<String> ids = units.stream().map(ActivityBasicUnit::getId).collect(Collectors.toSet());
// 虚拟根只用于树构建;避开真实单位 ID,兼容空父级、孤立节点和自引用根节点。
String rootId = "root";
while (ids.contains(rootId)) {
rootId = "_" + rootId;
}
List<TreeNode<String>> nodes = new ArrayList<>();
for (int i = 0; i < units.size(); i++) {
ActivityBasicUnit unit = units.get(i);
String parentId = unit.getParentId();
if (StrUtil.isBlank(parentId) || !ids.contains(parentId) || unit.getId().equals(parentId)) {
parentId = rootId;
}
// 旧活动单位类型可为空,展示时按“其他”处理,不回写数据,也不再触发 Map.of 的空值异常。
nodes.add(new TreeNode<>(unit.getId(), parentId, unit.getName(), i)
.setExtra(NutMap.NEW().setv("unitTypeCode", unit.getUnitTypeCode() == null ? 0 : unit.getUnitTypeCode())));
}
List<Tree<String>> tree = TreeUtil.build(nodes, rootId);
if (tree == null) {
return Collections.emptyList();
}
if (StrUtil.isBlank(pid)) {
return tree;
}
// 先构建完整树再截取指定节点,避免只查询节点自身而丢失其后代。
ArrayDeque<Tree<String>> pending = new ArrayDeque<>(tree);
while (!pending.isEmpty()) {
Tree<String> node = pending.removeFirst();
if (pid.equals(node.getId())) {
return Collections.singletonList(node);
}
if (node.getChildren() != null) {
pending.addAll(node.getChildren());
}
}
return Collections.emptyList();
}
@Override
public Pagination<NutMap> getUnitPage(String parentId, PageForm pageForm) {
if (StrUtil.isBlank(parentId)) {
return new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, Collections.emptyList());
}
Cnd cnd = Cnd.where("parentId", "=", parentId).and("id", "!=", parentId);
cnd.asc("unitcode");
// 查询字段限于页面提供的单位名称、编码;自引用根节点不应出现在自身的下级列表中。
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())
&& ("name".equals(pageForm.getSearchName()) || "unitcode".equals(pageForm.getSearchName()))) {
cnd.and(Cnd.likeEX(pageForm.getSearchName(), pageForm.getSearchKeyword()));
}
Sql sql = Sqls.create("select id,parentId,name,unitcode,unitLevel,unionId from activity_basic_unit $condition");
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
}
@@ -4,7 +4,7 @@
<el-input v-model="cnd.memberSearchKeyWord" placeholder="请输入值" style="width: 100%">
<el-select v-model="cnd.memberSearchName" slot="prepend" placeholder="字段" style="width: 80px">
<el-option
v-for="column in columnInfos"
v-for="column in visibleColumnInfos"
:key="column.COLUMN_NAME"
:label="column.COLUMN_COMMENT"
:value="column.COLUMN_NAME"
@@ -24,6 +24,12 @@ module.exports = {
cnd: {}
}
},
computed: {
// 模糊查询字段由接口动态返回,屏蔽人员属性,避免通过公共查询组件再次选择该字段。
visibleColumnInfos() {
return (this.columnInfos || []).filter(column => column.COLUMN_NAME !== 'userAttribute' && column.COLUMN_COMMENT !== '人员属性')
}
},
watch: {
cnd: {
handler(val) {
@@ -2,29 +2,43 @@
layout("/layouts/platform.html"){
#-->
<style>
/* 与系统单位页保持一致的树节点间距、选中状态和图标颜色,仅作用于本页。 */
.activity-unit-tree { background: transparent; padding: 8px; }
.activity-unit-tree .el-tree-node { margin: 2px 0; border-radius: 6px; }
.activity-unit-tree .el-tree-node__content { height: 36px; line-height: 36px; padding: 0 8px; border-radius: 6px; }
.activity-unit-tree .el-tree-node.is-current > .el-tree-node__content { background: #e8f4ff; border-left: 3px solid #409eff; }
.activity-unit-tree .custom-tree-node { display: flex; align-items: center; width: 100%; gap: 8px; }
.activity-unit-tree .node-label { flex: 1; font-size: 13px; color: #303133; font-weight: 500; }
.activity-unit-tree .el-icon-folder { color: #909399; }
.activity-unit-tree .el-icon-folder-opened { color: #409eff; }
</style>
<div id="app" v-cloak>
<el-row :gutter="10" type="flex" style="height: calc(100vh - 126px)">
<el-row :gutter="20" type="flex" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never" style="height: 100%" body-style="{ height: '100%' }">
<div style="max-height: calc(100vh - 160px); overflow-y: auto">
<el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input>
<div v-loading="treeLoading" style="max-height: calc(100vh - 200px); overflow-y: auto">
<el-tree
:data="treeData"
:default-expanded-keys="['1']"
:default-expanded-keys="defaultExpandedKeys"
:expand-on-click-node="false"
:props="{
children: 'child',
children: 'children',
label: 'name'
}"
@node-click="treeNodeClick"
:filter-node-method="filterNode"
class="activity-unit-tree"
highlight-current
node-key="id"
ref="treeRef"
>
<template slot-scope="{ node, data }">
<span class="el-tree-node__label">
<span class="custom-tree-node">
<i class="el-icon-folder-opened" v-if="node.level===1"></i>
<i class="el-icon-folder" v-else></i>
{{node.label}}
<span class="node-label">{{ node.label }}</span>
</span>
</template>
</el-tree>
@@ -77,7 +91,7 @@ layout("/layouts/platform.html"){
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="100px">
<template slot-scope="{row}">
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
<el-button :disabled="deleteLoading" @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -95,50 +109,99 @@ layout("/layouts/platform.html"){
data() {
return {
pageForm: {
searchName: "name"
searchName: "name",
parentId: ""
},
treeData: [],
filterText: "",
defaultExpandedKeys: [],
treeLoading: false,
deleteLoading: false,
currentTreeNode: null,
currentTreeData: null
}
},
components: {},
watch: {
filterText(value) {
this.$refs.treeRef.filter(value)
}
},
methods: {
async doDelete(id) {
const confirm = await this.$confirm("确定要删除该单位吗?", "提示", {
doDelete(id) {
this.$confirm("确定要删除该单位吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + "/doDelete", { id })
if (resp.code === 0) {
this.getTreeData()
this.doSearch()
this.$message.success(resp.msg)
} else {
this.notifyWarning(resp.msg)
}).then(() => {
this.deleteLoading = true
// 删除后统一刷新树,由树恢复选中节点并刷新直属下级,避免重复查询或保留已删除节点。
return this.$axios.post(loc() + "/doDelete", { id })
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
return this.getTreeData()
}
this.notifyWarning(res.msg)
})
.finally(() => {
this.deleteLoading = false
})
}).catch((error) => {
if (error !== "cancel" && error !== "close") {
this.notifyWarning("删除活动单位失败,请稍后重试")
}
}
})
},
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
this.pageForm.parentId = data.id
this.$set(this.pageForm, "parentId", data.id)
// 复用公共查询方法重置页码,列表始终对应当前选中单位的直属下级。
this.doSearch()
},
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.currentTreeData = this.treeData[0]
}
})
filterNode(value, data) {
return !value || (data.name || "").indexOf(value) !== -1
},
openUnit() {}
getTreeData() {
this.treeLoading = true
return this.$axios.post(loc() + "/tree")
.then((res) => {
if (res.code !== 0) {
this.notifyWarning(res.msg || "加载活动单位树失败")
return
}
this.treeData = res.data || []
this.defaultExpandedKeys = this.treeData.length ? [this.treeData[0].id] : []
return this.$nextTick(() => {
// 首次选中实际根节点;刷新时保留有效选中项,不再假定根单位 ID 为 1。
const tree = this.$refs.treeRef
const selectedId = this.currentTreeData ? this.currentTreeData.id : null
const selectedNode = selectedId ? tree.getNode(selectedId) : null
const data = selectedNode ? selectedNode.data : this.treeData[0]
tree.filter(this.filterText)
tree.setCurrentKey(data ? data.id : null)
if (data) {
this.treeNodeClick(data, tree.getNode(data.id))
} else {
// 空树直接清空旧列表,避免显示刷新前的单位数据。
this.currentTreeData = null
this.currentTreeNode = null
this.$set(this.pageForm, "parentId", "")
this.$set(this.pageForm, "pageNumber", 1)
this.$set(this.pageForm, "totalCount", 0)
this.tableData = []
}
})
})
.catch(() => {
this.notifyWarning("加载活动单位树失败,请稍后重试")
})
.finally(() => {
this.treeLoading = false
})
}
},
created() {
this.pageData()
this.getTreeData()
}
})
@@ -51,9 +51,9 @@ layout("/layouts/platform.html"){
<div class="search-item-option">
<el-select placeholder="所属工会" v-model="pageForm.unionId" style="width: 100%;"
clearable
@change="flushUnits" @clear="flushUnits"
@change="flushUnits"
filterable>
<el-option v-for="item in unions" :label="item.unionname" :value="item.id"></el-option>
<el-option v-for="item in unions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</div>
</div>
@@ -64,7 +64,7 @@ layout("/layouts/platform.html"){
<el-select placeholder="所属单位" v-model="pageForm.unitId" style="width: 100%;"
clearable
filterable>
<el-option v-for="item in units" :label="item.name" :value="item.id"></el-option>
<el-option v-for="item in units" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</div>
</div>
@@ -144,6 +144,7 @@ layout("/layouts/platform.html"){
<script nonce="${cspNonce!}">
const vue = new Vue({
el: '#app',
store,
mixins: [initTableMixins],
components: {
"vcron": typeof vcrontab !== 'undefined' ? vcrontab.default || vcrontab : null
@@ -153,11 +154,17 @@ layout("/layouts/platform.html"){
pageForm: {
data: moment().format('YYYY-MM-DD'),
searchName: "username",
blessingName: ''
blessingName: '',
unionId: '',
unitId: ''
},
sexOptions: ['男', '女'],
unions: [],
units: [],
// null 表示用户组织信息未就绪,空字符串表示校级管理员可选择全部工会。
orgUnionId: null,
unionRequestVersion: 0,
unitRequestVersion: 0,
activityGroupList: [],
dialogVisible: false,
tableColumns: [
@@ -176,26 +183,64 @@ layout("/layouts/platform.html"){
showCron: false,
}
},
watch: {
"$store.state.user": {
// 公共布局异步更新登录用户,角色和所属工会就绪后重新加载选项。
handler() {
this.initOrgOptions()
},
immediate: true
}
},
methods: {
async getActivityGroup() {
const {data} = await $.get('/platform/activity/basic/scope/getActivityUserScopeGroup')
this.activityGroupList = data
getActivityGroup() {
return $.get('/platform/activity/basic/scope/getActivityUserScopeGroup').then((res) => {
this.activityGroupList = res.data
})
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
if (this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN')) {
this.units = await this.$businessTool.listUnit(this.pageForm.unionId)
} else {
this.units = await this.$businessTool.listUnit(this.$store.state.user.union.id)
initOrgOptions() {
const requestVersion = ++this.unionRequestVersion
const user = this.$store.state.user
this.orgUnionId = null
this.unions = []
this.$set(this.pageForm, "unionId", '')
if (user && Array.isArray(user.roles)) {
// 与会员查询页面保持一致:校级管理角色可选全部工会,其余角色限定所属工会。
const hasAdmin = this.$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, SCHOOL_UNION_MEMBER_ADMIN')
this.orgUnionId = hasAdmin ? '' : ((user.union && user.union.id) || null)
}
this.flushUnits()
if (this.orgUnionId === null) {
return
}
this.$businessTool.listUnion(this.orgUnionId).then((data) => {
// 用户状态变化后丢弃旧响应,避免不同组织范围的选项互相覆盖。
if (requestVersion === this.unionRequestVersion) {
this.unions = Array.isArray(data) ? data : []
}
})
},
flushUnits() {
const requestVersion = ++this.unitRequestVersion
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.orgUnionId === null) {
return
}
// 选中工会时加载对应单位;清空时恢复当前角色可选择的单位范围。
const unionId = this.orgUnionId || this.pageForm.unionId || ''
this.$businessTool.listUnit(unionId).then((data) => {
// 快速切换或清空工会时,仅接受最后一次单位查询的结果。
if (requestVersion === this.unitRequestVersion) {
this.units = Array.isArray(data) ? data : []
}
})
},
},
async created() {
await this.getActivityGroup()
created() {
this.getActivityGroup()
this.pageData()
this.unions = await this.$businessTool.listUnion()
this.flushUnits()
}
})
@@ -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"
@@ -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>
@@ -76,8 +76,8 @@ const INFO = {
</template>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="变更信息" name="changeInfo" v-if="viewData.changeInfos">
<el-table :data="viewData.changeInfos" :size="tableSize" @sort-change="pageOrder" ref="table"
<el-tab-pane label="变更信息" name="changeInfo" v-if="visibleChangeInfos.length">
<el-table :data="visibleChangeInfos" :size="tableSize" @sort-change="pageOrder" ref="table"
row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
@@ -144,6 +144,12 @@ const INFO = {
activeName: "basicInfo",
}
},
computed: {
// 变更明细仅屏蔽人员属性的展示,保留接口返回的原始记录。
visibleChangeInfos() {
return (this.viewData.changeInfos || []).filter(item => item.field !== 'userAttribute' && item.fieldName !== '人员属性')
}
},
methods: {
// 打开
onOpen(row) {
@@ -61,9 +61,9 @@ const MEMBER_ALL_CHANGE_INFO = {
</template>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="历史变更记录" name="changeInfo" v-if="viewData.allChangeInfo">
<el-tab-pane label="历史变更记录" name="changeInfo" v-if="visibleAllChangeInfo.length">
<el-timeline>
<el-timeline-item placement="top" v-for="(changeData, index) in viewData.allChangeInfo"
<el-timeline-item placement="top" v-for="(changeData, index) in visibleAllChangeInfo"
:key="index" :timestamp="changeData.timestamp">
<el-card>
<h4>{{ changeData.changeOriginName }}</h4>
@@ -86,6 +86,7 @@ const MEMBER_ALL_CHANGE_INFO = {
</el-timeline-item>
</el-timeline>
</el-tab-pane>
<slot></slot>
</el-tabs>
`,
store,
@@ -95,6 +96,15 @@ const MEMBER_ALL_CHANGE_INFO = {
activeName: "basicInfo"
}
},
computed: {
// 仅过滤历史记录的展示副本;隐藏人员属性明细及过滤后为空的记录,原始数据保持不变。
visibleAllChangeInfo() {
return (this.viewData.allChangeInfo || []).map(item => ({
...item,
changeInfos: (item.changeInfos || []).filter(field => field.field !== 'userAttribute' && field.fieldName !== '人员属性')
})).filter(item => item.changeInfos.length > 0)
}
},
methods:{
onOpen(userId){
this.$axios.post('/platform/member/change/manage/getAllChangeMemberInfo', {userId})
@@ -140,7 +140,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>
@@ -43,7 +43,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>
@@ -69,7 +70,8 @@ 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>
@@ -231,7 +233,8 @@ layout("/layouts/platform.html"){
<member-all-change ref="memberAllChangeRef"></member-all-change>
</template>
<el-drawer
<!-- 人员属性批量设置弹框同步屏蔽,保留原有字段和处理逻辑。 -->
<el-drawer v-if="false"
:before-close="handleClose"
:visible.sync="batchEditUserAttributeVisible"
size="1000px" title="批量设置人员属性">
@@ -560,7 +563,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 },
@@ -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>
@@ -59,8 +59,8 @@
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="变更信息" name="changeInfo" v-if="viewData.changeInfos">
<el-table :data="viewData.changeInfos" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-tab-pane label="变更信息" name="changeInfo" v-if="visibleChangeInfos.length">
<el-table :data="visibleChangeInfos" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="id" style="width: 100%">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column prop="fieldName" label="变更字段" header-align="center"></el-table-column>
@@ -119,6 +119,12 @@
doneTasks: []
}
},
computed: {
// 变更明细仅屏蔽人员属性的展示,保留接口返回的原始记录。
visibleChangeInfos() {
return (this.viewData.changeInfos || []).filter(item => item.field !== 'userAttribute' && item.fieldName !== '人员属性')
}
},
methods: {
info() {
this.$axios.post("/platform/member/change/view/findMemberChangeRecord", { id: this.businessId }).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>
@@ -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>
@@ -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>
@@ -129,7 +129,8 @@ 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"
@@ -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 },
@@ -113,7 +113,8 @@ 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,8 @@ 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"
@@ -84,7 +84,8 @@ const filterUser = {
v-model="pageForm.personTypes"></dict-select>
</search-item>
<search-item label="人员属性:">
<!-- 人员属性统一屏蔽,仅隐藏前端入口,保留原字段数据。 -->
<search-item label="人员属性:" v-if="false">
<dict-select clearable code="USER_ATTRIBUTE"
multiple
collapse-tags
@@ -65,7 +65,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.userAttribute" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE"></dict-select>
</search-item>
@@ -113,7 +113,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.userAttribute" placeholder="请选择人员属性" @change="doSearch"
code="USER_ATTRIBUTE"></dict-select>
</search-item>