diff --git a/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineApplyController.java b/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineApplyController.java index 92197d3d..9cce435e 100644 --- a/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineApplyController.java +++ b/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineApplyController.java @@ -133,6 +133,9 @@ public class ClubExamineApplyController { .and("year", "=", year) .desc("year") ); + if (club == null) { + return Result.success(0f); + } Number number = ObjectUtil.defaultIfNull(club.getTotalQuota(), 0); return Result.success(number.floatValue()); } @@ -154,7 +157,6 @@ public class ClubExamineApplyController { } @At - @SaCheckPermission("club.examine") public Result info(String id) { if(StrUtil.isBlank(id)) { return Result.error("id信息为空,请核查"); diff --git a/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineSchoolLeaderAuditController.java b/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineSchoolLeaderAuditController.java index 8630a96c..3bfc9ddb 100644 --- a/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineSchoolLeaderAuditController.java +++ b/src/main/java/com/budwk/app/zhgh/club/controller/examine/ClubExamineSchoolLeaderAuditController.java @@ -1,17 +1,29 @@ package com.budwk.app.zhgh.club.controller.examine; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import com.budwk.app.base.utils.CommonDownloadUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.result.Result; import com.budwk.app.zhgh.club.param.ClubUserPageForm; import com.budwk.app.zhgh.club.service.SysClubExamineService; +import com.budwk.app.zhgh.club.vo.ClubExamineVo; import com.budwk.app.zhgh.club.vo.ClubExaminePageVo; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; +import org.apache.poi.ss.usermodel.Workbook; +import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; /** * @ClassName ClubExamineSchoolLeaderAuditController @@ -39,4 +51,49 @@ public class ClubExamineSchoolLeaderAuditController { Pagination pagination = sysClubExamineService.schoolLeaderAuditPageData(pageForm); return Result.success(pagination); } + + @At + @Ok("void") + @SaCheckPermission("club.examine.schoolLeaderAudit") + public void doExportPlan(String id, HttpServletResponse response) { + ClubExamineVo examineVo = sysClubExamineService.findOne(id); + if (Lang.isEmpty(examineVo)) { + return; + } + // 导出下一年度活动计划,字段顺序与查看页列表保持一致。 + List exportData = sysClubExamineService.getPlanExportData(id); + List entityList = new ArrayList<>(); + entityList.add(new ExcelExportEntity("活动主题/赛事名称", "activityName", 40)); + entityList.add(new ExcelExportEntity("活动/赛事主办单位", "activityUnit", 40)); + entityList.add(new ExcelExportEntity("活动地点", "activityAddress", 40)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, exportData); + CommonDownloadUtil.download(examineVo.getClubName() + "下一年度活动计划.xlsx", workbook, response); + } + + @At + @Ok("void") + @SaCheckPermission("club.examine.schoolLeaderAudit") + public void doExportActivity(String id, HttpServletResponse response) { + ClubExamineVo examineVo = sysClubExamineService.findOne(id); + if (Lang.isEmpty(examineVo)) { + return; + } + // 导出本年度活动开展情况,字段与年审填报表格列保持一致。 + List exportData = sysClubExamineService.getYearActivityExportData(id); + List entityList = new ArrayList<>(); + entityList.add(new ExcelExportEntity("活动时间", "activityTime", 20)); + entityList.add(new ExcelExportEntity("活动主题/赛事名称", "activityName", 40)); + entityList.add(new ExcelExportEntity("活动/赛事主办单位", "activityUnit", 40)); + entityList.add(new ExcelExportEntity("活动地点", "activityAddress", 40)); + entityList.add(new ExcelExportEntity("参加人数", "joinNum", 20)); + entityList.add(new ExcelExportEntity("获奖情况", "prize", 30)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, exportData); + CommonDownloadUtil.download(examineVo.getClubName() + "本年度活动开展情况.xlsx", workbook, response); + } } diff --git a/src/main/java/com/budwk/app/zhgh/club/service/SysClubExamineService.java b/src/main/java/com/budwk/app/zhgh/club/service/SysClubExamineService.java index adc8300c..5836c312 100644 --- a/src/main/java/com/budwk/app/zhgh/club/service/SysClubExamineService.java +++ b/src/main/java/com/budwk/app/zhgh/club/service/SysClubExamineService.java @@ -30,4 +30,20 @@ public interface SysClubExamineService extends BaseService schoolLeaderAuditPageData(@Valid ClubUserPageForm pageForm); ClubExamineVo findOne(@Valid String id); + + /** + * 查询本年度活动开展情况导出数据。 + * + * @param id 年审主键 + * @return 导出行数据 + */ + List getYearActivityExportData(@Valid String id); + + /** + * 查询下一年度活动计划导出数据。 + * + * @param id 年审主键 + * @return 导出行数据 + */ + List getPlanExportData(@Valid String id); } 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 044e7498..0811b055 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 @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.club.service.impl; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import com.budwk.app.base.constant.RoleConstant; @@ -308,7 +309,7 @@ public class SysClubExamineServiceImpl extends BaseServiceImpl getYearActivityExportData(String id) { + ClubExamineVo examineVo = this.findOne(id); + if (Lang.isEmpty(examineVo) || Lang.isEmpty(examineVo.getYearActivityList())) { + return new ArrayList<>(); + } + // 导出字段与前端表格字段保持一致,避免控制层再做字段转换。 + return examineVo.getYearActivityList().stream() + .map(item -> Dict.create() + .set("activityTime", item.getStr("activityTime")) + .set("activityName", item.getStr("activityName")) + .set("activityUnit", item.getStr("activityUnit")) + .set("activityAddress", item.getStr("activityAddress")) + .set("joinNum", item.getStr("joinNum")) + .set("prize", item.getStr("prize"))) + .map(NutMap::new) + .collect(Collectors.toList()); + } + + @Override + public List getPlanExportData(String id) { + ClubExamineVo examineVo = this.findOne(id); + if (Lang.isEmpty(examineVo) || Lang.isEmpty(examineVo.getPlans())) { + return new ArrayList<>(); + } + // 下年度活动计划导出只保留页面已有的三个业务字段。 + return examineVo.getPlans().stream() + .map(item -> Dict.create() + .set("activityName", item.getStr("activityName")) + .set("activityUnit", item.getStr("activityUnit")) + .set("activityAddress", item.getStr("activityAddress"))) + .map(NutMap::new) + .collect(Collectors.toList()); + } + /** * 生成审核分页通用SQL * @param pageForm 分页查询参数 diff --git a/src/main/resources/views/platform/zhgh/club/examine/apply/index.html b/src/main/resources/views/platform/zhgh/club/examine/apply/index.html index 830a2a6e..4dde0117 100644 --- a/src/main/resources/views/platform/zhgh/club/examine/apply/index.html +++ b/src/main/resources/views/platform/zhgh/club/examine/apply/index.html @@ -22,8 +22,9 @@ layout("/layouts/platform.html"){ width: 80px; } /* 财务明细表格高度 */ - .finance-table { + .finance-table >>> .el-table__body-wrapper { max-height: 600px; + overflow-y: auto !important; } /* 统计表格高度 */ .stat-table { @@ -725,7 +726,12 @@ layout("/layouts/platform.html"){ }, // 计算年度结余 calcSurplus(row) { - const total = (row.lastYearSurplus || 0) + (row.income || 0) + (row.allocate || 0) + (row.support || 0) - (row.totalExpend || 0); + const lastYearSurplusVal = this.lastYearSurplus !== null ? this.lastYearSurplus : (row.lastYearSurplus || 0); + const income = row.income || 0; + const allocate = row.allocate || 0; + const support = row.support || 0; + const totalExpend = row.totalExpend || 0; + const total = Number(lastYearSurplusVal) + Number(income) + Number(allocate) + Number(support) - Number(totalExpend); return this.formatNumber(total); }, // 表单校验通用方法 @@ -783,13 +789,43 @@ layout("/layouts/platform.html"){ this.formData = data; // 初始化财务数据 this.financeData.incomeCensus = data.incomeCensus || [{ lastYearSurplus: 0, income: 0, allocate: 0, support: 0, totalExpend: 0, surplus: 0 }]; - this.financeData.incomeDetailed = data.detailedList || []; + + // 从统计数据中提取去年年度结余 + if (this.financeData.incomeCensus && this.financeData.incomeCensus.length > 0) { + this.lastYearSurplus = this.financeData.incomeCensus[0].lastYearSurplus || 0; + } + + if (data.detailedList && data.detailedList.length > 0) { + this.financeData.incomeDetailed = this.sortIncomeDetailed(data.detailedList); + } else { + this.financeData.incomeDetailed = []; + } // 初始化成员数据 await this.fetchClubUserNum(data.clubId); await this.fetchMemberList(data.clubId); // 检查是否已登记 await this.checkIsRegistered(); }, + sortIncomeDetailed(list) { + const defaultContents = [new Date().getFullYear() - 1 + "年度结余", "会费收入", "校工会拨款"]; + const defaultItems = []; + const customItems = []; + + list.forEach(item => { + if (item.content && defaultContents.includes(item.content)) { + defaultItems.push(item); + } else { + customItems.push(item); + } + }); + + // 按默认顺序排列前三条 + const sortedDefaults = defaultContents.map(content => + defaultItems.find(item => item.content === content) + ).filter(item => item !== undefined); + + return [...sortedDefaults, ...customItems]; + }, // 获取社团成员数量 async fetchClubUserNum(clubId) { const resp = await this.$axios.post("/platform/club/examine/apply/getClubUserNum", { @@ -830,6 +866,11 @@ layout("/layouts/platform.html"){ year: this.formData.year }); this.lastYearSurplus = resp.data || 0; + + // 同步更新到统计表格 + if (this.financeData.incomeCensus && this.financeData.incomeCensus.length > 0) { + this.financeData.incomeCensus[0].lastYearSurplus = this.lastYearSurplus; + } }, // 获取上年度社团数据 async fetchLastClubData() { @@ -897,22 +938,25 @@ layout("/layouts/platform.html"){ }, // 删除财务明细项 deleteFinanceItem(row, index) { - // 扣除对应统计金额 - this.financeData.incomeCensus[0].income = (this.financeData.incomeCensus[0].income || 0) - (Number(row.income) || 0); - this.financeData.incomeCensus[0].support = (this.financeData.incomeCensus[0].support || 0) - (Number(row.income) || 0); - this.financeData.incomeCensus[0].totalExpend = (this.financeData.incomeCensus[0].totalExpend || 0) - (Number(row.expend) || 0); + // 根据收支类型扣除对应统计金额 + const income = Number(row.income) || 0; + const expend = Number(row.expend) || 0; + + if (row.incomeType === "会费收入") { + this.financeData.incomeCensus[0].income = (this.financeData.incomeCensus[0].income || 0) - income; + } else if (row.incomeType === "校工会拨款") { + this.financeData.incomeCensus[0].allocate = (this.financeData.incomeCensus[0].allocate || 0) - income; + } else if (row.incomeType === "社会赞助") { + this.financeData.incomeCensus[0].support = (this.financeData.incomeCensus[0].support || 0) - income; + } else if (row.incomeType === "支出") { + this.financeData.incomeCensus[0].totalExpend = (this.financeData.incomeCensus[0].totalExpend || 0) - expend; + } + // 删除明细项 this.financeData.incomeDetailed.splice(index, 1); - // 清空统计数据 - if (this.financeData.incomeDetailed.length === 0) { - this.financeData.incomeCensus = [{ - income: this.dueIncome, - allocate: this.unionAllocate, - support: 0, - totalExpend: 0, - surplus: 0 - }]; - } + + // 重新计算统计数据,确保准确性 + this.recalculateCensus(); }, // 收支类型变化处理 handleIncomeTypeChange(row) { @@ -933,27 +977,31 @@ layout("/layouts/platform.html"){ // 年初余额输入处理 handleQcMoneyInput(row) { this.lastYearSurplus = Number(row.qcMoney) || 0; + // 同步更新到统计表格 + if (this.financeData.incomeCensus && this.financeData.incomeCensus.length > 0) { + this.financeData.incomeCensus[0].lastYearSurplus = this.lastYearSurplus; + } + // 更新后强制重新计算统计数据 + this.$forceUpdate(); }, // 收入输入处理 handleIncomeInput(row) { - // 计算总收入 - let totalIncome = 0; - this.financeData.incomeDetailed.forEach(item => { - totalIncome += Number(item.income) || 0; - }); - this.financeData.incomeCensus[0].income = totalIncome; // 按类型更新对应统计 - if (row.incomeType === "社会赞助") this.calcSupportTotal(); - if (row.incomeType === "校工会拨款") this.calcAllocateTotal(); - if (row.incomeType === "会费收入") this.calcDueIncomeTotal(); + if (row.incomeType === "社会赞助") { + this.calcSupportTotal(); + } else if (row.incomeType === "校工会拨款") { + this.calcAllocateTotal(); + } else if (row.incomeType === "会费收入") { + this.calcDueIncomeTotal(); + } + // 重新计算所有统计数据,确保一致性 + this.recalculateCensus(); }, // 支出输入处理 handleExpendInput: function() { - let totalExpend = 0; - this.financeData.incomeDetailed.forEach(item => { - totalExpend += Number(item.expend) || 0; - }); - this.financeData.incomeCensus[0].totalExpend = totalExpend; + this.calcExpendTotal(); + // 重新计算所有统计数据,确保一致性 + this.recalculateCensus(); }, // 计算校工会拨款合计 calcAllocateTotal() { @@ -984,6 +1032,43 @@ layout("/layouts/platform.html"){ .reduce((sum, item) => sum + (Number(item.expend) || 0), 0); this.financeData.incomeCensus[0].totalExpend = total; }, + // 重新计算所有统计数据 + recalculateCensus() { + // 计算会费收入总额 + const dueIncomeTotal = this.financeData.incomeDetailed + .filter(item => item.incomeType === "会费收入") + .reduce((sum, item) => sum + (Number(item.income) || 0), 0); + + // 计算校工会拨款总额 + const allocateTotal = this.financeData.incomeDetailed + .filter(item => item.incomeType === "校工会拨款") + .reduce((sum, item) => sum + (Number(item.income) || 0), 0); + + // 计算社会赞助总额 + const supportTotal = this.financeData.incomeDetailed + .filter(item => item.incomeType === "社会赞助") + .reduce((sum, item) => sum + (Number(item.income) || 0), 0); + + // 计算总支出 + const totalExpend = this.financeData.incomeDetailed + .filter(item => item.incomeType === "支出") + .reduce((sum, item) => sum + (Number(item.expend) || 0), 0); + + // 更新统计数据 + this.financeData.incomeCensus[0].income = dueIncomeTotal; + this.financeData.incomeCensus[0].allocate = allocateTotal; + this.financeData.incomeCensus[0].support = supportTotal; + this.financeData.incomeCensus[0].totalExpend = totalExpend; + // 确保去年年度结余不丢失 + this.financeData.incomeCensus[0].lastYearSurplus = this.lastYearSurplus; + + // 同步更新全局变量 + this.dueIncome = dueIncomeTotal; + this.unionAllocate = allocateTotal; + + // 强制更新视图,确保年度结余重新计算 + this.$forceUpdate(); + }, /************************ 事件处理方法 ************************/ // 年度变化处理 diff --git a/src/main/resources/views/platform/zhgh/club/examine/clubAudit/index.html b/src/main/resources/views/platform/zhgh/club/examine/clubAudit/index.html index ace4da06..d05c82be 100644 --- a/src/main/resources/views/platform/zhgh/club/examine/clubAudit/index.html +++ b/src/main/resources/views/platform/zhgh/club/examine/clubAudit/index.html @@ -73,6 +73,10 @@ layout("/layouts/platform.html"){ :rules="[{required:true,message:'必填',trigger:['change','blur']}]"> + + + 取消 @@ -124,22 +128,27 @@ layout("/layouts/platform.html"){ }) }, handleTaskAction(val) { - this.$confirm("您确定要提交吗?", "提示", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning" - }).then(() => { - this.$axios.post("/flow/common/executeTask", { - data: JSON.stringify({ - ...this.formData, - submitType: val + this.$refs.formRef.validate((valid) => { + if (!valid) { + return + } + this.$confirm("您确定要提交吗?", "提示", { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning" + }).then(() => { + this.$axios.post("/flow/common/executeTask", { + data: JSON.stringify({ + ...this.formData, + submitType: val + }) + }).then((res) => { + if (res.code === 0) { + this.$refs.guava.index() + this.$message.success(res.msg) + this.doSearch() + } }) - }).then((res) => { - if (res.code === 0) { - this.$refs.guava.index() - this.$message.success(res.msg) - this.doSearch() - } }) }) }, diff --git a/src/main/resources/views/platform/zhgh/club/examine/schoolLeaderAudit/index.html b/src/main/resources/views/platform/zhgh/club/examine/schoolLeaderAudit/index.html index ea71bcbd..695c3062 100644 --- a/src/main/resources/views/platform/zhgh/club/examine/schoolLeaderAudit/index.html +++ b/src/main/resources/views/platform/zhgh/club/examine/schoolLeaderAudit/index.html @@ -50,11 +50,13 @@ layout("/layouts/platform.html"){ - + @@ -73,6 +75,10 @@ layout("/layouts/platform.html"){ :rules="[{required:true,message:'必填',trigger:['change','blur']}]"> + + + 取消 @@ -124,22 +130,27 @@ layout("/layouts/platform.html"){ }) }, handleTaskAction(val) { - this.$confirm("您确定要提交吗?", "提示", { - confirmButtonText: "确定", - cancelButtonText: "取消", - type: "warning" - }).then(() => { - this.$axios.post("/flow/common/executeTask", { - data: JSON.stringify({ - ...this.formData, - submitType: val + this.$refs.formRef.validate((valid) => { + if (!valid) { + return + } + this.$confirm("您确定要提交吗?", "提示", { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning" + }).then(() => { + this.$axios.post("/flow/common/executeTask", { + data: JSON.stringify({ + ...this.formData, + submitType: val + }) + }).then((res) => { + if (res.code === 0) { + this.$refs.guava.index() + this.$message.success(res.msg) + this.doSearch() + } }) - }).then((res) => { - if (res.code === 0) { - this.$refs.guava.index() - this.$message.success(res.msg) - this.doSearch() - } }) }) }, @@ -157,6 +168,12 @@ layout("/layouts/platform.html"){ }) }) }, + doExportPlan(row) { + this.$downLoad("/platform/club/examine/schoolLeaderAudit/doExportPlan", { id: row.id }) + }, + doExportActivity(row) { + this.$downLoad("/platform/club/examine/schoolLeaderAudit/doExportActivity", { id: row.id }) + }, async pageData() { let form = clone(this.pageForm) if (form.isAudit === null) {