diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index cb1a291..f807d2f 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -1,6 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -27,4 +42,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9ae45b6..ec149a9 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,6 @@
-
-
\ No newline at end of file
+
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareListController.java b/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareListController.java
index 635be84..fbc4a58 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareListController.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareListController.java
@@ -165,6 +165,60 @@ public class WelfareListController {
welfareListService.exportXlsx(pageForm, response);
}
+ /**
+ * 导出指定福利项目和套餐的报销表。
+ *
+ * @param projectId 福利项目 ID
+ * @param optionId 福利套餐 ID,必须属于 projectId 对应项目
+ * @param response XLSX 文件下载响应
+ */
+ @At
+ @Ok("void")
+ @SaCheckPermission("welfare.list.mange")
+ @ApiOperation("导出福利报销表")
+ public void doExcelByOptionId(@Param("projectId") String projectId,
+ @Param("optionId") String optionId,
+ HttpServletResponse response) {
+ welfareListService.doExcelByOptionId(projectId, optionId, response);
+ }
+
+ /**
+ * 导出供货商使用的套餐选择数据,按套餐拆分工作表。
+ *
+ * @param projectId 福利项目 ID
+ * @param unionId 可选的分工会 ID;为空时按当前用户的数据权限导出
+ * @param response XLSX 文件下载响应
+ */
+ @At
+ @Ok("void")
+ @SaCheckPermission("welfare.list.mange")
+ @ApiOperation("导出供货商选择数据")
+ public void exportSelectData(@Param("projectId") String projectId,
+ @Param("unionId") String unionId,
+ HttpServletResponse response) {
+ welfareListService.exportSelectData(projectId, unionId, response);
+ }
+
+ /**
+ * 导入供应商提供的快递单号文件。
+ *
+ * @param file XLS 或 XLSX 文件,包含工号与最多四个快递单号列
+ * @param projectId 福利项目 ID
+ * @param optionId 福利套餐 ID,必须属于 projectId 对应项目
+ * @return 导入结果;成功时返回成功提示,失败时返回具体原因
+ */
+ @At
+ @Aop(TransAop.READ_COMMITTED)
+ @SaCheckPermission("welfare.list.mange")
+ @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
+ @SLog(tag = "福利名单管理", msg = "导入福利快递单号")
+ @ApiOperation("导入福利快递单号")
+ public Result importCourierNumber(@Param("file") TempFile file,
+ @Param("projectId") String projectId,
+ @Param("optionId") String optionId) {
+ return welfareListService.importCourierNumber(file, projectId, optionId);
+ }
+
@At
@SaCheckPermission("welfare.list.mange")
@ApiOperation("编辑备注")
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareStatisticsController.java b/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareStatisticsController.java
index 56218a0..994edf0 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareStatisticsController.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/controller/WelfareStatisticsController.java
@@ -110,8 +110,8 @@ public class WelfareStatisticsController {
@Ok("void")
@SaCheckPermission("welfare.statistics")
@ApiOperation("按福利选项导出")
- public void exportByWelfareOptions(String projectId, HttpServletResponse response) {
- welfareStatisticsService.exportByWelfareOptions(projectId, response);
+ public void exportByWelfareOptions(String projectId, String unionId, HttpServletResponse response) {
+ welfareStatisticsService.exportByWelfareOptions(projectId, unionId, response);
}
@At
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/mode/WelfareExportEntityTc.java b/src/main/java/com/budwk/app/zhgh/welfare/mode/WelfareExportEntityTc.java
index 500108f..de86840 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/mode/WelfareExportEntityTc.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/mode/WelfareExportEntityTc.java
@@ -30,9 +30,19 @@ public class WelfareExportEntityTc {
@Excel(name = "已选福利", width = 80d)
private String optionName;
- @Excel(name = "收货信息", width = 100d)
+ // V4 原“收货信息”导出列保留字段,现按 V3 规则拆分为收货人、联系方式和收货地址。
+// @Excel(name = "收货信息", width = 100d)
private String receiveAddress;
+ @Excel(name = "收货人", width = 15d)
+ private String recipient;
+
+ @Excel(name = "联系方式", width = 20d)
+ private String phone;
+
+ @Excel(name = "收货地址", width = 60d)
+ private String address;
+
@Excel(name = "快递单号", width = 40d)
private String courierNumber;
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/param/WelfareSelectionSituationPageForm.java b/src/main/java/com/budwk/app/zhgh/welfare/param/WelfareSelectionSituationPageForm.java
index 6d17fbd..756891d 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/param/WelfareSelectionSituationPageForm.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/param/WelfareSelectionSituationPageForm.java
@@ -37,4 +37,10 @@ public class WelfareSelectionSituationPageForm extends PageForm {
@ApiModelProperty("人员属性")
private String userAttribute;
+
+ @ApiModelProperty("人员类型")
+ private String[] personTypes;
+
+ @ApiModelProperty("在职状态")
+ private String[] userStates;
}
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareListService.java b/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareListService.java
index 04eb36b..5f710c5 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareListService.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareListService.java
@@ -13,10 +13,32 @@ import javax.servlet.http.HttpServletResponse;
public interface WelfareListService extends BaseService {
+ /**
+ * 导出一个福利项目下指定套餐的报销表。
+ *
+ * @param projectId 福利项目 ID
+ * @param optionId 福利套餐 ID,必须属于指定福利项目
+ * @param response XLSX 文件下载响应
+ */
void doExcelByOptionId(String projectId, String optionId, HttpServletResponse response);
+ /**
+ * 导出供应商所需的选择数据,并按套餐创建工作表。
+ *
+ * @param projectId 福利项目 ID
+ * @param unionId 可选的分工会 ID;为空时按当前登录人的数据范围导出
+ * @param response XLSX 文件下载响应
+ */
void exportSelectData(String projectId, String unionId, HttpServletResponse response);
+ /**
+ * 导入指定福利项目、套餐下的快递单号。
+ *
+ * @param file XLS 或 XLSX 文件,列为工号、姓名和最多四个快递单号
+ * @param projectId 福利项目 ID
+ * @param optionId 福利套餐 ID,必须属于指定福利项目
+ * @return 成功或失败的导入结果
+ */
Result importCourierNumber(TempFile file, String projectId, String optionId);
void doEditWelfareData(String editWelfareData, String welfareOptions);
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareStatisticsService.java b/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareStatisticsService.java
index 1217d76..59d3070 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareStatisticsService.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/WelfareStatisticsService.java
@@ -62,7 +62,7 @@ public interface WelfareStatisticsService extends BaseService {
* @param projectId
* @param response
*/
- void exportByWelfareOptions(String projectId, HttpServletResponse response);
+ void exportByWelfareOptions(String projectId, String unionId, HttpServletResponse response);
/**
* 导出汇总表
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareListServiceImpl.java b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareListServiceImpl.java
index 0d06541..03a4aa5 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareListServiceImpl.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareListServiceImpl.java
@@ -61,8 +61,17 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
@Override
public void doExcelByOptionId(String projectId, String optionId, HttpServletResponse response) {
+ if (StrUtil.isBlank(projectId) || StrUtil.isBlank(optionId)) {
+ log.warn("导出报销表失败:福利项目或套餐不能为空");
+ return;
+ }
WelfareProject project = dao().fetch(WelfareProject.class, projectId);
- WelfareProjectSubjectOption subjectOption = dao().fetch(WelfareProjectSubjectOption.class, optionId);
+ WelfareProjectSubjectOption subjectOption = dao().fetch(WelfareProjectSubjectOption.class,
+ Cnd.where("id", "=", optionId).and("welfareId", "=", projectId));
+ if (project == null || subjectOption == null) {
+ log.warn("导出报销表失败:福利项目或套餐不存在,projectId={}, optionId={}", projectId, optionId);
+ return;
+ }
Sql sql = Sqls.create("""
SELECT
@@ -75,30 +84,35 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
wpus.selectNum
FROM
welfare_project_user_selection wpus
- LEFT JOIN `welfare_list` wl ON wpus.selectUserId = wl.userId
+ INNER JOIN `welfare_list` wl ON wl.userId = wpus.selectUserId
+ AND wl.projectId = wpus.welfareId
LEFT JOIN `sys_user` u ON u.id = wl.userId
- LEFT JOIN sys_union un ON un.id = wl.welfareUnitId
- LEFT JOIN sys_unit it ON it.id = wl.welfareSecondLevelUnitId
+ LEFT JOIN sys_union un ON un.id = wl.welfareUnionId
+ LEFT JOIN sys_unit it ON it.id = wl.welfareUnitId
WHERE
- wl.projectId = @welfareId
- AND wpus.selectOptionId = @selectOptionId and wpus.selectNum!=0
-
+ wpus.welfareId = @welfareId
+ AND wpus.selectOptionId = @selectOptionId
+ AND IFNULL(wpus.selectNum, 0) <> 0
+ ORDER BY wl.welfareUnionName, wl.welfareUnitName, u.loginname
""").setParam("welfareId", projectId).setParam("selectOptionId", optionId);
List mapList = listMap(sql);
List userId = mapList.stream().map(m -> m.getString("id")).collect(Collectors.toList());
- List courierNumberList = dao().query(WelfareCourierNumber.class,
+ List courierNumberList = userId.isEmpty()
+ ? Collections.emptyList()
+ : dao().query(WelfareCourierNumber.class,
Cnd.where("selectUserId", "in", userId)
.and("welfareId", "=", projectId)
- .and("selectOptionId", "=", optionId));
+ .and("selectOptionId", "=", optionId)
+ .asc("createdAt"));
List nameList = List.of("one", "two", "three", "four");
for (NutMap map : mapList) {
List userCourierNumbers = courierNumberList.stream()
.filter(c -> c.getSelectUserId().equals(map.getString("id"))).collect(Collectors.toList());
- for (int i = 0; i < userCourierNumbers.size(); i++) {
+ for (int i = 0; i < userCourierNumbers.size() && i < nameList.size(); i++) {
map.setv(nameList.get(i) + "CourierNumber", userCourierNumbers.get(i).getCourierNumber());
}
}
@@ -138,14 +152,13 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
exportParams.setSheetName(un);
service.createSheetForMap(workbook, exportParams, exportEntities, v);
}*/
- try {
- ExportParams exportParams = new ExportParams();
- exportParams.setType(ExcelType.XSSF);
- exportParams.setTitle(project.getName() + subjectOption.getOptionName() + "发放名单");
- Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, mapList);
+ ExportParams exportParams = new ExportParams();
+ exportParams.setType(ExcelType.XSSF);
+ exportParams.setTitle(project.getName() + subjectOption.getOptionName() + "报销表");
+ try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, mapList)) {
CommonDownloadUtil.download(project.getName() + subjectOption.getOptionName() + ".xlsx", workbook, response);
} catch (Exception e) {
- e.printStackTrace();
+ log.error("导出报销表失败,projectId={}, optionId={}", projectId, optionId, e);
}
}
@@ -153,6 +166,10 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
@Override
public void exportSelectData(String projectId, String unionId, HttpServletResponse response) {
WelfareProject welfareProject = dao().fetch(WelfareProject.class, Cnd.where("id", "=", projectId));
+ if (welfareProject == null) {
+ log.warn("导出供货商选择数据失败:福利项目不存在,projectId={}", projectId);
+ return;
+ }
String projectName = welfareProject.getName();
Cnd cnd = Cnd.NEW();
Sql sql = Sqls.create("""
@@ -170,16 +187,18 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
left join `sys_user` u on u.id = wpus.selectUserId
left join welfare_project_subject_option wpso on wpso.id = wpus.selectOptionId
left join welfare_list wl on wl.userId = wpus.selectUserId and wl.projectId=wpus.welfareId
- LEFT JOIN sys_union un ON un.id = wl.welfareUnitId
- LEFT JOIN sys_unit it ON it.id = wl.welfareSecondLevelUnitId
+ LEFT JOIN sys_union un ON un.id = wl.welfareUnionId
+ LEFT JOIN sys_unit it ON it.id = wl.welfareUnitId
$condition
""");
cnd.and("wpus.welfareId", "=", projectId);
- if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_WELFARE_ADMIN.name())) {
- cnd.and("wl.welfareUnitId", "=", SecurityUtil.getUnionId());
+ if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())
+ || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ADMIN.name())
+ || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WENTI_SPORTS.name())) {
+ cnd.and("wl.welfareUnionId", "=", SecurityUtil.getUnionId());
}
- cnd.andEX("wl.welfareUnitId", "=", unionId);
+ cnd.andEX("wl.welfareUnionId", "=", unionId);
cnd.groupBy("wpus.selectUserId", "wpus.selectOptionId");
cnd.asc("it.unitcode");
sql.setCondition(cnd);
@@ -207,12 +226,21 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
try {
CommonDownloadUtil.download(projectName + ".xlsx", workbook, response);
} catch (Exception e) {
- e.printStackTrace();
+ log.error("导出供货商选择数据失败,projectId={}", projectId, e);
}
}
@Override
+ @Aop(TransAop.READ_COMMITTED)
public Result importCourierNumber(TempFile file, String projectId, String optionId) {
+ if (StrUtil.isBlank(projectId) || StrUtil.isBlank(optionId)) {
+ return Result.error("福利项目和套餐不能为空");
+ }
+ WelfareProjectSubjectOption subjectOption = dao().fetch(WelfareProjectSubjectOption.class,
+ Cnd.where("id", "=", optionId).and("welfareId", "=", projectId));
+ if (subjectOption == null) {
+ return Result.error("福利套餐不存在或不属于当前福利项目");
+ }
if (Lang.isEmpty(file)) {
return Result.error("上传的文件不能为空");
}
@@ -226,7 +254,7 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
ImportParams importParams = new ImportParams();
excelList = ExcelImportUtil.importExcel(file.getFile(), CourierNumberExcelMode.class, importParams);
} catch (Exception e) {
- e.printStackTrace();
+ log.warn("读取快递单号导入文件失败", e);
return Result.error("读取不到数据,请检查excel文件格式");
}
@@ -236,7 +264,7 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
try {
if (excelList.stream().anyMatch(v -> StrUtil.isBlank(v.getLoginName()))) {
- return Result.error("工号和快递单号不能为空");
+ return Result.error("工号不能为空");
}
List filterExcelList = excelList.stream().collect(Collectors.collectingAndThen(
@@ -249,6 +277,9 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
Sql loginNameSql = Sqls.create("select id,loginname from sys_user where loginname in (@loginNameList)");
loginNameSql.setParam("loginNameList", loginNameList);
List loginNameMaps = listMap(loginNameSql);
+ if (loginNameMaps.isEmpty()) {
+ return Result.error("Excel中的工号均未匹配到系统用户");
+ }
List userIds = loginNameMaps.stream().map(v -> v.getString("id")).collect(Collectors.toList());
@@ -291,12 +322,13 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
welfareCourierNumbers.add(courierNumber);
}
}
- insert(welfareCourierNumbers);
+ if (!welfareCourierNumbers.isEmpty()) {
+ insert(welfareCourierNumbers);
+ }
return Result.success("导入成功");
} catch (Exception e) {
-
- e.printStackTrace();
+ log.error("导入快递单号失败,projectId={}, optionId={}", projectId, optionId, e);
return Result.error("导入快递单号失败");
}
@@ -685,12 +717,10 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
t2.loginname,
t2.username,
t2.sex,
- DATE_FORMAT(t2.birthday, '%Y-%m-%d') AS birthday,
- threeUnit.name AS threeUnitName
+ DATE_FORMAT(t2.birthday, '%Y-%m-%d') AS birthday
FROM
`welfare_list` t1
LEFT JOIN sys_user t2 ON t2.id = t1.userId
- LEFT JOIN sys_unit threeUnit ON threeUnit.id = t2.threeUnitId
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -735,7 +765,6 @@ public class WelfareListServiceImpl extends BaseServiceImpl impleme
entities.add(new ExcelExportEntity("在职状态", "userState", 20));
entities.add(new ExcelExportEntity("所属工会", "welfareUnionName", 20));
entities.add(new ExcelExportEntity("所属单位", "welfareUnitName", 20));
- entities.add(new ExcelExportEntity("三级单位", "threeUnitName", 20));
entities.add(new ExcelExportEntity("备注", "remark", 20));
// 设置导出参数
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSelectionSituationServiceImpl.java b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSelectionSituationServiceImpl.java
index 6ca8f31..419d599 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSelectionSituationServiceImpl.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSelectionSituationServiceImpl.java
@@ -169,6 +169,8 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl> safeList = list.stream().map(nutMap -> {
- Map map = new HashMap<>(nutMap);
- return map;
- }).toList();
-
- // 分组
- Map>> listMap = safeList.stream()
- .collect(Collectors.groupingBy(n -> (String) n.get("welfareUnionName")));
+ // 保留 NutMap 数据结构,避免 EasyPOI 在 Java 17 下反射普通 HashMap 导致工作表创建失败。
+ Map> listMap = list.stream()
+ .collect(Collectors.groupingBy(n -> n.getString("welfareUnionName")));
// 构建 Excel 列
List entities = new ArrayList<>();
@@ -342,16 +349,16 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl {
ExcelExportService service = new ExcelExportService();
ExportParams exportParams = new ExportParams();
exportParams.setSheetName(k);
- exportParams.setType(ExcelType.HSSF);
+ exportParams.setType(ExcelType.XSSF);
service.createSheetForMap(workbook, exportParams, entities, v);
});
- CommonDownloadUtil.download("领取表.xls", workbook, response);
+ CommonDownloadUtil.download("领取表.xlsx", workbook, response);
}
/**
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java
index 512a8db..c1af776 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java
@@ -4,11 +4,14 @@ import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
+import cn.afterturn.easypoi.excel.export.ExcelExportService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.utils.CommonDownloadUtil;
+import com.budwk.app.sys.models.Sys_file;
+import com.budwk.app.sys.utils.SysFileMinIoUtil;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.welfare.mode.WelfareExportEntityTc;
@@ -31,9 +34,7 @@ import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -159,9 +160,10 @@ public class WelfareSingleServiceImpl extends BaseServiceImpl implements Welfare
u.unitname AS unitName,
u.unionname AS unionName,
u.mobile,
- IF(LOCATE('undefined',wpus.receiveAddress)>0,NULL,wpus.receiveAddress) as receiveAddress,
- GROUP_CONCAT(DISTINCT wpso.optionName ,'(',wpus.selectNum,'份)') optionName,
- wpus.courierNumber
+ IF(LOCATE('undefined',wpus.receiveAddress)>0,NULL,wpus.receiveAddress) as receiveAddress,
+ GROUP_CONCAT(DISTINCT wpso.optionName ,'(',wpus.selectNum,'份)') optionName,
+ wpus.courierNumber,
+ MAX(wpus.userSign) userSign
FROM
welfare_project_user_selection wpus
LEFT JOIN `vw_user` u ON u.id = wpus.selectUserId
@@ -183,6 +185,8 @@ public class WelfareSingleServiceImpl extends BaseServiceImpl implements Welfare
@Override
public Workbook exportReceiveDetail(String projectId, String unionId) {
+ // V4 原横向套餐签领表逻辑保留,当前按 V3 的“每个套餐一个工作表”格式执行。
+ if (false) {
Sql optionSql = Sqls.create("""
SELECT w2.id, w2.optionName
@@ -282,9 +286,148 @@ public class WelfareSingleServiceImpl extends BaseServiceImpl implements Welfare
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, dataList);
return workbook;
+ }
+ return exportReceiveDetailV3(projectId, unionId);
}
+ /**
+ * 生成参考项目格式的分工会福利签领表:一个工作表展示人员、套餐份数和签字,并在末行汇总套餐份数。
+ *
+ * @param projectId 福利项目ID
+ * @param unionId 分工会ID
+ * @return XLSX工作簿
+ */
+ private Workbook exportReceiveDetailV3(String projectId, String unionId) {
+ Sql optionSql = Sqls.create("""
+ SELECT id, optionName
+ FROM welfare_project_subject_option
+ WHERE welfareId = @projectId
+ ORDER BY optionSort, id
+ """);
+ optionSql.setParam("projectId", projectId);
+ List options = listMap(optionSql);
+
+ Sql sql = Sqls.create("""
+ SELECT
+ wl.userId,
+ u.username AS userName,
+ u.loginname AS loginName,
+ wl.welfareUnitName AS unitName,
+ wpus.userSign,
+ wpus.selectOptionId,
+ wpus.selectNum
+ FROM welfare_list wl
+ LEFT JOIN sys_user u ON u.id = wl.userId
+ LEFT JOIN welfare_project_user_selection wpus ON wpus.selectUserId = wl.userId
+ AND wpus.welfareId = wl.projectId
+ WHERE wl.projectId = @projectId AND wl.welfareUnionId = @unionId
+ ORDER BY wl.welfareUnitName, u.loginname, wpus.selectOptionId
+ """);
+ sql.setParam("projectId", projectId);
+ sql.setParam("unionId", unionId);
+ List rows = listMap(sql);
+ rows.forEach(this::fillUserSign);
+
+ Map> userRows = rows.stream().collect(Collectors.groupingBy(
+ row -> row.getString("userId"), LinkedHashMap::new, Collectors.toList()));
+ List exportRows = new ArrayList<>();
+ int index = 1;
+ for (List selectedRows : userRows.values()) {
+ NutMap userRow = selectedRows.get(0);
+ NutMap exportRow = NutMap.NEW();
+ exportRow.put("no", index++);
+ exportRow.put("userName", userRow.getString("userName"));
+ exportRow.put("loginName", userRow.getString("loginName"));
+ exportRow.put("unitName", userRow.getString("unitName"));
+ exportRow.put("qzBytes", selectedRows.stream()
+ .map(row -> row.get("qzBytes"))
+ .filter(Objects::nonNull)
+ .findFirst()
+ .orElse(null));
+ for (NutMap option : options) {
+ int selectNum = selectedRows.stream()
+ .filter(row -> option.getString("id").equals(row.getString("selectOptionId")))
+ .mapToInt(row -> row.getInt("selectNum", 0))
+ .sum();
+ exportRow.put(option.getString("id"), selectNum);
+ }
+ exportRows.add(exportRow);
+ }
+
+ NutMap totalRow = NutMap.NEW();
+ totalRow.put("no", "合计");
+ for (NutMap option : options) {
+ int total = rows.stream()
+ .filter(row -> option.getString("id").equals(row.getString("selectOptionId")))
+ .mapToInt(row -> row.getInt("selectNum", 0))
+ .sum();
+ totalRow.put(option.getString("id"), total);
+ }
+ exportRows.add(totalRow);
+
+ List entities = new ArrayList<>();
+ entities.add(new ExcelExportEntity("序号", "no", 10));
+ entities.add(new ExcelExportEntity("姓名", "userName", 15));
+ entities.add(new ExcelExportEntity("工号", "loginName", 18));
+ ExcelExportEntity unitEntity = new ExcelExportEntity("所在单位", "unitName", 25);
+ unitEntity.setWrap(true);
+ entities.add(unitEntity);
+ for (NutMap option : options) {
+ entities.add(new ExcelExportEntity(option.getString("optionName"), option.getString("id"), 12));
+ }
+ ExcelExportEntity signEntity = new ExcelExportEntity("签字", "qzBytes", 20);
+ signEntity.setType(2);
+ signEntity.setExportImageType(2);
+ entities.add(signEntity);
+
+ ExportParams exportParams = new ExportParams();
+ exportParams.setType(ExcelType.XSSF);
+ return ExcelExportUtil.exportExcel(exportParams, entities, exportRows);
+ }
+
+ /** 从 V4 文件存储读取签名图片,历史文件缺失时保留空白签字格。 */
+ private void fillUserSign(NutMap row) {
+ String userSign = row.getString("userSign");
+ if (StrUtil.isBlank(userSign)) {
+ return;
+ }
+ try {
+ Sys_file file = dao().fetch(Sys_file.class, Cnd.where(Sys_file::getDownloadPath, "=", userSign));
+ if (file != null) {
+ row.put("qzBytes", SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath()));
+ }
+ } catch (Exception ignored) {
+ // 单个签名文件异常不能影响整份签领表导出。
+ }
+ }
+
+ /** 身份证仅显示前段信息,保持 V3 签领表的脱敏规则。 */
+ private String maskIdCard(String idCard) {
+ if (StrUtil.isBlank(idCard) || idCard.length() <= 4) {
+ return idCard;
+ }
+ return idCard.substring(0, idCard.length() - 4) + "****";
+ }
+
+ /** 将历史收货信息拆为 V3 名单所需的收货人、联系方式和收货地址字段。 */
+ private void fillV3ReceiveAddress(NutMap row) {
+ String receiveAddress = row.getString("receiveAddress");
+ if (StrUtil.isBlank(receiveAddress)) {
+ return;
+ }
+ Map values = new HashMap<>();
+ for (String pair : receiveAddress.split("[,,]")) {
+ String[] keyValue = pair.split("[::]", 2);
+ if (keyValue.length == 2) {
+ values.put(keyValue[0].trim(), keyValue[1].trim());
+ }
+ }
+ row.put("recipient", values.get("收件人"));
+ row.put("phone", values.get("联系方式"));
+ row.put("address", values.get("收货地址"));
+ }
+
@Override
public Object unclaimedData(String projectId, String unionId, Integer pageNumber, Integer pageSize) {
@@ -333,6 +476,7 @@ public class WelfareSingleServiceImpl extends BaseServiceImpl implements Welfare
}
List list2 = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionName"))).collect(Collectors.toList());
+ list2.forEach(this::fillV3ReceiveAddress);
List welfareExportEntityTcList = list2.stream()
.map(map -> JSONUtil.toBean(Json.toJson(map), WelfareExportEntityTc.class))
@@ -340,15 +484,15 @@ public class WelfareSingleServiceImpl extends BaseServiceImpl implements Welfare
welfareExportEntityTcList.forEach(v -> {
if (StrUtil.isNotBlank(v.getUserSign())) {
- ByteArrayOutputStream signOs = new ByteArrayOutputStream();
-// ftpService.download(v.getUserSign(), signOs);
- byte[] imageBytes = signOs.toByteArray();
- if (Lang.isNotEmpty(imageBytes)) {
- v.setQzBytes(imageBytes);
- } else {
- v.setQzBytes(null);
+ try {
+ Sys_file file = dao().fetch(Sys_file.class,
+ Cnd.where(Sys_file::getDownloadPath, "=", v.getUserSign()));
+ if (file != null) {
+ v.setQzBytes(SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath()));
+ }
+ } catch (Exception ignored) {
+ // 签名文件缺失时保留空白,不中断名单导出。
}
-
}
});
ExportParams exportParams = new ExportParams();
diff --git a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareStatisticsServiceImpl.java
index 476f5a8..925f7be 100644
--- a/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareStatisticsServiceImpl.java
+++ b/src/main/java/com/budwk/app/zhgh/welfare/service/impl/WelfareStatisticsServiceImpl.java
@@ -17,6 +17,7 @@ import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.welfare.model.WelfareProject;
import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
+import com.budwk.app.zhgh.welfare.service.WelfareSingleService;
import com.budwk.app.zhgh.welfare.service.WelfareStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
@@ -32,14 +33,15 @@ import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
import java.util.stream.Collectors;
@IocBean(args = {"refer:dao"})
@Slf4j
public class WelfareStatisticsServiceImpl extends BaseServiceImpl implements WelfareStatisticsService {
+ @org.nutz.ioc.loader.annotation.Inject
+ private WelfareSingleService welfareSingleService;
+
public WelfareStatisticsServiceImpl(Dao dao) {
super(dao);
}
@@ -65,7 +67,7 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl welfareOptions = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
+ List welfareOptions = getNaturalSortedOptions(projectId);
for (WelfareProjectSubjectOption welfareOption : welfareOptions) {
dynamicTableColumns.add(NutMap.NEW().addv("label", welfareOption.getOptionName()).addv("prop", welfareOption.getId()));
@@ -176,6 +178,8 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl exportEntities = new ArrayList<>();
@@ -434,6 +448,8 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl welfareOptions = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
+ List welfareOptions = getNaturalSortedOptions(projectId);
for (WelfareProjectSubjectOption welfareOption : welfareOptions) {
ExcelExportEntity entity = new ExcelExportEntity(welfareOption.getOptionName(), welfareOption.getId(), 20);
entity.setType(10);
@@ -543,4 +559,150 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl entities = new ArrayList<>();
+ entities.add(new ExcelExportEntity("工号", "loginName", 20));
+ entities.add(new ExcelExportEntity("姓名", "userName", 20));
+ entities.add(new ExcelExportEntity("电话号码", "mobile", 20));
+ entities.add(new ExcelExportEntity("在职状态", "userState", 20));
+ entities.add(new ExcelExportEntity("人员类型", "personType", 20));
+ entities.add(new ExcelExportEntity("所在分工会", "welfareUnionName", 30));
+ entities.add(new ExcelExportEntity("所在单位", "welfareUnitName", 50));
+ entities.add(new ExcelExportEntity("选择份数", "selectNum", 10));
+ entities.add(new ExcelExportEntity("收货人", "recipient", 15));
+ entities.add(new ExcelExportEntity("联系方式", "phone", 20));
+ entities.add(new ExcelExportEntity("收货地址", "address", 60));
+
+ Sql sql = Sqls.create("""
+ SELECT
+ u.loginname AS loginName,
+ u.username AS userName,
+ wpus.mobile,
+ wl.userState,
+ wl.personType,
+ wl.welfareUnionName,
+ wl.welfareUnitName,
+ wpus.receiveAddress,
+ wpus.selectNum,
+ wpus.selectOptionId
+ FROM welfare_project_user_selection wpus
+ LEFT JOIN welfare_list wl ON wl.userId = wpus.selectUserId AND wl.projectId = wpus.welfareId
+ LEFT JOIN sys_user u ON u.id = wpus.selectUserId
+ $condition
+ """);
+ Cnd cnd = Cnd.NEW();
+ cnd.and("wpus.welfareId", "=", projectId);
+ cnd.and("wpus.selectNum", "!=", 0);
+ cnd.andEX("wl.welfareUnionId", "=", resolveExportUnionId(unionId));
+ cnd.asc("wl.welfareUnionName").asc("wl.welfareUnitName").asc("u.loginname");
+ sql.setCondition(cnd);
+ List rows = listMap(sql);
+ rows.forEach(this::fillV3ReceiveAddress);
+
+ try (Workbook workbook = new XSSFWorkbook()) {
+ for (WelfareProjectSubjectOption option : getNaturalSortedOptions(projectId)) {
+ List optionRows = rows.stream()
+ .filter(row -> option.getId().equals(row.getString("selectOptionId")))
+ // EasyPOI 生成工作表时会移除已处理行,必须传入可修改列表。
+ .collect(Collectors.toCollection(ArrayList::new));
+ ExportParams exportParams = new ExportParams();
+ exportParams.setType(ExcelType.XSSF);
+ exportParams.setTitle(option.getOptionName() + "选择情况");
+ exportParams.setSheetName(option.getOptionName());
+ new ExcelExportService().createSheetForMap(workbook, exportParams, entities, optionRows);
+ }
+ CommonDownloadUtil.download("按品牌导出选择情况表.xlsx", workbook, response);
+ } catch (Exception e) {
+ log.error("按品牌导出Excel失败", e);
+ }
+ }
+
+ /** 分工会角色只能导出本人工会数据,校级角色可按页面筛选导出。 */
+ private String resolveExportUnionId(String unionId) {
+ if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())
+ || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_ADMIN.name())
+ || AuthUtil.hasRole(RoleConstant.BRANCH_UNION_WENTI_SPORTS.name())) {
+ return SecurityUtil.getUnionId();
+ }
+ return unionId;
+ }
+
+ /** 将历史收货信息拆为 V3 导出所需的收货人、联系方式和收货地址三列。 */
+ private void fillV3ReceiveAddress(NutMap row) {
+ String receiveAddress = row.getString("receiveAddress");
+ if (StrUtil.isBlank(receiveAddress)) {
+ return;
+ }
+ Map values = new HashMap<>();
+ for (String pair : receiveAddress.split("[,,]")) {
+ String[] keyValue = pair.split("[::]", 2);
+ if (keyValue.length == 2) {
+ values.put(keyValue[0].trim(), keyValue[1].trim());
+ }
+ }
+ row.put("recipient", values.get("收件人"));
+ row.put("phone", values.get("联系方式"));
+ row.put("address", values.get("收货地址"));
+ }
+
+ /**
+ * 按套餐名称进行自然排序,数字片段按数值比较、英文字母忽略大小写比较,避免“套餐10”排在“套餐2”之前。
+ */
+ private List getNaturalSortedOptions(String projectId) {
+ List options = dao().query(WelfareProjectSubjectOption.class,
+ Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
+ options.sort(Comparator.comparing(WelfareProjectSubjectOption::getOptionName, this::compareOptionNames)
+ .thenComparing(option -> option.getOptionSort() == null ? Integer.MAX_VALUE : option.getOptionSort())
+ .thenComparing(WelfareProjectSubjectOption::getId));
+ return options;
+ }
+
+ private int compareOptionNames(String left, String right) {
+ String leftName = StrUtil.blankToDefault(left, "");
+ String rightName = StrUtil.blankToDefault(right, "");
+ int leftIndex = 0;
+ int rightIndex = 0;
+ while (leftIndex < leftName.length() && rightIndex < rightName.length()) {
+ char leftChar = leftName.charAt(leftIndex);
+ char rightChar = rightName.charAt(rightIndex);
+ if (Character.isDigit(leftChar) && Character.isDigit(rightChar)) {
+ int leftEnd = leftIndex;
+ int rightEnd = rightIndex;
+ while (leftEnd < leftName.length() && Character.isDigit(leftName.charAt(leftEnd))) {
+ leftEnd++;
+ }
+ while (rightEnd < rightName.length() && Character.isDigit(rightName.charAt(rightEnd))) {
+ rightEnd++;
+ }
+ String leftNumber = leftName.substring(leftIndex, leftEnd).replaceFirst("^0+(?!$)", "");
+ String rightNumber = rightName.substring(rightIndex, rightEnd).replaceFirst("^0+(?!$)", "");
+ int numberCompare = Integer.compare(leftNumber.length(), rightNumber.length());
+ if (numberCompare != 0) {
+ return numberCompare;
+ }
+ numberCompare = leftNumber.compareTo(rightNumber);
+ if (numberCompare != 0) {
+ return numberCompare;
+ }
+ leftIndex = leftEnd;
+ rightIndex = rightEnd;
+ continue;
+ }
+ int charCompare = String.valueOf(leftChar).compareToIgnoreCase(String.valueOf(rightChar));
+ if (charCompare != 0) {
+ return charCompare;
+ }
+ leftIndex++;
+ rightIndex++;
+ }
+ return Integer.compare(leftName.length(), rightName.length());
+ }
}
diff --git a/src/main/resources/views/platform/zhgh/welfare/projectMange/index.html b/src/main/resources/views/platform/zhgh/welfare/projectMange/index.html
index 7f18c35..482a3dc 100644
--- a/src/main/resources/views/platform/zhgh/welfare/projectMange/index.html
+++ b/src/main/resources/views/platform/zhgh/welfare/projectMange/index.html
@@ -373,7 +373,6 @@ layout("/layouts/platform.html"){
formRules: {
name: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
festival: [{ required: true, message: "必选", trigger: ["blur", "change"] }],
- provideTime: [{ required: true, message: "必选", trigger: ["blur", "change"] }],
choiceTime: [{ required: true, message: "必选", trigger: ["blur", "change"] }],
provideAddress: [{ required: true, message: "必选", trigger: ["blur", "change"] }],
provideMode: [{ required: true, message: "必选", trigger: ["blur", "change"] }],
diff --git a/src/main/resources/views/platform/zhgh/welfare/selectionSituation/index.html b/src/main/resources/views/platform/zhgh/welfare/selectionSituation/index.html
index 871cf11..0dd7c97 100644
--- a/src/main/resources/views/platform/zhgh/welfare/selectionSituation/index.html
+++ b/src/main/resources/views/platform/zhgh/welfare/selectionSituation/index.html
@@ -29,8 +29,8 @@ layout("/layouts/platform.html"){
-
-
+
+
@@ -66,10 +66,33 @@ layout("/layouts/platform.html"){
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -185,10 +208,13 @@ layout("/layouts/platform.html"){
pageForm: {
searchName: "username",
year: new Date().getFullYear().toString(),
- isSelect: null
+ isSelect: null,
+ personTypes: [],
+ userStates: []
},
unionOptions: [],
unitOptions: [],
+ aidFundMemberUserTypeOptions: [],
projectOptions: [],
tableColumns: [
{ prop: "loginName", label: "工号" },
@@ -401,6 +427,9 @@ layout("/layouts/platform.html"){
this.getWelfareList()
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
+ // 人员分类下拉仅在当前页面排除离退休人员,不影响全局字典及其他页面。
+ this.$set(this, "aidFundMemberUserTypeOptions", (await this.$businessTool.getDictOptions("AIDFUND_MEMBER_USER_TYPE"))
+ .filter((item) => item.code !== "离退休人员"))
}
})
diff --git a/src/main/resources/views/platform/zhgh/welfare/statistics/index.html b/src/main/resources/views/platform/zhgh/welfare/statistics/index.html
index 0208572..ed61b40 100644
--- a/src/main/resources/views/platform/zhgh/welfare/statistics/index.html
+++ b/src/main/resources/views/platform/zhgh/welfare/statistics/index.html
@@ -33,15 +33,21 @@ layout("/layouts/platform.html"){
- 按福利选项导出
+
+
提醒未选择人员
-
- 导出汇总表
+
+
+
+ 导出各分工会福利签领表
+ 按品牌导出
+ 导出已选名单
+ 导出未选名单
{{row.unSelectedNum}}
+
+
+ 导出福利签领表
+ 已选人员
+
+
@@ -113,7 +125,7 @@ layout("/layouts/platform.html"){
remindUnSelectedPlaceholder() {
this.$message.info("提醒未选择人员功能待开发")
},
- // 导出汇总表
+ // V4 原汇总表导出方法保留,页面已改用 V3 风格的导出入口。
exportSummary() {
this.$downLoad("/platform/welfare/statistics/exportSummary", {
projectId: this.pageForm.projectId
@@ -129,7 +141,7 @@ layout("/layouts/platform.html"){
this.$refs.unSelectedUserRef.onOpen(this.pageForm.projectId, row)
},
- // 按福利选项导出
+ // V4 原按福利选项导出方法保留,页面已改用 V3 的按品牌导出入口。
exportByWelfareOptions() {
this.$downLoad("/platform/welfare/statistics/exportByWelfareOptions", {
projectId: this.pageForm.projectId,
@@ -137,6 +149,38 @@ layout("/layouts/platform.html"){
})
},
+ // V3 按品牌导出:按套餐拆分工作表,并传递当前分工会筛选范围。
+ exportByWelfareOptionsV3() {
+ this.$downLoad("/platform/welfare/statistics/exportByWelfareOptions", {
+ projectId: this.pageForm.projectId,
+ unionId: this.pageForm.unionId
+ })
+ },
+
+ // V3 已选、未选名单导出:未选择分工会时由后台导出当前数据权限内的全部人员。
+ exportReceiveDetailByUnionId(flag) {
+ this.$downLoad("/platform/welfare/statistics/exportReceiveDetailByUnionId", {
+ projectId: this.pageForm.projectId,
+ unionId: this.pageForm.unionId,
+ flag: flag
+ })
+ },
+
+ // V3 单个分工会福利签领表导出。
+ exportReceiveDetailByUnionIdWord(row) {
+ this.$downLoad("/platform/welfare/statistics/exportReceiveDetailByUnionIdWord", {
+ projectId: this.pageForm.projectId,
+ unionId: row.id
+ })
+ },
+
+ // V3 全部分工会福利签领表导出,后台生成 ZIP 文件。
+ allExportReceiveDetailByUnionIdWord() {
+ this.$downLoad("/platform/welfare/statistics/allExportReceiveDetailByUnionIdWord", {
+ projectId: this.pageForm.projectId
+ })
+ },
+
async pageData() {
this.tableLoading = true
const resp = await this.$axios.post("/platform/welfare/statistics/pageData", this.pageForm)
diff --git a/src/main/resources/views/platform/zhgh/welfare/statistics/selectedUser.js b/src/main/resources/views/platform/zhgh/welfare/statistics/selectedUser.js
index 3fe3029..6603251 100644
--- a/src/main/resources/views/platform/zhgh/welfare/statistics/selectedUser.js
+++ b/src/main/resources/views/platform/zhgh/welfare/statistics/selectedUser.js
@@ -6,7 +6,7 @@ const selectedUser = {
-
@@ -76,18 +76,6 @@ const addUser = {
-
-
-
-
-
-
-
{
- if (res.code === 0) {
- this.$set(this, "threeUnitOptions", res.data || [])
- } else {
- this.$message.error(res.msg || "三级单位查询失败")
- }
- })
- .catch(() => {
- this.$message.error("三级单位查询失败,请稍后重试")
- })
- },
-
pageData() {
this.tableLoading = true
this.$axios
diff --git a/src/main/resources/views/platform/zhgh/welfare/welfareUser/index.html b/src/main/resources/views/platform/zhgh/welfare/welfareUser/index.html
index ac5be5b..b4499c0 100644
--- a/src/main/resources/views/platform/zhgh/welfare/welfareUser/index.html
+++ b/src/main/resources/views/platform/zhgh/welfare/welfareUser/index.html
@@ -25,7 +25,7 @@ layout("/layouts/platform.html"){
-
+
@@ -133,11 +133,6 @@ layout("/layouts/platform.html"){
-
-
-
-
@@ -148,6 +143,35 @@ layout("/layouts/platform.html"){
+
+
+
+
+ 导出报销表
+
+
+ 导入快递单号
+
删除人员
@@ -254,6 +278,8 @@ layout("/layouts/platform.html"){
width="700px"
:extra_params="{projectId:pageForm.projectId}"
>
+
+