From 0204dc8c929d7ba8df5dc947a4dab08b8805fc6c Mon Sep 17 00:00:00 2001 From: hongqiwei <1143662660@qq.com> Date: Mon, 21 Sep 2026 16:30:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E5=86=8C=E5=8D=8F=E4=BC=9A=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E5=AE=8C=E6=88=90=E5=90=8E=E5=AF=BC=E5=87=BA=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E8=A1=A8=20=E6=B3=A8=E5=86=8C=E5=8D=8F=E4=BC=9A?= =?UTF-8?q?=E7=9A=84=E4=B8=8A=E4=BC=A0=E7=94=B3=E8=AF=B7=E8=A1=A8=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E4=B8=8D=E5=BF=85=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../register/ClubMyApplyController.java | 8 ++ .../budwk/app/zhgh/club/model/SysClub.java | 1 - .../app/zhgh/club/service/SysClubService.java | 13 +- .../club/service/impl/SysClubServiceImpl.java | 124 +++++++++++++++++- .../club/register/apply/clubRegisterForm.js | 2 - .../zhgh/club/register/apply/index.html | 22 +--- .../zhgh/club/register/mine/index.html | 4 + 7 files changed, 148 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/budwk/app/zhgh/club/controller/register/ClubMyApplyController.java b/src/main/java/com/budwk/app/zhgh/club/controller/register/ClubMyApplyController.java index e80ae52..d6c3863 100644 --- a/src/main/java/com/budwk/app/zhgh/club/controller/register/ClubMyApplyController.java +++ b/src/main/java/com/budwk/app/zhgh/club/controller/register/ClubMyApplyController.java @@ -70,4 +70,12 @@ public class ClubMyApplyController { flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id); return Result.success(); } + + @At + @Ok("void") + @ApiOperation("导出协会申请表") + @SaCheckPermission("club.register.myApply") + public void exportApply(@Valid String id, javax.servlet.http.HttpServletResponse response) { + sysClubService.exportApply(id, response); + } } diff --git a/src/main/java/com/budwk/app/zhgh/club/model/SysClub.java b/src/main/java/com/budwk/app/zhgh/club/model/SysClub.java index 3f40ecb..31fc8d3 100644 --- a/src/main/java/com/budwk/app/zhgh/club/model/SysClub.java +++ b/src/main/java/com/budwk/app/zhgh/club/model/SysClub.java @@ -103,7 +103,6 @@ public class SysClub extends BaseModel { @Column @Comment("申请成立报告") @ColDefine(type = ColType.MYSQL_JSON) - @NotEmpty(message = "申请成立报告不能为空") private List establishReport; @Column diff --git a/src/main/java/com/budwk/app/zhgh/club/service/SysClubService.java b/src/main/java/com/budwk/app/zhgh/club/service/SysClubService.java index 2c8ee07..92b5952 100644 --- a/src/main/java/com/budwk/app/zhgh/club/service/SysClubService.java +++ b/src/main/java/com/budwk/app/zhgh/club/service/SysClubService.java @@ -46,9 +46,10 @@ public interface SysClubService extends BaseService { void validateManagePerson(List managePerson); /** - * 校验协会正式提交时申请成立报告和章程草案是否已上传。 + * 校验协会正式提交时章程草案是否已上传,申请成立报告为选填。 * - * @param club 协会申请信息 + * @param club 协会申请信息,rulesFile 应包含已上传的章程草案附件 + * @throws com.budwk.app.base.exception.BaseException 申请信息为空或未上传章程草案;校验通过时无返回值 */ void validateRequiredFiles(SysClub club); @@ -70,6 +71,14 @@ public interface SysClubService extends BaseService { */ void downloadRulesTemplate(HttpServletRequest request, HttpServletResponse response) throws IOException; + /** + * 按协会申请表模板导出已提交的协会申请。 + * + * @param clubId 申请协会 ID + * @param response HTTP 响应,用于输出渲染后的 Word 文件 + */ + void exportApply(String clubId, HttpServletResponse response); + Pagination minePageData(@Valid ClubUserPageForm pageForm); Pagination schoolLeaderAuditPageData(@Valid ClubUserPageForm pageForm); diff --git a/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubServiceImpl.java b/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubServiceImpl.java index 07b27be..673d344 100644 --- a/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/club/service/impl/SysClubServiceImpl.java @@ -9,7 +9,9 @@ import com.budwk.app.base.exception.BaseException; 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.base.utils.CommonDownloadUtil; import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.base.utils.SysOfficeTemplateUtil; import com.budwk.app.bpm.enums.BpmProcessInstanceStatusEnum; import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum; import com.budwk.app.bpm.models.BpmProcessInstance; @@ -33,6 +35,9 @@ import com.budwk.app.zhgh.club.service.SysClubUserService; import com.budwk.app.zhgh.club.vo.ClubCommonPageVo; import com.budwk.app.zhgh.club.vo.ClubRegisterPageVo; import com.budwk.app.zhgh.club.vo.ClubRegisterVo; +import com.deepoove.poi.XWPFTemplate; +import cn.hutool.json.JSONUtil; +import com.deepoove.poi.config.Configure; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; @@ -43,7 +48,9 @@ import org.nutz.lang.util.NutMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -69,6 +76,8 @@ public class SysClubServiceImpl extends BaseServiceImpl implements SysC private BpmService bpmService; @Inject private SysFileService sysFileService; + @Inject + private SysOfficeTemplateUtil sysOfficeTemplateUtil; @Override public Pagination getAllClubWithPage(PageForm pageForm, Cnd cnd) { @@ -126,6 +135,114 @@ public class SysClubServiceImpl extends BaseServiceImpl implements SysC downloadClubTemplate("club_rules", "协会章程草案模板", request, response); } + @Override + public void exportApply(String clubId, HttpServletResponse response) { + Sql clubSql = Sqls.create(""" + SELECT c.clubName, c.createTime, c.introduce, c.purpose, + u.username AS applicantName, u.mobile AS applicantMobile, + u.unitName AS applicantUnitName + FROM sys_club c + LEFT JOIN vw_user u ON u.id = c.userId + WHERE c.id = @clubId + """); + clubSql.setParam("clubId", clubId); + clubSql.setCallback(Sqls.callback.map()); + dao().execute(clubSql); + NutMap club = (NutMap) clubSql.getResult(); + if (ObjectUtil.isEmpty(club)) { + throw new BaseException("协会申请不存在"); + } + + Sql memberSql = Sqls.create(""" + SELECT u.username, u.unitName, u.mobile, + CASE + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_PRESIDENT\"') THEN '会长' + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_SECRETARY\"') THEN '秘书长' + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_VICE_PRESIDENT\"') THEN '副会长' + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_VICE_SECRETARY\"') THEN '副秘书长' + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_OPERATOR\"') THEN '经办人' + ELSE '理事' + END AS roleName + FROM club_user cu + LEFT JOIN vw_user u ON u.id = cu.userId + WHERE cu.clubId = @clubId + ORDER BY CASE + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_PRESIDENT\"') THEN 1 + WHEN JSON_CONTAINS(cu.roleCode, '\"CLUB_SECRETARY\"') THEN 2 + ELSE 3 + END + """); + memberSql.setParam("clubId", clubId); + List members = listMap(memberSql); + StringBuilder managementInfo = new StringBuilder(); + for (NutMap member : members) { + if (managementInfo.length() > 0) { + managementInfo.append("\n"); + } + managementInfo.append(member.getString("roleName", "理事")) + .append(":").append(member.getString("username", "")) + .append(",所属单位:").append(member.getString("unitName", "")) + .append(",联系电话:").append(member.getString("mobile", "")); + } + + Sql auditSql = Sqls.create(""" + SELECT t.variable, t.finishTime + FROM wf_process_task t + INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId + WHERE ins.businessNo = @clubId + AND t.taskState = 20 + AND t.taskName <> 'startTask' + ORDER BY t.finishTime DESC + LIMIT 1 + """); + auditSql.setParam("clubId", clubId); + auditSql.setCallback(Sqls.callback.map()); + dao().execute(auditSql); + NutMap audit = (NutMap) auditSql.getResult(); + String schoolUnionOpinion = ""; + String schoolUnionAuditTime = ""; + if (ObjectUtil.isNotEmpty(audit)) { + String variable = audit.getString("variable"); + if (JSONUtil.isTypeJSON(variable)) { + cn.hutool.json.JSONObject data = JSONUtil.parseObj(variable); + schoolUnionOpinion = data.getStr("tf_opinion", data.getStr("tf_approvalComment", data.getStr("approvalOpinion", ""))); + } + if (audit.get("finishTime") != null) { + schoolUnionAuditTime = DateUtil.format((java.util.Date) audit.get("finishTime"), "yyyy年MM月dd日"); + } + } + + Map docData = new HashMap<>(); + docData.put("clubName", club.getString("clubName", "")); + docData.put("applyTime", formatDate(club.getString("createTime"))); + docData.put("applicantName", club.getString("applicantName", "")); + docData.put("applicantMobile", club.getString("applicantMobile", "")); + docData.put("applicantUnitName", club.getString("applicantUnitName", "")); + docData.put("introduce", toPlainText(club.getString("introduce", ""))); + docData.put("managementInfo", managementInfo.toString()); + docData.put("schoolUnionOpinion", schoolUnionOpinion); + docData.put("schoolUnionAuditTime", schoolUnionAuditTime); + + try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("clubRegisterApply"), Configure.builder().build()) + .render(docData).writeAndClose(output); + CommonDownloadUtil.download("教职工社团申请表(" + club.getString("clubName", "") + ").docx", output.toByteArray(), response); + } catch (IOException e) { + throw new BaseException("协会申请表导出失败", e); + } + } + + private String formatDate(String value) { + if (StrUtil.isBlank(value)) { + return ""; + } + return DateUtil.format(DateUtil.parse(value), "yyyy年MM月dd日"); + } + + private String toPlainText(String value) { + return StrUtil.blankToDefault(value, "").replaceAll("<[^>]*>", "").replace(" ", " "); + } + /** * 按固定模板代码下载协会模板,模板代码仅由服务内部指定,避免下载其他业务模板。 */ @@ -275,11 +392,8 @@ public class SysClubServiceImpl extends BaseServiceImpl implements SysC @Override public void validateRequiredFiles(SysClub club) { - // 文件上传组件提交空数组时,不能仅依赖 Bean Validation 的 @NotEmpty,需要在正式提交前显式校验。 - if (club == null || ObjectUtil.isEmpty(club.getEstablishReport())) { - throw new BaseException("请上传申请成立报告"); - } - if (ObjectUtil.isEmpty(club.getRulesFile())) { + // 申请成立报告为选填;章程草案仍需显式检查空附件列表,并保留申请信息为空时的保护。 + if (club == null || ObjectUtil.isEmpty(club.getRulesFile())) { throw new BaseException("请上传章程草案"); } } diff --git a/src/main/resources/views/platform/zhgh/club/register/apply/clubRegisterForm.js b/src/main/resources/views/platform/zhgh/club/register/apply/clubRegisterForm.js index 43bf568..5de0fd1 100644 --- a/src/main/resources/views/platform/zhgh/club/register/apply/clubRegisterForm.js +++ b/src/main/resources/views/platform/zhgh/club/register/apply/clubRegisterForm.js @@ -180,9 +180,7 @@ const CLUB_FORM_TEMPLATE = { clubType: [{ required: true, message: "请选择协会类型", trigger: ["blur", "change"] }], concatPerson: [{ required: true, message: "请选择协会联系人", trigger: ["blur", "change"] }], foundTime: [{ required: true, message: "请选择成立时间", trigger: ["blur", "change"] }], - establishReport: [{ required: true, message: "请上传申请成立报告", trigger: ["blur", "change"] }], rulesFile: [{ required: true, message: "请上传章程草案", trigger: ["blur", "change"] }] - // establishReport: [{ required: true, message: "请上传申请成立报告", trigger: ["blur", "change"] }] //rulesFile: [{ required: true, message: "请上传章程草案", trigger: ["blur", "change"] }], //manageFile: [{ required: true, message: "请上传经费来源及管理办法", trigger: ["blur", "change"] }], //yearPlanFile: [{ required: true, message: "请上传年度活动计划", trigger: ["blur", "change"] }] diff --git a/src/main/resources/views/platform/zhgh/club/register/apply/index.html b/src/main/resources/views/platform/zhgh/club/register/apply/index.html index 6465a25..fb63f55 100644 --- a/src/main/resources/views/platform/zhgh/club/register/apply/index.html +++ b/src/main/resources/views/platform/zhgh/club/register/apply/index.html @@ -62,17 +62,11 @@ layout("/layouts/platform.html"){ }, methods: { nextStep() { - let valid = true - this.$refs.clubFormRef.$refs.form.validateField( - ["clubName", "clubType", "foundTime", "establishReport", "rulesFile"], - (errMsg) => { - if (!errMsg) { - valid = false - } - } - ) - if (valid) return - this.activeName = 1 + this.$refs.clubFormRef.$refs.form.validate().then(() => { + this.activeName = 1 + }).catch(() => { + this.$message.warning({ title: "警告", message: "存在必填项未填写!" }) + }) }, async onSave() { let valid = true @@ -100,13 +94,9 @@ layout("/layouts/platform.html"){ this.$message.warning({ title: "警告", message: "存在必填项未填写!" }) }) }, - // 文件上传组件使用数组承载文件,提交前显式检查空数组,避免表单校验误判为已填写。 + // 申请成立报告为选填;章程草案仍需上传,提交前显式检查空数组,避免表单校验误判。 validateRequiredFiles() { const formData = this.$refs.clubFormRef.formData - if (!formData.establishReport || formData.establishReport.length === 0) { - this.$message.warning({ title: "警告", message: "请上传申请成立报告" }) - return false - } if (!formData.rulesFile || formData.rulesFile.length === 0) { this.$message.warning({ title: "警告", message: "请上传章程草案" }) return false diff --git a/src/main/resources/views/platform/zhgh/club/register/mine/index.html b/src/main/resources/views/platform/zhgh/club/register/mine/index.html index 5426a40..79954ca 100644 --- a/src/main/resources/views/platform/zhgh/club/register/mine/index.html +++ b/src/main/resources/views/platform/zhgh/club/register/mine/index.html @@ -56,6 +56,7 @@ layout("/layouts/platform.html"){