This commit is contained in:
那些花儿
2025-06-11 09:38:24 +08:00
parent 8f2934305e
commit 49838f730d
20 changed files with 1084 additions and 452 deletions
@@ -297,59 +297,44 @@ public class SysHomeController {
@ApiOperation("获取新闻")
@Ok("json")
public Result getNews() {
//获取是否有缓存
String news = redisService.get("gonghui_news");
if (StrUtil.isNotBlank(news)) {
List<NutMap> result = Json.fromJsonAsList(NutMap.class, news);
return Result.success(result);
} else {
// 定义要爬取的URL
String url = "https://gonghui.njupt.edu.cn/";
try {
// 使用Jsoup连接到URL并获取页面内容
Document document = Jsoup.connect(url).get();
Elements paragraphs = document.select("div.mbox");
List<NutMap> results = new ArrayList<>();
for (Element element : paragraphs) {
NutMap map = new NutMap();
Elements title = element.select(".title");
Elements ulEle = element.select(".notice-list, .notice-list2");
Elements liEle = ulEle.select("li");
List<NutMap> mapList = new ArrayList<>();
liEle.forEach(el -> {
NutMap m = new NutMap();
Elements a = el.select("a");
m.put("text", a.text());
m.put("href", a.attr("href"));
Elements div = el.select("div");
m.put("time", div.text());
mapList.add(m);
});
map.put("label", title.text());
mapList.sort((o1, o2) -> {
// 解析日期字符串
LocalDate date1 = (StrUtil.isNotBlank(o1.getString("time"))) ? LocalDate.parse(o1.getString("time"), DateTimeFormatter.ISO_LOCAL_DATE) : null;
LocalDate date2 = (StrUtil.isNotBlank(o2.getString("time"))) ? LocalDate.parse(o2.getString("time"), DateTimeFormatter.ISO_LOCAL_DATE) : null;
// 定义要爬取的URL
String domain = "https://nsdgh.njnu.edu.cn";
try {
// 使用Jsoup连接到URL并获取页面内容
Document document = Jsoup.connect(domain).get();
List<NutMap> results = new ArrayList<>();
// 检查是否为null,并进行降序排序
if (date1 == null && date2 == null) {
return 0; // 两者都为null,视为相等
} else if (date1 == null) {
return 1; // o1为null,视为较大
} else if (date2 == null) {
return -1; // o2为null,视为较小
} else {
return date2.compareTo(date1); // 正常比较,降序
}
});
map.put("value", mapList);
results.add(map);
}
redisService.setex("gonghui_news", 60 * 60 * 6, Json.toJson(results));
return Result.success(results);
} catch (IOException ignored) {
// 最新新闻
Element newsElement = document.getElementById("news");
// 获取所有li元素下的a标签
Elements links = newsElement.select("li a");
List<NutMap> list = links.stream().map(a -> {
NutMap map = new NutMap();
map.put("href", domain + "/" + a.attr("href"));
map.put("text", a.text());
return map;
}).toList();
results.add(NutMap.NEW().addv("label", "最新新闻").addv("value", list));
// 通知公告
Elements newsSections = document.select("div.news1");
for (Element section : newsSections) {
String category = section.selectFirst("h6").ownText(); // 获取"通知公告"或"分工会"
Elements items = section.select("li a");
List<NutMap> list1 = items.stream().map(a -> {
NutMap map = new NutMap();
map.put("href", domain + "/" + a.attr("href"));
map.put("text", a.text());
return map;
}).toList();
results.add(NutMap.NEW().addv("label", category).addv("value", list1));
}
return Result.success();
return Result.success(results);
} catch (Exception e) {
log.error(e);
return Result.error();
}
}
}
@@ -23,10 +23,17 @@ public class WelfareCommonController {
private WelfareListService welfareListService;
@At
@SaCheckPermission("welfare")
@ApiOperation("获取项目列表")
public Result list(Integer year) {
return Result.success(projectService.getWelfareList(year));
}
@At
@SaCheckPermission("welfare")
@ApiOperation("获取项目信息")
public Result projectInfo(@Valid String id){
public Result projectInfo(@Valid String id) {
return Result.success(projectService.projectInfo(id));
}
@@ -25,6 +25,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.formula.functions.T;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
@@ -71,7 +72,6 @@ public class WelfareListController {
public void index() {
}
@At
@SaCheckPermission("welfare.list.mange")
@Ok("json:{dateFormat:'yyyy-MM-dd'}")
@@ -92,23 +92,30 @@ public class WelfareListController {
return Result.success();
}
@At
@SaCheckPermission("welfare.list.mange")
@ApiOperation("分页查询非福利会员")
@Ok("json:{dateFormat:'yyyy-MM-dd'}")
public Result notWelfareUserPageData(@Valid @Param("pageForm") WelfareFilterUserPageForm pageForm){
public Result notWelfareUserPageData(@Valid @Param("pageForm") WelfareFilterUserPageForm pageForm) {
return Result.success(welfareListService.notWelfareUserPageData(pageForm));
}
@At
@SaCheckPermission("welfare.list.mange")
@ApiOperation("添加用户到福利名单")
public Result addWelfareUser(@Valid @Param("pageForm") WelfareFilterUserPageForm pageForm){
public Result addWelfareUser(@Valid @Param("pageForm") WelfareFilterUserPageForm pageForm) {
welfareListService.addWelfareUser(pageForm);
return Result.success();
}
@At
@SaCheckPermission("welfare.list.mange")
@ApiOperation("编辑备注")
public Result updateRemark(@Param("remark") String remark, @Param("id") @Valid String id) {
welfareListService.update(Chain.make("remark", remark), Cnd.where("id", "=", id));
return Result.success();
}
@At
@Ok("void")
@SaCheckPermission("welfare.list.mange")
@@ -0,0 +1,118 @@
package com.budwk.app.zhgh.welfare.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
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.utils.PageUtil;
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
import com.budwk.app.zhgh.welfare.service.WelfareListService;
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
import com.budwk.app.zhgh.welfare.service.WelfareSingleService;
import com.budwk.app.zhgh.welfare.service.WelfareStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Collections;
@IocBean
@Ok("json:full")
@At("/platform/welfare/selection/situation")
@Slf4j
@Api(tags = "选择情况")
public class WelfareSelectionSituationController {
@Inject
private Dao dao;
@Inject
private WelfareListService welfareListService;
@Inject
private WelfareStatisticsService welfareStatisticsService;
@Inject
private WelfareSelectionSituationService situationService;
@At("")
@Ok("beetl:/platform/zhgh/welfare/selectionSituation/index.html")
@SaCheckPermission("welfare.selection.situation")
public void index() {
}
@At
@SaCheckPermission("welfare.selection.situation")
@ApiOperation("分页查询")
public Result pageData(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm) {
if (StrUtil.isBlank(pageForm.getProjectId())) {
return Result.success(new Pagination<>(1, 10, 0, Collections.emptyList()));
}
Sql sql = Sqls.create("""
SELECT
t1.id,
t1.welfareUnionName,
t1.welfareUnitName,
GROUP_CONCAT(DISTINCT t3.optionName) AS selectedOptions,
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
t4.username AS userName,
t4.loginname AS loginName,
t4.sex
FROM
welfare_list t1
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId AND t2.selectUserId = t1.userId
LEFT JOIN welfare_project_subject_option t3 ON t3.id = t2.selectOptionId
LEFT JOIN sys_user t4 ON t4.id = t1.userId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.projectId", "=", pageForm.getProjectId());
if (StrUtil.isNotBlank(pageForm.getUserName())) {
cnd.where().andLike("t4.username", pageForm.getUserName());
}
if (StrUtil.isNotBlank(pageForm.getLoginName())) {
cnd.where().andLike("t4.loginname", pageForm.getLoginName());
}
cnd.andEX("t1.welfareUnitId", "in", pageForm.getUnitIds());
cnd.andEX("t1.welfareUnionId", "=", pageForm.getUnionId());
if (pageForm.getIsSelect() != null) {
if (pageForm.getIsSelect()) {
cnd.and("t2.id", "IS NOT", null);
} else {
cnd.and("t2.id", "IS", null);
}
}
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.asc("welfareUnionName");
cnd.asc("welfareUnitName");
} else {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
cnd.groupBy("t1.id");
sql.setCondition(cnd);
Pagination pagination = welfareListService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("welfare.selection.situation")
@Ok("void")
@ApiOperation("导出Excel")
public void exportXlsx(@Valid @Param("pageForm") WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
situationService.exportXlsx(pageForm, response);
}
}
@@ -72,7 +72,8 @@ public class WelfareStatisticsController {
@At
@SaCheckPermission("welfare.statistics")
public Result pageData(String projectId, String unionId) {
return Result.success(welfareSingleService.pageData(projectId, unionId));
NutMap data = welfareStatisticsService.pageData(projectId, unionId);
return Result.success(data);
}
@@ -89,7 +90,7 @@ public class WelfareStatisticsController {
@SaCheckPermission("welfare.statistics")
@ApiOperation("导出某分工会已选择人员")
public void exportSelectedUnionUser(String projectId, String unionId, HttpServletResponse response) {
welfareStatisticsService.exportSelectedUnionUser(projectId,unionId,response);
welfareStatisticsService.exportSelectedUnionUser(projectId, unionId, response);
}
@At
@@ -105,7 +106,7 @@ public class WelfareStatisticsController {
@SaCheckPermission("welfare.statistics")
@ApiOperation("导出某分工会未选择人员")
public void exportUnSelectedUnionUser(String projectId, String unionId, HttpServletResponse response) {
welfareStatisticsService.exportUnSelectedUnionUser(projectId,unionId,response);
welfareStatisticsService.exportUnSelectedUnionUser(projectId, unionId, response);
}
@At
@@ -113,7 +114,7 @@ public class WelfareStatisticsController {
@SaCheckPermission("welfare.statistics")
@ApiOperation("导出各分工会选择情况")
public void exportUnionExcel(String projectId, HttpServletResponse response) {
welfareStatisticsService.exportUnionExcel(projectId,response);
welfareStatisticsService.exportUnionExcel(projectId, response);
}
@@ -121,12 +122,17 @@ 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, HttpServletResponse response) {
welfareStatisticsService.exportByWelfareOptions(projectId, response);
}
@At
@Ok("void")
@SaCheckPermission("welfare.statistics")
@ApiOperation("导出汇总表")
public void exportSummary(String projectId, HttpServletResponse response) {
welfareStatisticsService.exportSummary(projectId, response);
}
/**
@@ -93,4 +93,9 @@ public class WelfareList extends BaseModel{
@ColDefine(type = ColType.BOOLEAN)
private Boolean isAutoSelect;
@Column
@Comment("备注")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String remark;
}
@@ -0,0 +1,32 @@
package com.budwk.app.zhgh.welfare.param;
import com.budwk.app.base.param.PageForm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel("选择统计分页参数")
public class WelfareSelectionSituationPageForm extends PageForm {
@ApiModelProperty("福利项目id")
private String projectId;
@ApiModelProperty("姓名")
private String userName;
@ApiModelProperty("工号")
private String loginName;
@ApiModelProperty("工会id")
private String unionId;
@ApiModelProperty("单位id")
private String[] unitIds;
@ApiModelProperty("是否已选择")
private Boolean isSelect;
}
@@ -0,0 +1,13 @@
package com.budwk.app.zhgh.welfare.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.welfare.model.WelfareList;
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
import javax.servlet.http.HttpServletResponse;
public interface WelfareSelectionSituationService extends BaseService<WelfareList> {
void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response);
}
@@ -4,11 +4,20 @@ 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.welfare.model.WelfareProject;
import org.nutz.lang.util.NutMap;
import javax.servlet.http.HttpServletResponse;
public interface WelfareStatisticsService extends BaseService<WelfareProject> {
/**
* 分页查询
* @param projectId
* @param unionId
* @return
*/
NutMap pageData(String projectId, String unionId);
/**
* 查询某分工会已选择人员
* @param pageForm
@@ -54,4 +63,10 @@ public interface WelfareStatisticsService extends BaseService<WelfareProject> {
* @param response
*/
void exportByWelfareOptions(String projectId, HttpServletResponse response);
/**
* 导出汇总表
*/
void exportSummary(String projectId, HttpServletResponse response);
}
@@ -0,0 +1,105 @@
package com.budwk.app.zhgh.welfare.service.impl;
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.hutool.core.util.StrUtil;
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.zhgh.welfare.model.WelfareList;
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
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 javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
@IocBean(args = {"refer:dao"})
@Slf4j
public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<WelfareList> implements WelfareSelectionSituationService {
public WelfareSelectionSituationServiceImpl(Dao dao) {
super(dao);
}
@Override
public void exportXlsx(WelfareSelectionSituationPageForm pageForm, HttpServletResponse response) {
Sql sql = Sqls.create("""
SELECT
t1.id,
t1.welfareUnionName,
t1.welfareUnitName,
GROUP_CONCAT(DISTINCT t3.optionName) AS selectedOptions,
GROUP_CONCAT(DISTINCT t2.mobile) AS mobile,
t4.username AS userName,
t4.loginname AS loginName,
t4.sex
FROM
welfare_list t1
LEFT JOIN welfare_project_user_selection t2 ON t2.welfareId = t1.projectId AND t2.selectUserId = t1.userId
LEFT JOIN welfare_project_subject_option t3 ON t3.id = t2.selectOptionId
LEFT JOIN sys_user t4 ON t4.id = t1.userId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.projectId", "=", pageForm.getProjectId());
if (StrUtil.isNotBlank(pageForm.getUserName())) {
cnd.where().andLike("t4.username", pageForm.getUserName());
}
if (StrUtil.isNotBlank(pageForm.getLoginName())) {
cnd.where().andLike("t4.loginname", pageForm.getLoginName());
}
cnd.andEX("t1.welfareUnitId", "in", pageForm.getUnitIds());
cnd.andEX("t1.welfareUnionId", "=", pageForm.getUnionId());
if (pageForm.getIsSelect() != null) {
if (pageForm.getIsSelect()) {
cnd.and("t2.id", "IS NOT", null);
} else {
cnd.and("t2.id", "IS", null);
}
}
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.asc("welfareUnionName");
cnd.asc("welfareUnitName");
} else {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
cnd.groupBy("t1.id");
sql.setCondition(cnd);
List<NutMap> list = listMap(sql);
// excel列
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
entities.add(new ExcelExportEntity("性别", "sex", 20));
entities.add(new ExcelExportEntity("所属单位", "welfareUnitName", 20));
entities.add(new ExcelExportEntity("所属工会", "welfareUnionName", 20));
entities.add(new ExcelExportEntity("所选福利", "selectedOptions", 20));
entities.add(new ExcelExportEntity("联系电话", "mobile", 20));
// 设置导出参数
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
// 导出Excel并下载
try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, list)) {
CommonDownloadUtil.download("选择情况.xlsx", workbook, response);
} catch (Exception e) {
log.error("导出Excel失败", e);
}
}
}
@@ -4,17 +4,22 @@ 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.bean.BeanUtil;
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.base.utils.CommonDownloadUtil;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.zhgh.welfare.model.WelfareList;
import com.budwk.app.zhgh.welfare.model.WelfareProject;
import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
import com.budwk.app.zhgh.welfare.model.WelfareUserSelection;
import com.budwk.app.zhgh.welfare.service.WelfareStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
@@ -26,9 +31,8 @@ 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
@@ -37,6 +41,82 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
super(dao);
}
@Override
public NutMap pageData(String projectId, String unionId) {
// 分工会数据
List<Sys_union> unions = dao().query(Sys_union.class, Cnd.NEW().andEX(Sys_union::getId, "=", unionId).asc(Sys_union::getUnionCode));
List<NutMap> mapUnions = BeanUtil.copyToList(unions, NutMap.class);
// 表格动态列数据
List<NutMap> dynamicTableColumns = new ArrayList<>() {{
add(NutMap.NEW().addv("label", "分工会").addv("prop", "name"));
add(NutMap.NEW().addv("label", "本次福利会员人数").addv("prop", "teacherSum"));
add(NutMap.NEW().addv("label", "已选人数").addv("prop", "selectedNum"));
add(NutMap.NEW().addv("label", "未选人数").addv("prop", "unSelectedNum"));
}};
// 选项数据
List<WelfareProjectSubjectOption> welfareOptions = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
for (WelfareProjectSubjectOption welfareOption : welfareOptions) {
dynamicTableColumns.add(NutMap.NEW().addv("label", welfareOption.getOptionName()).addv("prop", welfareOption.getId()));
}
// 查询福利名单以及查询出选项数据
Sql sql = Sqls.create("""
SELECT
t1.*,
t2.id IS NOT NULL AS has_selected
FROM
`welfare_list` t1
LEFT JOIN welfare_project_user_selection t2 ON t2.selectUserId = t1.userId
AND t2.welfareId = t1.projectId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.projectId", "=", projectId);
cnd.andEX("t1.welfareUnionId", "=", unionId);
sql.setCondition(cnd);
List<NutMap> welfareSelectionList = listMap(sql);
Sql sql2 = Sqls.create("""
SELECT
t1.*,
t2.welfareUnionId
FROM
`welfare_project_user_selection` t1
LEFT JOIN welfare_list t2 ON t2.projectId = t1.welfareId
AND t1.selectUserId = t2.userId
$condition
""");
Cnd cnd2 = Cnd.NEW();
cnd2.and("t1.welfareId", "=", projectId);
sql2.setCondition(cnd2);
List<NutMap> userSelections = listMap(sql2);
for (NutMap union : mapUnions) {
// 福利人数
long teacherSum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id"))).count();
union.put("teacherSum", teacherSum);
// 已选人数
long selectedNum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
union.put("selectedNum", selectedNum);
// 未选人数
union.put("unSelectedNum", teacherSum - selectedNum);
// 各选项的选择人数
for (WelfareProjectSubjectOption option : welfareOptions) {
long count = userSelections.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getString("selectOptionId").equals(option.getId()))
.map(v -> v.getString("selectUserId")).distinct().count();
union.put(option.getId(), count);
}
}
return NutMap.NEW().addv("tableList", mapUnions).addv("tableColumn", dynamicTableColumns);
}
@Override
public Pagination selectedUnionUserPageData(PageForm pageForm, String projectId, String unionId) {
Sql sql = Sqls.create("""
@@ -240,9 +320,143 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
@Override
public void exportByWelfareOptions(String projectId, HttpServletResponse response) {
Workbook workbook = new XSSFWorkbook();
List<ExcelExportEntity> exportEntities = new ArrayList<>();
exportEntities.add(new ExcelExportEntity("工号", "loginName", 20));
exportEntities.add(new ExcelExportEntity("姓名", "userName", 20));
exportEntities.add(new ExcelExportEntity("电话号码", "mobile", 20));
exportEntities.add(new ExcelExportEntity("所在分工会", "welfareUnionName", 20));
exportEntities.add(new ExcelExportEntity("所在单位", "welfareUnitName", 20));
exportEntities.add(new ExcelExportEntity("所在福利", "optionName", 50));
Sql sql = Sqls.create("""
SELECT
u.loginname AS loginName,
u.username AS userName,
wl.welfareUnitName,
wl.welfareUnionName,
wpus.mobile,
wpus.selectOptionId,
wpso.optionName,
GROUP_CONCAT(DISTINCT wpso.optionName, '', wpus.selectNum, '份)') selectOptionName
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
LEFT JOIN welfare_project_subject_option wpso ON wpso.id = wpus.selectOptionId
WHERE
wpus.welfareId = @projectId
GROUP BY
u.loginname
ORDER BY
wl.welfareUnionName DESC,
wl.welfareUnitName DESC,
wpus.selectOptionId DESC
""");
sql.setParam("projectId", projectId);
List<NutMap> list = listMap(sql);
List<WelfareProjectSubjectOption> options = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
for (WelfareProjectSubjectOption option : options) {
ExcelExportService service = new ExcelExportService();
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
exportParams.setTitle(option.getOptionName() + "选择情况");
exportParams.setSheetName(option.getOptionName());
List<NutMap> v = list.stream().filter(w -> w.getString("selectOptionId").equals(option.getId())).collect(Collectors.toList());
service.createSheetForMap(workbook, exportParams, exportEntities, v);
}
try {
CommonDownloadUtil.download("按选项导出选择情况表.xlsx", workbook, response);
} catch (Exception e) {
log.error("导出Excel失败", e);
}
}
@Override
public void exportSummary(String projectId, HttpServletResponse response) {
// 分工会数据
List<Sys_union> unions = dao().query(Sys_union.class, Cnd.NEW().asc(Sys_union::getUnionCode));
List<NutMap> mapUnions = BeanUtil.copyToList(unions, NutMap.class);
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("分工会", "name", 20));
entities.add(new ExcelExportEntity("本次福利会员人数", "teacherSum", 20));
entities.add(new ExcelExportEntity("已选人数", "selectedNum", 20));
entities.add(new ExcelExportEntity("未选人数", "unSelectedNum", 20));
// 选项数据
List<WelfareProjectSubjectOption> welfareOptions = dao().query(WelfareProjectSubjectOption.class, Cnd.where(WelfareProjectSubjectOption::getWelfareId, "=", projectId));
for (WelfareProjectSubjectOption welfareOption : welfareOptions) {
entities.add(new ExcelExportEntity(welfareOption.getOptionName(), welfareOption.getId(), 20));
}
// 查询福利名单以及查询出选项数据
Sql sql = Sqls.create("""
SELECT
t1.*,
t2.id IS NOT NULL AS has_selected
FROM
`welfare_list` t1
LEFT JOIN welfare_project_user_selection t2 ON t2.selectUserId = t1.userId
AND t2.welfareId = t1.projectId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("t1.projectId", "=", projectId);
sql.setCondition(cnd);
List<NutMap> welfareSelectionList = listMap(sql);
Sql sql2 = Sqls.create("""
SELECT
t1.*,
t2.welfareUnionId
FROM
`welfare_project_user_selection` t1
LEFT JOIN welfare_list t2 ON t2.projectId = t1.welfareId
AND t1.selectUserId = t2.userId
$condition
""");
Cnd cnd2 = Cnd.NEW();
cnd2.and("t1.welfareId", "=", projectId);
sql2.setCondition(cnd2);
List<NutMap> userSelections = listMap(sql2);
for (NutMap union : mapUnions) {
// 福利人数
long teacherSum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id"))).count();
union.put("teacherSum", teacherSum);
// 已选人数
long selectedNum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
union.put("selectedNum", selectedNum);
// 未选人数
union.put("unSelectedNum", teacherSum - selectedNum);
// 各选项的选择人数
for (WelfareProjectSubjectOption option : welfareOptions) {
long count = userSelections.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getString("selectOptionId").equals(option.getId()))
.map(v -> v.getString("selectUserId")).distinct().count();
union.put(option.getId(), count);
}
}
// 设置导出参数
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
// 导出Excel并下载
try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, mapUnions)) {
CommonDownloadUtil.download("汇总表.xlsx", workbook, response);
} catch (Exception e) {
log.error("导出Excel失败", e);
}
}
}
@@ -1,14 +1,14 @@
const news = {
template: /*language=HTML*/ `
<div class="home-news">
<!-- <el-tabs v-model="activeName">-->
<!-- <el-tab-pane v-for="(item,index) in newsData" :key="index" :label="item.label" :name="item.label" v-if="item.value.length > 0">-->
<!-- <div v-for="(n,i) in item.value" :key="i" @click="openUrl(n.href)">-->
<!-- <span v-if="n.time" class="news_time">{{ n.time }}</span>-->
<!-- <span class="news_text">{{ n.text }}</span>-->
<!-- </div>-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<el-tabs v-model="activeName">
<el-tab-pane v-for="(item,index) in newsData" :key="index" :label="item.label" :name="item.label" v-if="item.value.length > 0">
<div v-for="(n,i) in item.value" :key="i" @click="openUrl(n.href)">
<span v-if="n.time" class="news_time">{{ n.time }}</span>
<span class="news_text">{{ n.text }}</span>
</div>
</el-tab-pane>
</el-tabs>
</div>
`,
data() {
@@ -6,7 +6,7 @@ const quickEntry = {
<div class="quickEntries">
<div v-for="item in quickEntries" :key="item.id" @click="$store.dispatch('pjaxRoute',item.href)" class="quickEntryItem">
<svg-icon :name="item.icon" :size="40" style="color: var(--color-primary)"></svg-icon>
<span>{{item.name}}</span>
<span style="white-space: nowrap">{{item.name}}</span>
</div>
</div>
</el-card>
@@ -1,109 +1,87 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.reverseCheckBox {
margin: 0 10px 0 0 !important;
}
.query-row {
height: 60px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.query-row:not(:last-child) {
border-bottom: 1px dashed rgb(230, 230, 230);
}
.query-row-title {
width: 120px;
}
.query-row > .query-title {
width: 100px;
max-width: 100px;
min-width: 100px;
overflow: hidden;
}
.query-row > .query-content {
min-width: 200px;
overflow: hidden;
}
.query-row > .query-content > .el-tag {
margin-bottom: 5px;
margin-top: 5px;
}
@media screen and (max-width: 992px) {
.query-row:nth-child(4) .query-content .el-col:not(:last-child) {
margin-bottom: 5px;
}
.query-title {
display: none;
}
}
</style>
<style></style>
<div id="app">
<guava ref="guava">
<template>
<query-form @query="assignmentTableData" ref="queryFormRef"></query-form>
<el-card shadow="never">
<table-tool label="会员列表">
<el-select v-model="pageForm.searchType" placeholder="是否会员" clearable
style="width: 120px" @change="pageData" class="mr10" size="small">
<el-select
v-model="pageForm.searchType"
placeholder="是否会员"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="全部教工" value="all"></el-option>
<el-option label="会员" value="member"></el-option>
<el-option label="非会员" value="unMember"></el-option>
</el-select>
<el-select v-model="pageForm.isUnit" placeholder="是否有单位" clearable
style="width: 120px" @change="pageData" class="mr10" size="small">
<el-select
v-model="pageForm.isUnit"
placeholder="是否有单位"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="有单位" value="true"></el-option>
<el-option label="无单位" value="false"></el-option>
</el-select>
<el-select v-model="pageForm.isUnion" placeholder="是否有工会" clearable
style="width: 120px" @change="pageData" class="mr10" size="small">
<el-select
v-model="pageForm.isUnion"
placeholder="是否有工会"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="有工会" value="true"></el-option>
<el-option label="无工会" value="false"></el-option>
</el-select>
<el-button icon="el-icon-printer" class="m10" type="primary"
style="float: right"
size="small" @click="doExport">导出
</el-button>
<el-button icon="el-icon-printer" class="m10" type="primary" style="float: right" size="small" @click="doExport">导出</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" stripe border
:header-cell-style="{background:'#FAFAFA'}" row-key="id"
@sort-change="pageOrder">
<el-table-column align="center" header-align="center" type="index"
:index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table
:data="tableData"
style="width: 100%"
stripe
border
:header-cell-style="{background:'#FAFAFA'}"
row-key="id"
@sort-change="pageOrder"
>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
type="index"
:index="indexMethod"
label="序号"
width="80px"
></el-table-column>
<el-table-column
align="center"
header-align="center"
v-for="column in tableColumns"
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:width="column.width"
:sortable="column.sortable"
>
<template v-if="column.prop==='memberJoinTime'" scope="{row}">
{{$moment(row.memberJoinTime).format('YYYY-MM-DD')}}
</template>
<template v-if="column.prop==='memberJoinTime'" scope="{row}">{{$moment(row.memberJoinTime).format('YYYY-MM-DD')}}</template>
<template v-else-if="column.prop==='birthday'" scope="{row}">
{{row.birthday ? $moment(row.birthday).format('YYYY-MM-DD') : null}}
{{row.birthday ? $moment(row.birthday).format('YYYY-MM-DD') : null}}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="100px">
@@ -125,38 +103,38 @@ layout("/layouts/platform.html"){
<!--#include("queryForm.js"){}#-->
<!--#include("../../common/info/memberInfo.js"){}#-->
new Vue({
el: '#app',
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchType: "member",
searchType: "member"
},
unions: [],
units: [],
childrenData: {},
tableColumns: [
{prop: 'loginname', label: '工号'},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'birthday', label: '出生年月', sortable: true},
{prop: 'mobile', label: '联系电话'},
{prop: 'idCardType', label: '证件类型'},
{prop: 'idCard', label: '证件号码', width: 180},
{prop: 'userState', label: '在职状态', sortable: true},
{prop: 'personType', label: '教职工类别', sortable: true},
{prop: 'preparedBy', label: '聘用方式', sortable: true},
{prop: 'identityType', label: '身份类型', sortable: true},
{prop: 'unionName', label: '所属工会', sortable: true},
{prop: 'unitName', label: '所属单位', sortable: true},
{prop: 'arrivalAtSchoolDate', label: '来校年月', sortable: true},
],
{ prop: "loginname", label: "工号", fixed: "left" },
{ prop: "username", label: "姓名", fixed: "left" },
{ prop: "sex", label: "性别" },
{ prop: "birthday", label: "出生年月", width: 120, sortable: true },
{ prop: "mobile", label: "联系电话" },
{ prop: "idCardType", label: "证件类型" },
{ prop: "idCard", label: "证件号码", width: 180 },
{ prop: "userState", label: "在职状态", width: 120, sortable: true },
{ prop: "personType", label: "教职工类别", width: 120, sortable: true },
{ prop: "preparedBy", label: "聘用方式", width: 120, sortable: true },
{ prop: "identityType", label: "身份类型", width: 120, sortable: true },
{ prop: "unionName", label: "所属工会", width: 120, sortable: true },
{ prop: "unitName", label: "所属单位", width: 120, sortable: true },
{ prop: "arrivalAtSchoolDate", label: "来校年月", width: 120, sortable: true }
]
}
},
components: {
'query-form': MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM,
'member-info': MEMBER_INFO
"query-form": MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM,
"member-info": MEMBER_INFO
},
methods: {
openView(id) {
@@ -175,15 +153,15 @@ layout("/layouts/platform.html"){
this.$downLoad("/platform/member/statistics/comprehensive/doExport", pageForm)
},
assignmentTableData(data) {
this.tableData = data.list;
this.tableData = data.list
this.pageForm = this.$refs.queryFormRef.pageForm
this.pageForm.totalCount = data.totalCount;
this.pageForm.totalCount = data.totalCount
},
pageData() {
this.$refs.queryFormRef.pageForm = this.pageForm
this.$refs.queryFormRef.pageData();
},
},
this.$refs.queryFormRef.pageData()
}
}
})
</script>
<!--#
@@ -1,201 +1,131 @@
const MEMBER_STATISTICS_COMPREHENSIVE_QUERY_FORM = {
template: `
template: /*language=HTML*/ `
<el-card shadow="never">
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-title">年&emsp;&emsp;度:</el-col>
<el-col class="query-row-content" :span="12">
<el-row style="margin-left: 3px">
<el-date-picker @change="doSearch()"
style="width: 85%"
:picker-options="pickerOptions"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="选择年" :clearable="false">
</el-date-picker>
<el-link type="primary" style="margin-left: 10px"
:underline="false"
@click="setNowYear();doSearch()">
本年
</el-link>
</el-row>
</el-col>
<el-col class="query-row-title">姓名/工号:</el-col>
<el-col class="query-row-content" :span="12">
<el-row style="width: 92%">
<el-input placeholder="请输入内容" clearable v-model="pageForm.searchKeyword"></el-input>
</el-row>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-content">
<el-row>
<el-col :span="12">
<span>所属工会:</span>
<el-select placeholder="所属工会" v-model="pageForm.unionId"
clearable multiple style="margin-left: 33px;width: 80%"
@change="flushUnits();doSearch()"
@clear="flushUnits();doSearch()"
filterable>
<el-option v-for="item in unions" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-col>
<el-col :span="12">
<span>所属单位:</span>
<el-select placeholder="所属单位" v-model="pageForm.unitId"
clearable multiple style="margin-left: 33px;width: 80%" filterable>
<el-option v-for="item in units" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row class="query-row">
<el-col class="query-row-title">性别:</el-col>
<el-col class="query-row-content">
<el-tag
:effect="pageForm.sexTypes.includes(item.name)?'dark':'plain'"
:key="item.code"
:type="item.name"
@click="tagClick('sexTypes',item.name)"
style="cursor: pointer"
v-for="item in sexTypeOptions">
{{ item.name }}
</el-tag>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row" style="height: unset;padding: 10px 0">
<el-col class="query-row-title">在职状态:</el-col>
<el-col class="query-row-content" style="display: flex;flex-wrap: wrap;gap: 5px">
<el-tag
style="margin:0;cursor: pointer"
v-for="item in userStateOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.userStates.includes(item.name)?'dark':'plain'"
@click="tagClick('userStates',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="userStateOptions.length&&pageForm.userStates.length"
:underline="false"
@click="pageForm.userStates=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.userStates=userStateOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row" style="height: unset;padding: 10px 0">
<el-col class="query-row-title">教职工类别:</el-col>
<el-col class="query-row-content" style="display: flex;flex-wrap: wrap;gap: 5px">
<el-tag
style="margin:0;cursor: pointer"
v-for="item in personTypeOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.personTypes.includes(item.name)?'dark':'plain'"
@click="tagClick('personTypes',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="personTypeOptions.length&&pageForm.personTypes.length"
:underline="false"
@click="pageForm.personTypes=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.personTypes=personTypeOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row" style="height: unset;padding: 10px 0">
<el-col class="query-row-title">聘用方式:</el-col>
<el-col class="query-row-content" style="display: flex;flex-wrap: wrap;gap: 5px">
<el-tag
style="margin:0;cursor: pointer"
v-for="item in preparedByOptions"
:key="item.code"
:type="item.name"
:effect="pageForm.preparedBys.includes(item.name)?'dark':'plain'"
@click="tagClick('preparedBys',item.name)">
{{ item.name }}
</el-tag>
<el-link type="danger"
v-if="preparedByOptions.length&&pageForm.preparedBys.length"
:underline="false"
@click="pageForm.preparedBys=[];doSearch()">清空
</el-link>
<el-link :underline="false"
@click="pageForm.preparedBys=preparedByOptions.map(p=>p.code);doSearch()"
type="success">全部
</el-link>
</el-col>
</el-row>
<el-row class="query-row" type="flex" align="middle" style="height: unset;padding: 10px 0">
<el-col class="query-row-title">出生日期:</el-col>
<el-col class="query-row-content">
<el-date-picker
v-model="pageForm.startDate"
type="date"
@change="determineStartDate"
placeholder="选择开始日期">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker @change="doSearch"
:picker-options="pickerOptions"
style="width: 100%"
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="选择年" :clearable="false">
</el-date-picker>
</search-item>
<search-item label="姓名工号">
<el-input placeholder="请输入姓名或者工号" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
<search-item label="所属工会">
<el-select placeholder="所属工会"
v-model="pageForm.unionId"
clearable
multiple
@change="flushUnits();doSearch()"
@clear="flushUnits();doSearch()"
filterable>
<el-option v-for="item in unions"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select placeholder="所属单位"
v-model="pageForm.unitId"
clearable
multiple
filterable>
<el-option v-for="item in units"
:label="item.name"
:key="item.id"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="性别">
<el-select v-model="pageForm.sexTypes" clearable multiple placeholder="性别">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</search-item>
<search-item label="人员类型">
<dict-select
clearable
code="USER_PERSON_TYPE"
multiple
collapse-tags
placeholder="请选择人员类型"
v-model="pageForm.personTypes"
></dict-select>
</search-item>
<search-item label="聘用方式">
<dict-select clearable
code="USER_PREPARED_BY_TYPE"
multiple
collapse-tags
placeholder="请选择聘用方式"
v-model="pageForm.preparedBys"></dict-select>
</search-item>
<search-item label="在职状态">
<dict-select
clearable
code="USER_STATE"
multiple
collapse-tags
placeholder="请选择人员状态"
v-model="pageForm.userStates"
></dict-select>
</search-item>
<search-item label="出生日期">
<el-date-picker
v-model="pageForm.endDate"
type="date"
@change="determineEndDate"
placeholder="选择结束日期">
v-model="pageForm.startDate"
type="date"
@change="determineStartDate"
style="width: 100%"
placeholder="选择开始出生日期">
</el-date-picker>
</el-col>
</el-row>
<el-row class="query-row" type="flex" align="middle">
<el-col class="query-row-title">年龄范围:</el-col>
<el-col class="query-row-content">
<el-row type="flex" style="align-items: center">
<el-col :span="15">
<el-slider
v-model="pageForm.age"
range
show-stops
:max="100">
</el-slider>
</el-col>
<el-col :span="9" class="pl20">
当前范围:{{ pageForm.age }}
</el-col>
</el-row>
</el-col>
</el-row>
<el-row type="flex" align="middle" class="query-row">
<el-col class="query-row-title">模糊查询:</el-col>
<el-col class="query-row-content">
<member-cnd @cnd="(v)=>pageForm={...pageForm,...v}"></member-cnd>
</el-col>
</el-row>
<el-row class="query-row" style="justify-content: end">
<el-checkbox v-model="pageForm.reverseSelection" label="是否反选" border
@change="doSearch"
class="reverseCheckBox"></el-checkbox>
<el-button type="danger" icon="el-icon-circle-close" @click="doReset">重置
</el-button>
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
</el-row>
</search-item>
<search-item label="出生日期">
<el-date-picker
v-model="pageForm.endDate"
type="date"
@change="determineEndDate"
style="width: 100%"
placeholder="选择结束出生日期">
</el-date-picker>
</search-item>
<search-item label="年龄区间">
<div style="display: flex;align-items: center">
<el-slider
v-model="pageForm.age"
range
show-stops
:max="100"
style="flex: 1;padding: 0 12px"
>
</el-slider>
<div style="width: 70px;flex-shrink: 0;text-align: right">
{{ pageForm.age ? pageForm.age.join('-') : '' }}
</div>
</div>
</search-item>
</search>
<!-- <el-row type="flex" align="middle" class="query-row">-->
<!-- <el-col class="query-row-title">模糊查询:</el-col>-->
<!-- <el-col class="query-row-content">-->
<!-- <member-cnd @cnd="(v)=>pageForm={...pageForm,...v}"></member-cnd>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- <el-row class="query-row" style="justify-content: end">-->
<!-- <el-checkbox v-model="pageForm.reverseSelection" label="是否反选" border-->
<!-- @change="doSearch"-->
<!-- class="reverseCheckBox"></el-checkbox>-->
<!-- <el-button type="danger" icon="el-icon-circle-close" @click="doReset">重置-->
<!-- </el-button>-->
<!-- <el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>-->
<!-- </el-row>-->
</el-card>
`,
mixins: [initTableMixins],
@@ -0,0 +1,170 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="所属年份">
<el-date-picker
:clearable="false"
placeholder="所属年份"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
@change="getWelfareList"
></el-date-picker>
</search-item>
<search-item label="福利项目">
<el-select :clearable="false" filterable placeholder="请选择福利项目" style="width: 100%" v-model="pageForm.projectId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in projectSelectOptions"></el-option>
</el-select>
</search-item>
<search-item label="姓名">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入姓名"
style="width: 100%"
v-model="pageForm.userName"
></el-input>
</search-item>
<search-item label="工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入工号"
style="width: 100%"
v-model="pageForm.loginName"
></el-input>
</search-item>
<search-item label="所属工会">
<el-select clearable filterable placeholder="请选择工会" style="width: 100%" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unionOptions"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select clearable filterable multiple collapse-tags placeholder="请选择单位" style="width: 100%" v-model="pageForm.unitIds">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitOptions"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="选择情况">
<el-radio-group v-model="pageForm.isSelect" size="small" @change="doSearch">
<el-radio-button :label="null">全部</el-radio-button>
<el-radio-button :label="true">已选择</el-radio-button>
<el-radio-button :label="false">未选择</el-radio-button>
</el-radio-group>
<el-button type="primary" size="small" icon="el-icon-download" style="margin-left: 10px" @click="exportXlsx">
导出选择情况表
</el-button>
</table-tool>
<el-table
:data="tableData"
:size="tableSize"
@sort-change="pageOrder"
ref="tableRef"
row-key="id"
style="width: 100%"
v-loading="tableLoading"
>
<el-table-column :index="indexMethod" label="序号" type="index" width="80px"></el-table-column>
<el-table-column
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
></el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作" width="100px"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchName: "username",
year: new Date().getFullYear().toString(),
isSelect: null
},
unionOptions: [],
unitOptions: [],
projectSelectOptions: [],
tableColumns: [
{ prop: "loginName", label: "工号" },
{ prop: "userName", label: "姓名" },
{ prop: "sex", label: "性别", sortable: true, checked: 0 },
{ prop: "welfareUnionName", label: "所属工会", sortable: true },
{ prop: "welfareUnitName", label: "所属单位", sortable: true },
{ prop: "selectedOptions", label: "所选福利", sortable: true },
{ prop: "mobile", label: "联系电话", sortable: true }
]
}
},
methods: {
getWelfareList() {
this.$axios.post("/platform/welfare/common/list", { year: this.pageForm.year }).then((res) => {
this.projectSelectOptions = res.data
if (res.data && res.data.length > 0) {
this.$set(this.pageForm, "projectId", res.data[0].id)
} else {
this.$set(this.pageForm, "projectId", null)
}
this.doSearch()
})
},
pageData() {
this.tableLoading = true
this.$axios
.post("/platform/welfare/selection/situation/pageData", { pageForm: JSON.stringify(this.pageForm) })
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
.finally(() => {
this.tableLoading = false
})
},
exportXlsx() {
this.$downLoad("/platform/welfare/selection/situation/exportXlsx", { pageForm: JSON.stringify(this.pageForm) })
}
},
async created() {
this.getWelfareList()
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
}
})
</script>
<!--#
}
#-->
@@ -34,14 +34,10 @@ layout("/layouts/platform.html"){
<el-card class="mt10" shadow="never" v-loading="tableLoading">
<table-tool label="工会列表">
<el-button @click="exportByWelfareOptions" icon="el-icon-printer" size="small" type="primary">按福利选项导出</el-button>
<template
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN',
'SCHOOL_UNION_WELFARE_ADMIN'])"
>
<template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN','SCHOOL_UNION_WELFARE_ADMIN'])">
<el-button :disabled="!pageForm.projectId" @click="exportSummary" icon="el-icon-printer" size="small" type="primary">
导出分工会/福利套餐汇总表
导出汇总表
</el-button>
<el-button @click="selectOptionByAdmin" icon="el-icon-printer" size="small" type="primary">管理员代选择</el-button>
</template>
</table-tool>
<el-table
@@ -141,17 +137,12 @@ layout("/layouts/platform.html"){
}
},
methods: {
// 导出汇总表
exportSummary() {
this.$downLoad("/platform/welfare/statistics/exportSummary", {
projectId: this.pageForm.projectId
})
},
exportSelectData() {
this.$downLoad("/platform/welfare/statistics/exportSelectData", {
projectId: this.pageForm.projectId,
unionId: this.pageForm.unionId
})
},
// 查看已选择的人员
openSelected(row) {
this.$refs.selectedUserRef.onOpen(this.pageForm.projectId, row)
@@ -174,13 +165,7 @@ layout("/layouts/platform.html"){
this.tableLoading = true
const resp = await this.$axios.post("/platform/welfare/statistics/pageData", this.pageForm)
if (resp.code === 0) {
this.tableColumns = [
{
prop: "name",
label: "分工会",
width: "300"
}
].concat(resp.data.tableColumn)
this.tableColumns = resp.data.tableColumn
this.tableData = resp.data.tableList
}
this.tableLoading = false
@@ -163,14 +163,9 @@ layout("/layouts/platform.html"){
<el-tag type="warning" v-else>暂无</el-tag>
</template>
</el-table-column>
<el-table-column label="快递单号" prop="courierNumber" show-overflow-tooltip v-if="pageFormProjectType===3">
<template scope="{row}">
<span @click="viewCourierNumber(row)" class="text-primary" style="cursor: pointer">点击查看</span>
</template>
</el-table-column>
<el-table-column label="收货地址" prop="receiveAddress" show-overflow-tooltip v-if="pageFormProjectType===3"></el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="操作" width="100px">
<el-table-column align="center" fixed="right" header-align="center" label="操作" width="200px">
<template scope="{row}">
<el-button @click="$refs.updateRemarkRef.onOpen(row)" size="mini" type="primary">备注</el-button>
<el-button @click="doDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
@@ -194,37 +189,20 @@ layout("/layouts/platform.html"){
<add_welfare_list_by_select ref="addWelfareListUser" @search="doSearch"></add_welfare_list_by_select>
<add-user ref="addUserRef" @refresh="doSearch"></add-user>
<update-remark ref="updateRemarkRef" @refresh="doSearch"></update-remark>
</div>
<script>
<!--#include("importCourierNumberDialog.js"){}#-->
<!--#include("addWelfareListBySelect.js"){}#-->
<!--#include("addUser.js"){}#-->
<!--#include("updateRemark.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
computed: {
pageFormProjectType() {
if (this.pageForm.projectId) {
const projectInfo = this.projectSelectOptions.find((v) => v.id === this.pageForm.projectId)
if (projectInfo) {
return projectInfo.provideMode
}
return null
}
return null
},
pageFormSignMode() {
if (this.pageForm.projectId) {
const projectInfo = this.projectSelectOptions.find((v) => v.id === this.pageForm.projectId)
if (projectInfo) {
return projectInfo.signMode
}
return null
}
return null
},
pageFormProject() {
if (this.pageForm.projectId) {
const projectInfo = this.projectSelectOptions.find((v) => v.id === this.pageForm.projectId)
@@ -239,7 +217,8 @@ layout("/layouts/platform.html"){
components: {
add_welfare_list_by_select: ADD_WELFARE_LIST_BY_SELECT,
"file-import": httpVueLoader("/components/plugins/sysImport/index.vue?v=" + new Date().getTime()),
"add-user": addUser
"add-user": addUser,
"update-remark": updateRemark
},
data() {
return {
@@ -260,7 +239,8 @@ layout("/layouts/platform.html"){
{ prop: "preparedBy", label: "聘用方式", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true },
{ prop: "welfareUnionName", label: "所属工会", sortable: true },
{ prop: "welfareUnitName", label: "所属单位", sortable: true }
{ prop: "welfareUnitName", label: "所属单位", sortable: true },
{ prop: "remark", label: "备注", sortable: true }
],
importData: { fileList: [], isfg: 1 },
@@ -286,32 +266,6 @@ layout("/layouts/platform.html"){
}
this.importDialog = true
},
do_search() {
this.doSearch()
},
viewCourierNumber(row) {
this.$refs.courierNumberInfo.openView(row.projectId, row.id)
},
openImportExpressExcel() {
this.$refs.importCourierNumber.openImportExpressExcel(this.pageForm.projectId, this.pageFormProject)
},
doExcelByOptionId() {
if (!this.pageForm.optionId) {
this.$message.warning("请选择要导出的套餐")
return
}
if (!this.pageForm.projectId) {
this.$message.warning("请选择要导出的福利")
return
}
this.$downLoad("/platform/welfare/list/mange/doExcelByOptionId", {
projectId: this.pageForm.projectId,
optionId: this.pageForm.optionId
})
},
openEditWelfare(row) {
this.$refs.editWelfare.openEditWelfare(row, this.projectSelectOptions)
},
doDelete(row) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
@@ -0,0 +1,59 @@
const updateRemark = {
template: /*language=HTML*/ `
<el-dialog title="修改备注" :visible.sync="visible">
<el-form :model="formData" label-width="80px">
<el-form-item label="姓名">
<el-input :value="formData.username" disabled></el-input>
</el-form-item>
<el-form-item label="工号">
<el-input :value="formData.loginname" disabled></el-input>
</el-form-item>
<el-form-item label="单位">
<el-input :value="formData.welfareUnitName" disabled></el-input>
</el-form-item>
<el-form-item label="分工会">
<el-input :value="formData.welfareUnionName" disabled></el-input>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="formData.remark" placeholder="请填写备注" :maxlength="100" type="textarea" maxlength="100" show-word-limit></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
visible: false,
formData: {}
}
},
methods: {
onOpen(row) {
this.visible = true
this.formData = { ...row }
},
onSubmit() {
this.$confirm("您确定修改吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios
.post("/platform/welfare/list/mange/updateRemark", {
id: this.formData.id,
remark: this.formData.remark
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.$emit("refresh")
this.visible = false
}
})
})
}
}
}
@@ -600,7 +600,7 @@ layout("/layouts/platform_h5.html"){
:key="option.id"
class="welfare-option"
:class="{ selected: projectInfo.isCheckBox === 'radio' ? selectedRadioId === option.id : option.selectNum > 0 }"
@click="projectInfo.isCheckBox === 'radio' ? selectRadioOption(option.id) : null"
@click="projectInfo.isCheckBox === 'radio' && !isDeadlinePassed ? selectRadioOption(option.id) : null"
>
<div class="welfare-option-image">
<van-image :src="option.imgUrl" fit="cover" width="100%" height="100%" radius="4px"></van-image>
@@ -620,7 +620,12 @@ layout("/layouts/platform_h5.html"){
<!-- 单选模式使用单选按钮 -->
<div class="welfare-option-radio" v-if="projectInfo.isCheckBox === 'radio'">
<van-radio :name="option.id" v-model="selectedRadioId" @click="selectRadioOption(option.id)"></van-radio>
<van-radio
:name="option.id"
v-model="selectedRadioId"
@click.stop="isDeadlinePassed ? $toast.fail('已过选择截止时间,无法修改') : selectRadioOption(option.id)"
:disabled="isDeadlinePassed"
></van-radio>
</div>
<!-- 多选模式使用步进器 -->
@@ -631,7 +636,7 @@ layout("/layouts/platform_h5.html"){
disable-input
:default-value="0"
:min="0"
:disabled="false"
:disabled="isDeadlinePassed"
input-width="40px"
button-size="22px"
theme="round"
@@ -644,10 +649,16 @@ layout("/layouts/platform_h5.html"){
<!-- 底部提交按钮 -->
<div class="welfare-footer" v-if="projectInfo.id">
<van-button type="primary" class="welfare-submit-btn" :disabled="!hasSelection" @click="submitSelection" round>确认选择</van-button>
<van-button
type="primary"
class="welfare-submit-btn"
:disabled="submitButtonDisabled"
@click="submitSelection"
round
>{{ isDeadlinePassed ? '已截止' : '确认选择' }}</van-button>
</div>
<!-- 确认弹窗 (ActionSheet) -->
<!-- 确认弹窗 -->
<van-action-sheet v-model="showConfirmDialog" :close-on-click-overlay="false">
<div class="confirm-action-sheet">
<div class="confirm-sheet-title">确认选择</div>
@@ -682,7 +693,7 @@ layout("/layouts/platform_h5.html"){
</div>
<!-- 提示信息 -->
<div class="confirm-section" v-if="deadlineText || hasSubmittedBefore">
<div class="confirm-section" v-if="deadlineText || hasSubmittedBefore || isDeadlinePassed">
<div class="confirm-section-title">注意事项</div>
<div class="confirm-notice-item" v-if="hasSubmittedBefore">
@@ -690,10 +701,15 @@ layout("/layouts/platform_h5.html"){
<span>{{ confirmMessage }}</span>
</div>
<div class="confirm-notice-item deadline" v-if="deadlineText">
<div class="confirm-notice-item deadline" v-if="deadlineText && !isDeadlinePassed">
<van-icon name="clock-o" />
<span>{{ deadlineText }}</span>
</div>
<div class="confirm-notice-item" style="color: var(--danger-color)" v-if="isDeadlinePassed">
<van-icon name="warning-o" />
<span>选择截止时间已过,无法修改</span>
</div>
</div>
<div class="action-sheet-buttons">
@@ -746,6 +762,17 @@ layout("/layouts/platform_h5.html"){
}
},
isDeadlinePassed() {
if (!this.projectInfo.choiceTimeEnd) return false
const now = new Date()
const deadline = new Date(this.projectInfo.choiceTimeEnd)
return now > deadline
},
submitButtonDisabled() {
return !this.hasSelection || this.isDeadlinePassed
},
selectedOptions() {
if (this.projectInfo.isCheckBox === "radio") {
if (!this.selectedRadioId || !this.projectInfo.options) return []
@@ -863,6 +890,15 @@ layout("/layouts/platform_h5.html"){
// 执行提交
doSubmit() {
// 再次检查截止时间
const now = new Date()
const deadline = new Date(this.projectInfo.choiceTimeEnd)
if (now > deadline) {
this.$toast.fail("已过选择截止时间,无法修改")
this.showConfirmDialog = false
return
}
// 验证手机号
if (!this.validateMobile()) {
return
@@ -978,6 +1014,14 @@ layout("/layouts/platform_h5.html"){
return
}
// 检查是否已过截止时间
const now = new Date()
const deadline = new Date(this.projectInfo.choiceTimeEnd)
if (now > deadline) {
this.$toast.fail("已过选择截止时间,无法修改")
return
}
this.showConfirmDialog = true
},
@@ -987,6 +1031,10 @@ layout("/layouts/platform_h5.html"){
// 单选选项选择
selectRadioOption(optionId) {
if (this.isDeadlinePassed) {
this.$toast.fail("已过选择截止时间,无法修改")
return
}
this.selectedRadioId = optionId
// 重置所有选项的selectNum
@@ -1055,6 +1103,7 @@ layout("/layouts/platform_h5.html"){
deep: true,
handler(options) {
if (!options) return
if (this.isDeadlinePassed) return // 如果已过期,不处理数量变化
const maxSelect = this.projectInfo.multiSelectNum || options.length
const totalCount = options.reduce((sum, option) => sum + (option.selectNum || 0), 0)