场地预约,修复开关按钮报错bug

评优评先优化,增加个人/集体筛选
慰问、特困时间配置写到系统参数
This commit is contained in:
2026-09-14 17:25:01 +08:00
parent 3bd6027670
commit 4288a97bee
25 changed files with 648 additions and 178 deletions
@@ -12,25 +12,20 @@ import com.budwk.app.sys.models.Sys_home_activity;
import com.budwk.app.sys.models.Sys_home_template;
import com.budwk.app.sys.models.Sys_menu;
import com.budwk.app.sys.services.SysMenuService;
import com.budwk.app.sys.services.SysHomeNewsService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
import io.swagger.annotations.ApiOperation;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
@@ -42,9 +37,7 @@ import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@IocBean
@@ -58,7 +51,7 @@ public class SysHomeController {
@Inject
private SysUserService sysUserService;
@Inject
private RedisService redisService;
private SysHomeNewsService sysHomeNewsService;
@Inject
private ActivityBasicScopeService activityBasicScopeService;
@@ -278,38 +271,15 @@ public class SysHomeController {
}
/**
* 无需请求参数;返回 Result,data 为四个板块的 label/value 列表。
* value 中 href 为原文绝对链接,time 为 yyyy-MM-dd 发布日期,text 为完整标题。
*/
@At
@SaCheckLogin
@ApiOperation("获取新闻")
@Ok("json")
// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true)
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
public Result getNews() {
try {
String url = "https://xgh.cug.edu.cn/";
Document document = Jsoup.connect(url).get();
Elements homeElements = document.select(".gh,.jc,.fc,.jg");
List<Map<String, Object>> news = homeElements.stream().map(homeElement -> {
//获取板块名称
String name = homeElement.selectFirst(".title").text();
Elements liElements = homeElement.select("li");
List<NutMap> ele = liElements.stream().map(liElement -> {
NutMap row = NutMap.NEW();
String href = liElement.selectFirst("a").attr("href");
String time = liElement.selectFirst("span").text();
String title = liElement.selectFirst("a").attr("title");
row.put("href", href);
row.put("time", time);
row.put("text", title);
return row;
}).toList();
return Map.of("label", name, "value", ele);
}).collect(Collectors.toList());
redisService.setex("gonghui_news", 60 * 60 * 24, Json.toJson(news));
return Result.success(news);
} catch (IOException e) {
throw new RuntimeException(e);
}
return Result.success(sysHomeNewsService.getNews());
}
}
@@ -0,0 +1,16 @@
package com.budwk.app.sys.services;
import org.nutz.lang.util.NutMap;
import java.util.List;
public interface SysHomeNewsService {
/**
* 获取工会官网首页四个新闻板块,无需传入参数。
* 返回列表按新闻中心、图片新闻、建功立业、民主管理排序;label 为板块名称,
* value 为新闻列表,每条包含 href(原文绝对地址)、time(发布日期 yyyy-MM-dd)、text(完整标题)。
* 官网暂不可用时返回上次成功结果;尚无成功结果时返回四个空板块。
*/
List<NutMap> getNews();
}
@@ -0,0 +1,122 @@
package com.budwk.app.sys.services.impl;
import com.budwk.app.sys.services.SysHomeNewsService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@IocBean
public class SysHomeNewsServiceImpl implements SysHomeNewsService {
private static final Log log = Logs.get();
private static final String BASE_URL = "https://gh.swufe.edu.cn/";
private static final List<String> LABELS = List.of("新闻中心", "图片新闻", "建功立业", "民主管理");
private static final Pattern DATE = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
private static final int REQUEST_TIMEOUT = 5000;
private static final long CACHE_MILLIS = 30 * 60 * 1000L;
private static final long RETRY_MILLIS = 60 * 1000L;
// 仅缓存官网读取结果,不写业务库;失败时保留上次完整结果,防止临时网络故障清空首页。
private List<NutMap> cachedNews = emptySections();
private long nextRefreshTime;
/**
* 无入参,返回 label/value 板块列表,新闻字段为 href/time/text,含义见接口说明。
* 同步刷新避免并发访问重复抓取;成功缓存 30 分钟,失败后至少间隔 1 分钟再尝试。
*/
@Override
public synchronized List<NutMap> getNews() {
if (System.currentTimeMillis() < nextRefreshTime) {
return cachedNews;
}
try {
cachedNews = fetchNews();
nextRefreshTime = System.currentTimeMillis() + CACHE_MILLIS;
} catch (IOException | IllegalArgumentException e) {
nextRefreshTime = System.currentTimeMillis() + RETRY_MILLIS;
log.warn("工会官网新闻拉取失败,保留上次成功结果", e);
}
return cachedNews;
}
/** 按板块标题定位容器,官网存在重复组件 ID,不能直接用 ID 区分建功立业和基层动态。 */
private List<NutMap> fetchNews() throws IOException {
Document document = loadDocument(BASE_URL);
List<NutMap> sections = new ArrayList<>();
for (String label : LABELS) {
Element heading = document.select(".in-title > span").stream()
.filter(element -> label.equals(element.text().trim()))
.findFirst().orElse(null);
if (heading == null || heading.parent() == null || heading.parent().parent() == null) {
throw new IOException("工会官网缺少板块:" + label);
}
List<NutMap> rows = new ArrayList<>();
for (Element anchor : heading.parent().parent().select("li a[href]")) {
String href = anchor.absUrl("href");
String title = anchor.attr("title").trim();
if (title.isEmpty()) {
Element titleElement = anchor.clone();
titleElement.select("span").remove();
title = titleElement.text().trim();
}
if (title.isEmpty() || href.isEmpty()) {
throw new IOException("工会官网新闻缺少标题或链接:" + label);
}
String date;
if ("图片新闻".equals(label)) {
// 首页图片轮播不含日期,只读取详情中的“发布日期”,避免误用标题中的年份。
Document detail = loadDocument(href);
Element published = detail.select("p").stream()
.filter(element -> element.text().trim().startsWith("发布日期"))
.findFirst().orElse(null);
date = published == null ? "" : findDate(published.text());
} else {
date = findDate(anchor.select("span").text());
}
if (date.isEmpty()) {
throw new IOException("工会官网新闻缺少发布日期:" + href);
}
rows.add(NutMap.NEW().setv("href", href).setv("time", date).setv("text", title));
}
if (rows.isEmpty()) {
throw new IOException("工会官网板块无可用新闻:" + label);
}
sections.add(NutMap.NEW().setv("label", label).setv("value", rows));
}
return sections;
}
/** 请求固定工会站点的公开页面,限制超时且不跟随重定向,避免官网异常拖住首页请求。 */
private Document loadDocument(String url) throws IOException {
URI uri = URI.create(url);
if (!"https".equalsIgnoreCase(uri.getScheme()) || !"gh.swufe.edu.cn".equalsIgnoreCase(uri.getHost())) {
throw new IOException("工会官网返回了非本站 HTTPS 链接:" + url);
}
return Jsoup.connect(url).timeout(REQUEST_TIMEOUT).followRedirects(false).get();
}
/** 将官网方括号日期或发布日期文字统一为 yyyy-MM-dd;无日期时由调用方按抓取失败处理。 */
private String findDate(String text) {
Matcher matcher = DATE.matcher(text);
return matcher.find() ? matcher.group() : "";
}
/** 首次抓取失败时仍保留四个板块的顺序与名称,不用虚构新闻或日期填充。 */
private static List<NutMap> emptySections() {
List<NutMap> sections = new ArrayList<>();
for (String label : LABELS) {
sections.add(NutMap.NEW().setv("label", label).setv("value", List.of()));
}
return sections;
}
}
@@ -10,7 +10,7 @@ import cn.hutool.core.lang.tree.TreeUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
@@ -21,8 +21,6 @@ import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
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.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -46,7 +44,7 @@ public class EvaluateActivityController {
private Dao dao;
@Inject
private BaseService baseService;
private EvaluateActivityService evaluateActivityService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/evaluation/activity/index.html")
@@ -55,27 +53,19 @@ public class EvaluateActivityController {
}
/**
* 按组合条件获取活动分页数据。
* @param pageForm 分页参数,pageNumber 为页码,pageSize 为每页条数
* @param year 年度,未传时不限制年度
* @param searchKeyword 活动名称关键字,空值时不限制名称
* @param honorTypeId 个人或集体荣誉的分类 ID,空值表示全部荣誉类型
* @return Result,data 为分页对象,其中 list 为活动记录,totalCount 为符合条件的总条数
*/
@At
@SaCheckPermission("evaluation.activity")
@ApiOperation("获取评优评先活动列表")
public Result pageData(@Valid PageForm pageForm, Integer year, String searchKeyword) {
Sql sql = Sqls.create("""
SELECT
eva.*,
hb.NAME AS honorName,
bs.name as honorTypeName,
( SELECT groupName FROM activity_user_scope au WHERE au.groupId = eva.activityGroupId LIMIT 1 ) AS groupName
FROM
`evaluate_activity` eva
LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("year", "=", year);
cnd.and(Cnd.likeEX("eva.name", searchKeyword));
sql.setCondition(cnd);
return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
public Result pageData(@Valid PageForm pageForm, Integer year, String searchKeyword, String honorTypeId) {
return Result.success(evaluateActivityService.queryActivityPage(pageForm, year, searchKeyword, honorTypeId));
}
@At
@@ -150,12 +140,16 @@ public class EvaluateActivityController {
return Result.success();
}
/**
* @param year 活动年度,空值不限制
* @param honorTypeId 荣誉分类 ID,空值表示全部分类
* @return Result,data 为事项列表,id 为选项值,name 为选项名称
*/
@At
@SaCheckLogin
@ApiOperation("根据年查询荣誉申请事项")
public Result listEvaluateActivityByYear(Integer year) {
List<EvaluateActivity> list = dao.query(EvaluateActivity.class, Cnd.NEW().andEX(EvaluateActivity::getYear,"=",year));
return Result.success(list);
@ApiOperation("根据年度和荣誉类型查询申请事项")
public Result listEvaluateActivityByYear(Integer year, String honorTypeId) {
return Result.success(evaluateActivityService.listActivityOptions(year, honorTypeId));
}
}
@@ -3,8 +3,7 @@ package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.Dict;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowEngine;
@@ -21,10 +20,7 @@ import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
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.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -59,34 +55,16 @@ public class EvaluateApplyController {
public void index() {
}
/**
* 按年度和荣誉类型查询可申请活动。
* @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为分类 ID;年度、分类为空时不限制
* @return Result,data.list 为记录列表,data.totalCount 为符合条件的总条数
*/
@At
@SaCheckPermission("evaluation.apply")
@ApiOperation("获取评优评先活动列表")
public Result pageData(@Valid PageForm pageForm, Integer year) {
Sql sql = Sqls.create("""
SELECT
eva.id,
eva.honorId,
eva.honorTypeId,
eva.name,
eva.startTime,
eva.endTime,
eva.enable,
eva.year,
hb.NAME AS honorName,
bs.name as honorTypeName
FROM
evaluate_activity eva
LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("enable", "=", 1);
cnd.andEX("year", "=", year);
sql.setCondition(cnd);
Pagination pagination = evaluateActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
public Result pageData(@Valid EvaluatePageForm pageForm) {
return Result.success(evaluateActivityService.listApplyPage(pageForm));
}
@At
@@ -1,6 +1,8 @@
package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService;
import cn.hutool.core.bean.BeanUtil;
import com.budwk.app.base.constant.BpmProcessConstant;
import com.budwk.app.base.result.Result;
@@ -25,6 +27,8 @@ public class EvaluateCommonController {
@Inject
private EvaluateService evaluateService;
@Inject
private EvaluateActivityService evaluateActivityService;
@Inject
private BpmService bpmService;
@At
@@ -34,4 +38,18 @@ public class EvaluateCommonController {
EvaluateApply evaluateApply = evaluateService.fetch(id);
return Result.success(evaluateApply);
}
/**
* 为评优评先各角色提供荣誉类型下拉选项,无需活动管理权限。
* @return Result,data 为分类列表,id 为分类 ID,name 为个人或集体荣誉名称
*/
@At
@SaCheckPermission(value = {"evaluation.activity", "evaluation.apply", "evaluation.mine",
"evaluation.unitApproval", "evaluation.branchUnionApproval", "evaluation.partyOrganizationApproval",
"evaluation.schoolUnionApproval", "evaluation.summary"}, mode = SaMode.OR)
@ApiOperation("查询评优评先荣誉类型选项")
public Result honorTypes() {
return Result.success(evaluateActivityService.listHonorTypes());
}
}
@@ -2,18 +2,14 @@ package com.budwk.app.zhgh.dayofficework.evaluation.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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;
@@ -40,50 +36,15 @@ public class EvaluateMineController {
public void index() {
}
/**
* 按年度和荣誉类型查询当前用户的申请记录。
* @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为分类 ID;年度、分类为空时不限制
* @return Result,data.list 为记录列表,data.totalCount 为符合条件的总条数
*/
@At
@SaCheckPermission("evaluation.mine")
public Result pageData(@Valid PageForm pageForm, Integer year) {
Sql sql = Sqls.create("""
SELECT
info.*,
ea.name AS evaluateName,
hb.name AS honorName,
bs.name as honorTypeName,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable taskVariable,
IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke,
(SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask' AND taskState IN (10, 20)) AS startTaskId
FROM
evaluate_apply info
LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId
LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id
AND t.taskState = 10
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("YEAR(info.year)", "=", year);
cnd.and("info.loginName", "=", SecurityUtil.getUserLoginname());
cnd.desc("info.createdAt");
sql.setCondition(cnd);
Pagination pagination = evaluateService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
public Result pageData(@Valid EvaluatePageForm pageForm) {
return Result.success(evaluateService.listMinePage(pageForm));
}
@At
@@ -66,7 +66,8 @@ public class EvaluateSummaryController {
@SaCheckPermission("evaluation.summary")
@ApiOperation("导出评优评先活动列表")
public void exportExcel(@Valid EvaluatePageForm pageForm, HttpServletResponse response) {
EvaluateActivity activity = evaluateService.dao().fetch(EvaluateActivity.class, pageForm.getEvaluateId());
EvaluateActivity activity = org.nutz.lang.Strings.isBlank(pageForm.getEvaluateId()) ? null
: evaluateService.dao().fetch(EvaluateActivity.class, pageForm.getEvaluateId());
Sql sql = evaluateService.getSummarySql(pageForm);
List<NutMap> list = baseService.listMap(sql);
for (int i = 0; i < list.size(); i++) {
@@ -88,7 +89,9 @@ public class EvaluateSummaryController {
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
CommonDownloadUtil.download(activity.getName() + "人员列表.xlsx", workbook, response);
// 全部事项或当前分类下无事项时使用通用名称,避免空事项导致导出失败。
String fileName = activity == null ? "评优评先人员列表.xlsx" : activity.getName() + "人员列表.xlsx";
CommonDownloadUtil.download(fileName, workbook, response);
} catch (Exception ignored) {
}
}
@@ -1,7 +1,43 @@
package com.budwk.app.zhgh.dayofficework.evaluation.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import com.budwk.app.zhgh.dayofficework.honor.models.HonorBasicSettings;
import java.util.List;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
public interface EvaluateActivityService extends BaseService<EvaluateActivity> {
/**
* 按年度、名称和荣誉类型组合查询活动。
* @param pageForm 分页参数,包含页码 pageNumber 和每页条数 pageSize
* @param year 年度,空值时不限制
* @param searchKeyword 活动名称关键字,空值时不限制
* @param honorTypeId 荣誉分类 ID,空值表示全部个人和集体荣誉
* @return 分页对象,list 为包含荣誉名称、类型名称及人员范围名称的活动记录,totalCount 为总条数
*/
Pagination queryActivityPage(PageForm pageForm, Integer year, String searchKeyword, String honorTypeId);
/**
* 查询已启用的可申请活动。
* @param pageForm pageNumber/pageSize 为页码和每页条数,year 为年度,honorTypeId 为分类 ID;空筛选不限制
* @return 分页对象,list 为活动及荣誉名称,totalCount 为总条数
*/
Pagination listApplyPage(EvaluatePageForm pageForm);
/**
* 查询评优评先一级荣誉分类,供各列表页面选择个人或集体荣誉。
* @return 分类列表,id 为查询使用的分类 ID,name 为显示名称;未配置根分类时返回空列表
*/
List<HonorBasicSettings> listHonorTypes();
/**
* 按查询条件提供事项下拉选项。
* @param year 活动年度,空值不限制
* @param honorTypeId 荣誉分类 ID,空值表示全部
* @return 活动列表,id 为事项值,name 为事项名称
*/
List<EvaluateActivity> listActivityOptions(Integer year, String honorTypeId);
}
@@ -29,4 +29,12 @@ public interface EvaluateService extends BaseService<EvaluateApply> {
* @return 流程决策节点使用的路线参数值
*/
String getApprovalRoute(String unionId);
/**
* 查询当前登录用户的申请记录,保留原有流程信息和排序。
* @param pageForm pageNumber/pageSize 为分页参数,year 为年度,honorTypeId 为荣誉分类 ID;空筛选不限制
* @return 分页对象,list 为申请及流程信息,totalCount 为总条数
*/
Pagination listMinePage(EvaluatePageForm pageForm);
}
@@ -1,9 +1,18 @@
package com.budwk.app.zhgh.dayofficework.evaluation.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.zhgh.dayofficework.evaluation.vo.EvaluatePageForm;
import com.budwk.app.zhgh.dayofficework.evaluation.constant.EvaluateConstant;
import com.budwk.app.zhgh.dayofficework.honor.models.HonorBasicSettings;
import java.util.List;
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
import com.budwk.app.zhgh.dayofficework.evaluation.service.EvaluateActivityService;
import org.nutz.dao.Dao;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean(args = {"refer:dao"})
@@ -12,4 +21,78 @@ public class EvaluateActivityServiceImpl extends BaseServiceImpl<EvaluateActivit
public EvaluateActivityServiceImpl(Dao dao) {
super(dao);
}
/** {@inheritDoc} */
@Override
public Pagination queryActivityPage(PageForm pageForm, Integer year, String searchKeyword, String honorTypeId) {
Sql sql = Sqls.create("""
SELECT
eva.*,
hb.NAME AS honorName,
bs.name as honorTypeName,
( SELECT groupName FROM activity_user_scope au WHERE au.groupId = eva.activityGroupId LIMIT 1 ) AS groupName
FROM
`evaluate_activity` eva
LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("eva.year", "=", year);
cnd.and(Cnd.likeEX("eva.name", searchKeyword));
// 全部或旧调用未传分类 ID 时不增加限制,选中分类时按活动的荣誉类型精确匹配。
cnd.andEX("eva.honorTypeId", "=", honorTypeId);
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/** {@inheritDoc} */
@Override
public Pagination listApplyPage(EvaluatePageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
eva.id,
eva.honorId,
eva.honorTypeId,
eva.name,
eva.startTime,
eva.endTime,
eva.enable,
eva.year,
hb.NAME AS honorName,
bs.name as honorTypeName
FROM
evaluate_activity eva
LEFT JOIN honor_basic_settings hb ON hb.id = eva.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = eva.honorTypeId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("enable", "=", 1);
cnd.andEX("year", "=", pageForm.getYear());
// 空分类表示全部;选中分类时按当前记录的荣誉类型精确过滤。
cnd.andEX("eva.honorTypeId", "=", pageForm.getHonorTypeId());
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/** {@inheritDoc} */
@Override
public List<HonorBasicSettings> listHonorTypes() {
HonorBasicSettings parent = dao().fetch(HonorBasicSettings.class,
Cnd.where("code", "=", EvaluateConstant.HONOR_TYPE_CODE));
// 根分类未配置时不查询其他业务分类,页面仍可使用“全部”查询。
if (parent == null) {
return List.of();
}
return dao().query(HonorBasicSettings.class, Cnd.where("parentId", "=", parent.getId()).asc("code"));
}
/** {@inheritDoc} */
@Override
public List<EvaluateActivity> listActivityOptions(Integer year, String honorTypeId) {
return query(Cnd.NEW().andEX("year", "=", year).andEX("honorTypeId", "=", honorTypeId));
}
}
@@ -65,6 +65,8 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
Cnd cnd = Cnd.NEW();
cnd.andEX("YEAR(info.applyDateTime)", "=", pageForm.getYear());
cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId());
// 分类条件同时用于审核列表、统计列表及统计导出,空值时不限制。
cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId());
cnd.and("ins.state", "=", ProcessTaskStateEnum.FINISHED.getCode());
cnd.andEX("info.unitId", "=", pageForm.getUnitId());
cnd.andEX("info.unionId", "=", pageForm.getUnionId());
@@ -126,6 +128,8 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
cnd.and("t.taskName", "=", taskKey);
cnd.and("ta.actorId", "=", SecurityUtil.getUserId());
cnd.andEX("info.evaluateId", "=", pageForm.getEvaluateId());
// 分类条件同时用于审核列表、统计列表及统计导出,空值时不限制。
cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId());
cnd.andEX("info.unionId", "=", pageForm.getUnionId());
cnd.andEX("info.unitId", "=", pageForm.getUnitId());
@@ -171,4 +175,51 @@ public class EvaluateServiceImpl extends BaseServiceImpl<EvaluateApply> implemen
? EvaluateConstant.UNIT_APPROVAL_ROUTE
: EvaluateConstant.BRANCH_UNION_APPROVAL_ROUTE;
}
/** {@inheritDoc} */
@Override
public Pagination listMinePage(EvaluatePageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
info.*,
ea.name AS evaluateName,
hb.name AS honorName,
bs.name as honorTypeName,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable taskVariable,
IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke,
(SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask' AND taskState IN (10, 20)) AS startTaskId
FROM
evaluate_apply info
LEFT JOIN evaluate_activity ea ON ea.id = info.evaluateId
LEFT JOIN honor_basic_settings hb ON hb.id = info.honorId
LEFT JOIN honor_basic_settings bs ON bs.id = info.honorTypeId
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id
AND t.taskState = 10
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("YEAR(info.year)", "=", pageForm.getYear());
cnd.and("info.loginName", "=", SecurityUtil.getUserLoginname());
cnd.desc("info.createdAt");
// 空分类表示全部;选中分类时按当前记录的荣誉类型精确过滤。
cnd.andEX("info.honorTypeId", "=", pageForm.getHonorTypeId());
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
}
@@ -11,6 +11,10 @@ import lombok.EqualsAndHashCode;
@Data
public class EvaluatePageForm extends PageForm {
/** 个人或集体荣誉的分类 ID,空值表示全部荣誉类型。 */
@ApiModelProperty("荣誉类型ID,空值表示全部")
private String honorTypeId;
@ApiModelProperty("年度")
private Integer year;
@@ -15,6 +15,8 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.dao.Dao;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
@@ -76,11 +78,32 @@ public class SiteCugManageController {
return Result.success(pagination);
}
/**
* 仅切换场地开关:id 为已有场地 ID,state 为 true(开启)或 false(禁用)。
* 返回 Result,code=0 表示成功,data 为保存后的 Boolean 状态;参数无效返回错误消息。
*/
@At
@ApiOperation("切换场地开启状态")
@SaCheckPermission("siteCug.manage")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "siteCug.manage", msg = "切换场地开启状态")
public Result updateState(@Param("id") String id, @Param("state") Boolean state) {
if (StrUtil.isBlank(id) || state == null) {
return Result.error("场地ID和开启状态不能为空");
}
return Result.success(infoService.updateState(id, state));
}
@At
@ApiOperation("submit")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("siteCug.manage")
@SLog(tag = "siteCug.manage", msg = "submit site")
public Object submit(@Param("data") SiteCugInfo info) {
// 完整表单必须通过 data 参数提交;缺失时返回业务提示,避免空指针异常。
if (info == null) {
return Result.error("场地信息不能为空,请通过data参数提交完整表单");
}
List<NutMap> notApplyTimeList = info.getNotApplyTimeList();
if (notApplyTimeList != null) {
boolean invalid = notApplyTimeList.stream().anyMatch(item ->
@@ -4,4 +4,11 @@ import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugInfo;
public interface SiteCugInfoService extends BaseService<SiteCugInfo> {
/**
* 切换已有场地的开启状态,不改动开放时段及预约限制。
* @param id 场地业务 ID,不允许为空
* @param state true 开启,false 禁用,不允许为 null
* @return 保存后的开启状态;场地不存在或已删除时抛出业务异常
*/
boolean updateState(String id, Boolean state);
}
@@ -1,10 +1,17 @@
package com.budwk.app.zhgh.dayofficework.siteCug.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugInfo;
import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugInfoService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Dao;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.ioc.aop.Aop;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.loader.annotation.IocBean;
@Slf4j
@@ -14,4 +21,23 @@ public class SiteCugInfoServiceImpl extends BaseServiceImpl<SiteCugInfo> impleme
public SiteCugInfoServiceImpl(Dao dao) {
super(dao);
}
/** {@inheritDoc} */
@Override
@Aop(TransAop.READ_COMMITTED)
public boolean updateState(String id, Boolean state) {
if (StrUtil.isBlank(id) || state == null) {
throw new BaseException("场地ID和开启状态不能为空");
}
SiteCugInfo info = fetch(id);
if (info == null || Boolean.TRUE.equals(info.getDelFlag())) {
throw new BaseException("场地不存在或已删除");
}
// 只写状态及审计字段,缺少开放时段的历史场地也能关闭,且不会覆盖其他配置。
update(Chain.make("state", state)
.add("updatedBy", SecurityUtil.getUserId())
.add("updatedAt", System.currentTimeMillis()),
Cnd.where("id", "=", id));
return state;
}
}
@@ -164,11 +164,14 @@ layout("/layouts/v4/baseLayout.html"){
this.getWebSiteNews()
},
methods: {
// 无请求参数;data 为四个新闻板块,沿用 label/value 及 href/time/text 展示结构。
getWebSiteNews(){
this.$axios.post('/platform/home/getNews').then(res => {
if (res.code === 0) {
this.websiteNews = res.data
this.$set(this, 'websiteNews', res.data)
}
}).catch(() => {
this.$message.error('获取工会新闻失败,请稍后重试')
})
}
}
@@ -26,6 +26,7 @@ const jcdt = {
</el-carousel-item>
</el-carousel>
</div>
<slot></slot>
</div>
`,
data() {
@@ -39,11 +40,10 @@ const jcdt = {
},
methods: {
onLink(item) {
const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href
window.open(url)
},
isHttpOrHttps(url) {
return /^(http:\/\/|https:\/\/)/i.test(url)
// service 返回工会官网原文绝对地址,仅允许本站 HTTPS 新闻在新窗口打开。
if (item.href && /^https:\/\/gh\.swufe\.edu\.cn\//i.test(item.href)) {
window.open(item.href, '_blank', 'noopener')
}
}
},
style: /*language=CSS*/ `
@@ -8,6 +8,13 @@ layout("/layouts/platform.html"){
<search-item label="年度">
<el-date-picker placeholder="请选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
</search-item>
<!-- 荣誉类型使用现有分类 ID;全部对应空值,不限制个人或集体荣誉。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="名称">
<el-input placeholder="请输入评优评先名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
</search-item>
@@ -299,6 +306,8 @@ layout("/layouts/platform.html"){
}
},
created() {
// 默认查询全部荣誉类型,与年度、名称共同参与现有分页查询。
this.$set(this.pageForm, "honorTypeId", "")
this.$set(this.pageForm, "year", new Date().getFullYear().toString())
this.listHonorType()
this.getActivityGroup()
@@ -11,6 +11,13 @@ layout("/layouts/platform.html"){
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="选择年度"
style="width: 100%"></el-date-picker>
</search-item>
<!-- 荣誉分类为空时查询全部,分类 ID 与后端荣誉类型字段对应。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%" :loading="honorTypeLoading">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorTypeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
@@ -46,19 +53,34 @@ layout("/layouts/platform.html"){
<script nonce="${cspNonce!}">
<!--#include('apply.js'){}#-->
<!--#include('../common/info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
apply_form: apply_component
apply_form: apply_component,
info
},
data() {
return {
honorTypeOptions: [],
honorTypeLoading: false,
}
},
methods: {
// 分类选项使用模块公共接口,普通申请人和审核人无需活动管理权限。
loadHonorTypes() {
this.honorTypeLoading = true
this.$axios.post("/platform/evaluate/common/honorTypes").then((res) => {
if (res.code === 0) {
this.honorTypeOptions = res.data
}
}).finally(() => {
this.honorTypeLoading = false
})
},
openApply(row) {
if(this.$moment().isAfter(this.$moment(row.endTime))) {
this.$message.warning('申请时间已截止')
@@ -79,7 +101,9 @@ layout("/layouts/platform.html"){
})
}
},
async created() {
created() {
this.$set(this.pageForm, "honorTypeId", "")
this.loadHonorTypes()
this.pageData()
}
})
@@ -10,6 +10,13 @@ layout("/layouts/platform.html"){
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy"
placeholder="选择年度" @change="listEvaluate"></el-date-picker>
</search-item>
<!-- 荣誉分类为空时查询全部,分类 ID 与后端荣誉类型字段对应。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%" :loading="honorTypeLoading" @change="honorTypeChange">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorTypeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
@@ -105,6 +112,8 @@ layout("/layouts/platform.html"){
},
data() {
return {
honorTypeOptions: [],
honorTypeLoading: false,
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName",
@@ -117,6 +126,21 @@ layout("/layouts/platform.html"){
}
},
methods: {
// 分类选项使用模块公共接口,普通申请人和审核人无需活动管理权限。
loadHonorTypes() {
this.honorTypeLoading = true
this.$axios.post("/platform/evaluate/common/honorTypes").then((res) => {
if (res.code === 0) {
this.honorTypeOptions = res.data
}
}).finally(() => {
this.honorTypeLoading = false
})
},
// 切换荣誉类型后清除旧事项,查询该类型全部事项,避免旧事项与新类型冲突。
honorTypeChange() {
this.listEvaluate(false)
},
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.infoRef.onOpen(row)
@@ -171,20 +195,26 @@ layout("/layouts/platform.html"){
})
})
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
// selectFirst 为 false 表示类型切换;其他调用保持页面原有事项默认选择。
listEvaluate(selectFirst = true) {
this.$set(this.pageForm, "evaluateId", "")
this.evaluateList = []
const query = {year: this.pageForm.year, honorTypeId: this.pageForm.honorTypeId}
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", query).then((resp) => {
// 快速切换年度或类型时丢弃旧条件响应,避免覆盖当前事项选项。
if (query.year !== this.pageForm.year || query.honorTypeId !== this.pageForm.honorTypeId) {
return
}
if (resp.code === 0) {
this.evaluateList = resp.data
if (resp.data.length > 0) {
// this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
this.doSearch()
}
})
},
},
async created() {
created() {
this.$set(this.pageForm, "honorTypeId", "")
this.loadHonorTypes()
this.listEvaluate()
}
})
@@ -10,6 +10,13 @@ layout("/layouts/platform.html"){
<el-date-picker v-model="pageForm.year" type="year" placeholder="选择年度"
value-format="yyyy"></el-date-picker>
</search-item>
<!-- 荣誉分类为空时查询全部,分类 ID 与后端荣誉类型字段对应。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%" :loading="honorTypeLoading">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorTypeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
@@ -72,9 +79,20 @@ layout("/layouts/platform.html"){
info
},
data() {
return {}
return { honorTypeOptions: [], honorTypeLoading: false }
},
methods: {
// 分类选项使用模块公共接口,普通申请人和审核人无需活动管理权限。
loadHonorTypes() {
this.honorTypeLoading = true
this.$axios.post("/platform/evaluate/common/honorTypes").then((res) => {
if (res.code === 0) {
this.honorTypeOptions = res.data
}
}).finally(() => {
this.honorTypeLoading = false
})
},
refresh() {
this.$refs.guava.index()
this.pageData()
@@ -120,6 +138,8 @@ layout("/layouts/platform.html"){
},
},
created() {
this.$set(this.pageForm, "honorTypeId", "")
this.loadHonorTypes()
this.pageData()
}
})
@@ -9,6 +9,13 @@ layout("/layouts/platform.html"){
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="选择年度"@change="listEvaluate"></el-date-picker>
</search-item>
<!-- 荣誉分类为空时查询全部,分类 ID 与后端荣誉类型字段对应。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%" :loading="honorTypeLoading" @change="honorTypeChange">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorTypeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
@@ -113,6 +120,8 @@ layout("/layouts/platform.html"){
},
data() {
return {
honorTypeOptions: [],
honorTypeLoading: false,
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName",
@@ -125,6 +134,21 @@ layout("/layouts/platform.html"){
}
},
methods: {
// 分类选项使用模块公共接口,普通申请人和审核人无需活动管理权限。
loadHonorTypes() {
this.honorTypeLoading = true
this.$axios.post("/platform/evaluate/common/honorTypes").then((res) => {
if (res.code === 0) {
this.honorTypeOptions = res.data
}
}).finally(() => {
this.honorTypeLoading = false
})
},
// 切换荣誉类型后清除旧事项,查询该类型全部事项,避免旧事项与新类型冲突。
honorTypeChange() {
this.listEvaluate(false)
},
openView(row) {
this.$refs.guava.edit(() => {
this.$refs.infoRef.onOpen(row)
@@ -178,20 +202,30 @@ layout("/layouts/platform.html"){
})
})
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
// selectFirst 为 false 表示类型切换;其他调用保持页面原有事项默认选择。
listEvaluate(selectFirst = true) {
this.$set(this.pageForm, "evaluateId", "")
this.evaluateList = []
const query = {year: this.pageForm.year, honorTypeId: this.pageForm.honorTypeId}
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", query).then((resp) => {
// 快速切换年度或类型时丢弃旧条件响应,避免覆盖当前事项选项。
if (query.year !== this.pageForm.year || query.honorTypeId !== this.pageForm.honorTypeId) {
return
}
if (resp.code === 0) {
this.evaluateList = resp.data
if (resp.data.length > 0) {
// 年度切换和首次进入保留默认选中首个事项的原有行为。
if (selectFirst !== false && resp.data.length > 0) {
this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
this.doSearch()
}
})
},
},
async created() {
this.$set(this.pageForm, "honorTypeId", "")
this.loadHonorTypes()
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.listEvaluate()
@@ -16,6 +16,13 @@ layout("/layouts/platform.html"){
@change="listEvaluate()"
></el-date-picker>
</search-item>
<!-- 荣誉分类为空时查询全部,分类 ID 与后端荣誉类型字段对应。 -->
<search-item label="荣誉类型">
<el-select v-model="pageForm.honorTypeId" placeholder="全部" style="width: 100%" :loading="honorTypeLoading" @change="honorTypeChange">
<el-option label="全部" value=""></el-option>
<el-option v-for="item in honorTypeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="事项">
<el-select v-model="pageForm.evaluateId" placeholder="请选择评优评先事项" filterable clearable
style="width: 100%">
@@ -89,6 +96,8 @@ layout("/layouts/platform.html"){
},
data() {
return {
honorTypeOptions: [],
honorTypeLoading: false,
pageForm: {
year: new Date().getFullYear() + "",
searchName: "info.userName"
@@ -99,6 +108,21 @@ layout("/layouts/platform.html"){
}
},
methods: {
// 分类选项使用模块公共接口,普通申请人和审核人无需活动管理权限。
loadHonorTypes() {
this.honorTypeLoading = true
this.$axios.post("/platform/evaluate/common/honorTypes").then((res) => {
if (res.code === 0) {
this.honorTypeOptions = res.data
}
}).finally(() => {
this.honorTypeLoading = false
})
},
// 切换荣誉类型后清除旧事项,查询该类型全部事项,避免旧事项与新类型冲突。
honorTypeChange() {
this.listEvaluate(false)
},
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
@@ -119,20 +143,30 @@ layout("/layouts/platform.html"){
this.doSearch()
}
},
listEvaluate() {
this.$set(this.pageForm, "evaluateId","")
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", {year: this.pageForm.year}).then(resp => {
if (resp.code===0){
// selectFirst 为 false 表示类型切换;其他调用保持页面原有事项默认选择。
listEvaluate(selectFirst = true) {
this.$set(this.pageForm, "evaluateId", "")
this.evaluateList = []
const query = {year: this.pageForm.year, honorTypeId: this.pageForm.honorTypeId}
this.$axios.post("/platform/evaluate/activity/listEvaluateActivityByYear", query).then((resp) => {
// 快速切换年度或类型时丢弃旧条件响应,避免覆盖当前事项选项。
if (query.year !== this.pageForm.year || query.honorTypeId !== this.pageForm.honorTypeId) {
return
}
if (resp.code === 0) {
this.evaluateList = resp.data
if (resp.data.length > 0) {
// 年度切换和首次进入保留默认选中首个事项的原有行为。
if (selectFirst !== false && resp.data.length > 0) {
this.$set(this.pageForm, "evaluateId", resp.data[0].id)
}
this.pageData()
this.doSearch()
}
})
},
},
async created() {
this.$set(this.pageForm, "honorTypeId", "")
this.loadHonorTypes()
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.listEvaluate()
@@ -52,6 +52,7 @@ layout("/layouts/platform.html"){
<template v-slot="{ row }" v-if="column.prop === 'state'">
<el-switch
@change="switchChange(row)"
:disabled="!!stateLoading[row.id]"
v-model="row.state"
active-color="#13ce66"
inactive-color="#ff4949">
@@ -101,6 +102,7 @@ layout("/layouts/platform.html"){
data() {
return {
typeOptions: [],
stateLoading: {},
tableColumns: [
{prop: 'createUserName', label: '创建人', sortable: 'custom'},
{prop: 'name', label: '场地名称', sortable: 'custom'},
@@ -152,12 +154,26 @@ layout("/layouts/platform.html"){
.catch(() => {})
},
switchChange(row) {
this.$axios.post("/platform/siteCug/manage/submit", row).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
// v-model 已先切换状态;保存失败时恢复原值,每条场地独立防止重复提交。
if (this.stateLoading[row.id]) return
const previousState = !row.state
this.$set(this.stateLoading, row.id, true)
this.$axios.post("/platform/siteCug/manage/updateState", {id: row.id, state: row.state})
.then((res) => {
if (res.code === 0) {
this.$set(row, 'state', res.data)
this.$message.success('场地状态更新成功')
} else {
this.$set(row, 'state', previousState)
}
})
.catch(() => {
// 请求异常由全局拦截器提示,此处只恢复开关,避免界面与数据库状态不一致。
this.$set(row, 'state', previousState)
})
.finally(() => {
this.$set(this.stateLoading, row.id, false)
})
},
querySiteType() {
this.$axios.post("/platform/siteCug/function/type/queryFunctionType").then((res) => {