From 55cd8c86fabdda97eeef151e365a29a827c5b083 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 18 Aug 2026 15:17:32 +0800 Subject: [PATCH] commit --- .../ClubAuditManagerController.java | 4 +- .../club/model/SysClubExamineRegister.java | 8 ++ .../impl/SysClubExamineServiceImpl.java | 122 ++++++++++++++++-- .../controller/HonorSummaryController.java | 24 ++-- .../plugins/sysFilePreview/H5Index.vue | 28 ++-- .../plugins/sysFilePreview/index.vue | 28 ++-- .../sys/union/branchUnionUserManage.js | 5 +- .../zhgh/club/examine/common/examineInfo.js | 119 +++++++++++++---- .../zhghh5/dayofficework/qsv/vote/index.html | 8 ++ 9 files changed, 274 insertions(+), 72 deletions(-) diff --git a/src/main/java/com/budwk/app/zhgh/club/controller/infoManage/ClubAuditManagerController.java b/src/main/java/com/budwk/app/zhgh/club/controller/infoManage/ClubAuditManagerController.java index 25ab0593..30160fbf 100644 --- a/src/main/java/com/budwk/app/zhgh/club/controller/infoManage/ClubAuditManagerController.java +++ b/src/main/java/com/budwk/app/zhgh/club/controller/infoManage/ClubAuditManagerController.java @@ -90,10 +90,12 @@ public class ClubAuditManagerController { cnd.andEX("year(info.creatTime)", "=", pageForm.getYear()); cnd.and("t.taskName", "=", "ef81777f-22fb-4fe4-9800-909e6c681210"); - cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); if (approval) { + // 已审核是全量历史,不能因历史工作流参与人不同而遗漏参考库迁移记录。 cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); } else { + // 未审核只展示当前登录人实际可以处理的待办任务。 + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); } diff --git a/src/main/java/com/budwk/app/zhgh/club/model/SysClubExamineRegister.java b/src/main/java/com/budwk/app/zhgh/club/model/SysClubExamineRegister.java index 3b41d961..a672c7b8 100644 --- a/src/main/java/com/budwk/app/zhgh/club/model/SysClubExamineRegister.java +++ b/src/main/java/com/budwk/app/zhgh/club/model/SysClubExamineRegister.java @@ -95,6 +95,14 @@ public class SysClubExamineRegister extends BaseModel { @ColDefine(type = ColType.MYSQL_JSON) private List yearActivityList; + /** + * 旧版年审表保存的年度活动明细,保留该字段用于查看迁移历史数据。 + */ + @Column + @Comment("旧版年度活动明细") + @ColDefine(type = ColType.MYSQL_JSON) + private List yearActivitys; + @Column @Comment("财务收支情况统计json") @ColDefine(type = ColType.MYSQL_JSON) diff --git a/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubExamineServiceImpl.java b/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubExamineServiceImpl.java index 9b2521b7..c52d0e4d 100644 --- a/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubExamineServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubExamineServiceImpl.java @@ -8,6 +8,7 @@ import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.flow.entity.ProcessInstance; import com.budwk.app.flow.enums.ProcessInstanceStateEnum; import com.budwk.app.flow.enums.ProcessTaskStateEnum; import com.budwk.app.web.commons.auth.utils.AuthUtil; @@ -33,8 +34,10 @@ import org.nutz.lang.util.NutMap; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; @IocBean(args = {"refer:dao"}) @@ -119,6 +122,7 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl applications = listMap(applySql); + if (!applications.isEmpty()) { + // 流程状态改为按当前社团申请批量查询,避免相关子查询对流程实例表重复扫描。 + List applicationIds = applications.stream() + .map(application -> application.getString("id")) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toList()); + List finishedInstances = applicationIds.isEmpty() ? new ArrayList<>() + : dao().query(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "in", applicationIds) + .and(ProcessInstance::getState, "=", ProcessInstanceStateEnum.FINISHED.getCode())); + Set finishedBusinessNos = finishedInstances.stream() + .map(ProcessInstance::getBusinessNo) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(HashSet::new)); + applications.removeIf(application -> !finishedBusinessNos.contains(application.getString("id"))); + } applications.sort(Comparator.comparing(row -> row.getTime("applyDate"), Comparator.nullsLast(Date::compareTo))); for (NutMap application : applications) { @@ -259,6 +271,10 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl detailedList = dao().query(SysClubExamineRegisterDetailed.class, Cnd.where("registerId", "=", id).asc("location")); clubExamineVo.setDetailedList(detailedList); @@ -512,6 +530,94 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl yearActivitySource = examineVo.getYearActivityList(); + if (yearActivitySource == null || yearActivitySource.isEmpty()) { + yearActivitySource = examineVo.getYearActivitys(); + } + examineVo.setYearActivityList(yearActivitySource == null ? new ArrayList<>() + : yearActivitySource.stream() + .map(item -> normalizeActivityItem(item, true)) + .collect(Collectors.toList())); + + List planSource = examineVo.getPlans(); + examineVo.setPlans(planSource == null ? new ArrayList<>() + : planSource.stream() + .map(item -> normalizeActivityItem(item, false)) + .collect(Collectors.toList())); + } + + /** + * 将V3工作总结附件的文件主键包装为V4文件预览组件所需的response.data格式。 + * + * @param summaryFiles 原始工作总结附件 + * @return 可供文件预览组件读取的附件数据 + */ + private List normalizeSummaryFiles(List summaryFiles) { + if (summaryFiles == null || summaryFiles.isEmpty()) { + return new ArrayList<>(); + } + return summaryFiles.stream() + .filter(Objects::nonNull) + .map(file -> { + JSONObject response = file.getJSONObject("response"); + if (response != null && StrUtil.isNotBlank(response.getStr("data"))) { + return file; + } + String fileId = file.getStr("id"); + if (StrUtil.isBlank(fileId)) { + return null; + } + JSONObject normalizedFile = new JSONObject(); + normalizedFile.set("response", new JSONObject().set("data", fileId)); + return normalizedFile; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + /** + * 兼容V3活动字段(hdsj、mc、zbdw、hddd、cjrs、hjqk)和V4活动字段。 + * + * @param source 原始活动或计划数据 + * @param includeResult 是否包含本年度活动的参加人数和获奖情况 + * @return 供查看页使用的统一字段数据 + */ + private JSONObject normalizeActivityItem(JSONObject source, boolean includeResult) { + JSONObject item = new JSONObject(); + item.set("activityName", getActivityValue(source, "activityName", "mc")); + item.set("activityUnit", getActivityValue(source, "activityUnit", "zbdw")); + item.set("activityAddress", getActivityValue(source, "activityAddress", "hddd")); + if (includeResult) { + item.set("activityTime", getActivityValue(source, "activityTime", "hdsj")); + item.set("joinNum", getActivityValue(source, "joinNum", "cjrs")); + item.set("prize", getActivityValue(source, "prize", "hjqk")); + } + return item; + } + + /** + * 优先读取V4字段;历史记录没有该字段时回退读取对应的V3字段。 + * + * @param source 原始JSON数据 + * @param currentField V4字段名 + * @param legacyField V3字段名 + * @return 兼容后的字段值 + */ + private String getActivityValue(JSONObject source, String currentField, String legacyField) { + if (source == null) { + return null; + } + String currentValue = source.getStr(currentField); + return StrUtil.isNotBlank(currentValue) ? currentValue : source.getStr(legacyField); + } + @Override public List getYearActivityExportData(String id) { ClubExamineVo examineVo = this.findOne(id); diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/honor/controller/HonorSummaryController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/honor/controller/HonorSummaryController.java index 5aaa36e9..fa005714 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/honor/controller/HonorSummaryController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/honor/controller/HonorSummaryController.java @@ -79,21 +79,27 @@ public class HonorSummaryController { @At @SaCheckPermission("honor.honorLevel.Summary") public Result honorLevelData(HonorPageForm pageForm) { - - List query = dao.query(HonorBasicSettings.class, Cnd.where("queryTypeCode", "in", - List.of(HonorTypeOrigin.HONOR_SCHOOL_LEVEL.name(), HonorTypeOrigin.HONOR_PROVINCIAL_LEVEL.name(), HonorTypeOrigin.HONOR_NATIONAL_LEVEL.name()))); - String schoolHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SCHOOL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId(); - String provincialHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_PROVINCIAL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId(); - String nationalHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_NATIONAL_LEVEL.name())).findFirst().orElse(new HonorBasicSettings()).getId(); + HonorBasicSettings levelRoot = dao.fetch(HonorBasicSettings.class, + Cnd.where("queryTypeCode", "=", HonorTypeOrigin.HONOR_LEVEL.name())); + List levelList = levelRoot == null ? List.of() : dao.query(HonorBasicSettings.class, + Cnd.where("parentId", "=", levelRoot.getId())); + String schoolHonorId = levelList.stream().filter(item -> "校内".equals(item.getName())) + .findFirst().orElse(new HonorBasicSettings()).getId(); + String provincialHonorId = levelList.stream().filter(item -> "省部级".equals(item.getName())) + .findFirst().orElse(new HonorBasicSettings()).getId(); + String nationalHonorId = levelList.stream().filter(item -> "国家级".equals(item.getName())) + .findFirst().orElse(new HonorBasicSettings()).getId(); Cnd cnd = Cnd.NEW(); + // honor.honorLevel 直接保存荣誉等级项 ID,按“荣誉等级”下的具体等级项统计。 + // 历史荣誉记录可能未保存 unionId,统计时仅在 unionId 为空时按 unionName 回退关联。 Sql sql = Sqls.create(""" SELECT id, name as unionname, - ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @nationalLevel AND h.unionId = un.id $cnd) nationalLevelNum, - ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @provincial AND h.unionId = un.id $cnd) provincialNum , - ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @schoolLevel AND h.unionId = un.id $cnd) schoolLevelNum + ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @nationalLevel AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) nationalLevelNum, + ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @provincial AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) provincialNum , + ( SELECT COUNT( 1 ) FROM honor h WHERE h.honorLevel = @schoolLevel AND (h.unionId = un.id OR ((h.unionId IS NULL OR h.unionId = '') AND h.unionName = un.name)) $cnd) schoolLevelNum FROM sys_union un $condition """).setParam("nationalLevel", nationalHonorId).setParam("provincial", provincialHonorId).setParam("schoolLevel", schoolHonorId); diff --git a/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue b/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue index da51d706..a721e438 100644 --- a/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue +++ b/src/main/resources/static/components/plugins/sysFilePreview/H5Index.vue @@ -65,22 +65,10 @@ module.exports = { let ids = [] if (this.complete_result) { if (Array.isArray(val)) { - ids = val.map((item) => { - if (item.response.data.includes("=")) { - return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1) - } else { - return item?.response?.data - } - }) + ids = val.map((item) => this.resolveFileId(item)).filter((id) => id) } else { try { - ids = JSON.parse(val).map((item) => { - if (item.response.data.includes("=")) { - return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1) - } else { - return item?.response?.data - } - }) + ids = JSON.parse(val).map((item) => this.resolveFileId(item)).filter((id) => id) } catch (err) { this.fileList = [] } @@ -100,6 +88,18 @@ module.exports = { this.requestFullFile(ids) }, + // 新版上传组件保存 response.data,迁移的历史附件保留原文件主键 id。 + resolveFileId(item) { + if (!item) { + return "" + } + const fileValue = item.response && item.response.data ? item.response.data : item.id + if (typeof fileValue !== "string" || !fileValue) { + return "" + } + return fileValue.includes("=") ? fileValue.substring(fileValue.lastIndexOf("=") + 1) : fileValue + }, + requestFullFile(ids) { this.$axios.post("/platform/sys/file/previewFileData", {ids: JSON.stringify(ids)}).then((res) => { if (res.code === 0) { diff --git a/src/main/resources/static/components/plugins/sysFilePreview/index.vue b/src/main/resources/static/components/plugins/sysFilePreview/index.vue index 7fcb5326..d7edd1ea 100644 --- a/src/main/resources/static/components/plugins/sysFilePreview/index.vue +++ b/src/main/resources/static/components/plugins/sysFilePreview/index.vue @@ -65,22 +65,10 @@ module.exports = { let ids = [] if (this.complete_result) { if (Array.isArray(val)) { - ids = val.map((item) => { - if (item.response.data.includes("=")) { - return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1) - } else { - return item?.response?.data - } - }) + ids = val.map((item) => this.resolveFileId(item)).filter((id) => id) } else { try { - ids = JSON.parse(val).map((item) => { - if (item.response.data.includes("=")) { - return item?.response?.data.substring(item?.response?.data.lastIndexOf("=") + 1) - } else { - return item?.response?.data - } - }) + ids = JSON.parse(val).map((item) => this.resolveFileId(item)).filter((id) => id) } catch (err) { this.fileList = [] } @@ -100,6 +88,18 @@ module.exports = { this.requestFullFile(ids) }, + // 新版上传组件保存 response.data,迁移的历史附件保留原文件主键 id。 + resolveFileId(item) { + if (!item) { + return "" + } + const fileValue = item.response && item.response.data ? item.response.data : item.id + if (typeof fileValue !== "string" || !fileValue) { + return "" + } + return fileValue.includes("=") ? fileValue.substring(fileValue.lastIndexOf("=") + 1) : fileValue + }, + requestFullFile(ids) { this.$axios.post("/platform/sys/file/previewFileData", { ids: JSON.stringify(ids) }).then((res) => { if (res.code === 0) { diff --git a/src/main/resources/views/platform/sys/union/branchUnionUserManage.js b/src/main/resources/views/platform/sys/union/branchUnionUserManage.js index 81e4fffc..2ee8ce8d 100644 --- a/src/main/resources/views/platform/sys/union/branchUnionUserManage.js +++ b/src/main/resources/views/platform/sys/union/branchUnionUserManage.js @@ -198,7 +198,8 @@ const branchUnionUserManage = { initJSearch() { const optionTask = this.jOptions.length ? $.Deferred().resolve().promise() : this.loadJOptions() $.when(optionTask, this.loadUsedJCodes()).then(() => { - this.pageForm.j = this.getHighestUsedJ() + // 页面初始化时不限定届次,默认展示该分工会所有届次的干部。 + this.pageForm.j = "" this.pageData() }) }, @@ -225,6 +226,8 @@ const branchUnionUserManage = { }).then((res) => { if (res.code === 0) { this.$set(this, "partySecretaryUnitOptions", res.data || []) + // 新增二级党委书记时,默认授权当前分工会下的全部二级单位。 + this.$set(this.formData, "unitIds", this.partySecretaryUnitOptions.map(item => item.id)) } }) }, diff --git a/src/main/resources/views/platform/zhgh/club/examine/common/examineInfo.js b/src/main/resources/views/platform/zhgh/club/examine/common/examineInfo.js index db45eeea..60b72e07 100644 --- a/src/main/resources/views/platform/zhgh/club/examine/common/examineInfo.js +++ b/src/main/resources/views/platform/zhgh/club/examine/common/examineInfo.js @@ -105,8 +105,8 @@ - {{ task.taskFormData.userName - }}({{task.taskFormData.loginName}}) + {{ getTaskFormValue(task, "userName", "tf_userName") + }}({{ getTaskFormValue(task, "loginName", "tf_loginName") }}) {{ task.finishTime }} @@ -114,7 +114,7 @@ :value="task.ext.submitType"> {{ - task.taskFormData.opinion }} + getTaskFormValue(task, "opinion", "tf_opinion") }} @@ -125,7 +125,7 @@ {{ record.userName }}({{ record.loginName }}) {{ record.auditTime }} - {{ record.auditPass ? "审核通过" : "审核不通过" }} + {{ getLegacyAuditResult(record) }} {{ record.auditOpinion }} @@ -140,7 +140,14 @@ dicts: ["PROCESS_TASK_SUBMIT_TYPE"], data() { return { - viewData: {}, + viewData: { + changeUserNum: [], + detailedList: [], + incomeCensus: [], + jgUser: [], + plans: [], + yearActivityList: [] + }, activeName: "1", row: {}, doneTasks: [], @@ -165,37 +172,99 @@ getAuditDisplayName(displayName) { return displayName === "协会审核" ? "会长审核" : displayName }, + // 历史流程任务使用tf_前缀保存表单字段,正常流程继续优先读取标准字段。 + getTaskFormValue(task, fieldName, legacyFieldName) { + const formData = task.taskFormData || {} + return formData[fieldName] || formData[legacyFieldName] || "—" + }, + // 旧审核表的auditPass可能为空,不能按false错误展示为审核不通过。 + getLegacyAuditResult(record) { + if (record.auditPass === true || record.auditPass === 1) { + return "审核通过" + } + if (record.auditPass === false || record.auditPass === 0) { + return "审核不通过" + } + return "—" + }, async onOpen(row) { - this.row = row - const resp = await this.$axios.post("/platform/club/examine/common/findOne", { id: row.id }) - if (resp.code === 0) { - this.viewData = resp.data - this.$set(this, "legacyAuditRecords", resp.data.legacyAuditRecords || []) - await this.getClubUserNum(resp.data.clubId) - await this.getJgUser(resp.data.clubId) + this.$set(this, "row", row) + this.$set(this, "doneTasks", []) + this.$set(this, "legacyAuditRecords", []) + try { + const resp = await this.$axios.post("/platform/club/examine/common/findOne", { id: row.id }) + if (resp.code !== 0) { + this.$message.error(resp.msg || "查询年审详情失败") + return + } + const viewData = resp.data || {} + this.$set(this, "viewData", viewData) + this.$set(this, "legacyAuditRecords", viewData.legacyAuditRecords || []) + // 三类补充数据独立加载,成员变化统计失败不能阻断成员和审核记录显示。 + await Promise.all([ + this.getClubUserNum(viewData.clubId), + this.getJgUser(viewData.clubId), + this.getDoneTasks() + ]) + } catch (error) { + this.$message.error("查询年审详情失败") } - this.getDoneTasks() }, async getClubUserNum(clubId) { - const resp = await this.$axios.post("/platform/club/examine/apply/getClubUserNum", { - clubId: clubId, - year: this.row.year - }) - this.$set(this.viewData, "changeUserNum", resp.data) + if (!clubId) { + this.$set(this.viewData, "changeUserNum", []) + return + } + try { + const resp = await this.$axios.post("/platform/club/examine/apply/getClubUserNum", { + clubId: clubId, + year: this.row.year + }) + if (resp.code === 0) { + this.$set(this.viewData, "changeUserNum", resp.data || []) + } else { + this.$set(this.viewData, "changeUserNum", []) + this.$message.warning(resp.msg || "查询社团成员变化情况失败") + } + } catch (error) { + this.$set(this.viewData, "changeUserNum", []) + this.$message.warning("查询社团成员变化情况失败") + } }, async getJgUser(clubId) { - const respUser = await this.$axios.post("/platform/club/examine/apply/getJgUser", { - clubId: clubId - }) - this.$set(this.viewData, "jgUser", respUser.data) + if (!clubId) { + this.$set(this.viewData, "jgUser", []) + return + } + try { + const respUser = await this.$axios.post("/platform/club/examine/apply/getJgUser", { + clubId: clubId + }) + if (respUser.code === 0) { + this.$set(this.viewData, "jgUser", respUser.data || []) + } else { + this.$set(this.viewData, "jgUser", []) + this.$message.warning(respUser.msg || "查询社团成员失败") + } + } catch (error) { + this.$set(this.viewData, "jgUser", []) + this.$message.warning("查询社团成员失败") + } }, // 获取已办任务审批记录 - getDoneTasks() { - this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => { + async getDoneTasks() { + try { + const res = await this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}) if (res.code === 0) { this.$set(this, "doneTasks", res.data || []) + } else { + this.$set(this, "doneTasks", []) + this.$message.warning(res.msg || "查询审核记录失败") } - }) + } catch (error) { + this.$set(this, "doneTasks", []) + this.$message.warning("查询审核记录失败") + } }, // 查看流程图 openChart(){ diff --git a/src/main/resources/views/platform/zhghh5/dayofficework/qsv/vote/index.html b/src/main/resources/views/platform/zhghh5/dayofficework/qsv/vote/index.html index 2475384a..0d0bba5d 100644 --- a/src/main/resources/views/platform/zhghh5/dayofficework/qsv/vote/index.html +++ b/src/main/resources/views/platform/zhghh5/dayofficework/qsv/vote/index.html @@ -103,6 +103,7 @@ layout("/layouts/platform_h5.html"){ @@ -1980,6 +1981,13 @@ layout("/layouts/platform_h5.html"){ font-size: 14px; } + /* 已完成投票状态使用浅蓝色,与投票结束状态保持区分。 */ + .vote-bottom .van-button.vote-finished-button, + .vote-bottom .van-button.vote-finished-button.van-button--disabled { + color: #ffffff; + background: #86a8f7; + } + .vote-bottom .van-button .fa { display: none; }