场地预约整改
This commit is contained in:
@@ -5,32 +5,26 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.useragent.UserAgent;
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
import cn.hutool.http.useragent.UserAgentUtil;
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.sys.models.Sys_home_activity;
|
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_home_template;
|
||||||
import com.budwk.app.sys.models.Sys_menu;
|
import com.budwk.app.sys.models.Sys_menu;
|
||||||
|
import com.budwk.app.sys.services.SysHomeNewsService;
|
||||||
import com.budwk.app.sys.services.SysMenuService;
|
import com.budwk.app.sys.services.SysMenuService;
|
||||||
import com.budwk.app.sys.services.SysUserService;
|
import com.budwk.app.sys.services.SysUserService;
|
||||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||||
import io.swagger.annotations.ApiOperation;
|
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.Cnd;
|
||||||
import org.nutz.dao.Dao;
|
import org.nutz.dao.Dao;
|
||||||
import org.nutz.dao.FieldFilter;
|
import org.nutz.dao.FieldFilter;
|
||||||
import org.nutz.dao.Sqls;
|
import org.nutz.dao.Sqls;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
import org.nutz.dao.util.Daos;
|
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.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.json.Json;
|
|
||||||
import org.nutz.lang.Lang;
|
import org.nutz.lang.Lang;
|
||||||
import org.nutz.lang.Strings;
|
import org.nutz.lang.Strings;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
@@ -42,9 +36,7 @@ import org.nutz.mvc.annotation.Param;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
|
|
||||||
@IocBean
|
@IocBean
|
||||||
@@ -58,7 +50,7 @@ public class SysHomeController {
|
|||||||
@Inject
|
@Inject
|
||||||
private SysUserService sysUserService;
|
private SysUserService sysUserService;
|
||||||
@Inject
|
@Inject
|
||||||
private RedisService redisService;
|
private SysHomeNewsService sysHomeNewsService;
|
||||||
@Inject
|
@Inject
|
||||||
private ActivityBasicScopeService activityBasicScopeService;
|
private ActivityBasicScopeService activityBasicScopeService;
|
||||||
|
|
||||||
@@ -285,31 +277,11 @@ public class SysHomeController {
|
|||||||
// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true)
|
// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true)
|
||||||
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
|
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
|
||||||
public Result getNews() {
|
public Result getNews() {
|
||||||
try {
|
try {
|
||||||
String url = "https://xgh.cug.edu.cn/";
|
return Result.success(sysHomeNewsService.getUnionNoticeNews());
|
||||||
Document document = Jsoup.connect(url).get();
|
} catch (Exception e) {
|
||||||
Elements homeElements = document.select(".gh,.jc,.fc,.jg");
|
log.error(e);
|
||||||
|
return Result.success();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.budwk.app.sys.services;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface SysHomeNewsService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取江苏农牧科技职业学院工会网站通知公告,并保持首页新闻组件需要的数据结构。
|
||||||
|
*
|
||||||
|
* @return 首页网站新闻数据,当前使用 grassroots 字段兼容前端组件
|
||||||
|
*/
|
||||||
|
JSONObject getUnionNoticeNews() throws IOException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.budwk.app.sys.services.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.budwk.app.sys.services.SysHomeNewsService;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
public class SysHomeNewsServiceImpl implements SysHomeNewsService {
|
||||||
|
|
||||||
|
private static final String UNION_HOME_URL = "https://www.jsahvc.edu.cn/gh/main.htm";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject getUnionNoticeNews() throws IOException {
|
||||||
|
JSONObject root = new JSONObject();
|
||||||
|
List<JSONObject> noticeList = new ArrayList<>();
|
||||||
|
|
||||||
|
Document doc = Jsoup.connect(UNION_HOME_URL)
|
||||||
|
// 学校官网会过滤部分非浏览器请求,这里补充常规浏览器请求头提高抓取稳定性。
|
||||||
|
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36")
|
||||||
|
.referrer("https://www.jsahvc.edu.cn/")
|
||||||
|
.timeout(10000)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
Elements noticeItems = getNoticeItems(doc);
|
||||||
|
for (Element item : noticeItems) {
|
||||||
|
Element titleLink = item.selectFirst(".news_title a, a[title], a");
|
||||||
|
if (titleLink == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String title = StrUtil.blankToDefault(titleLink.attr("title"), titleLink.text()).trim();
|
||||||
|
String url = titleLink.absUrl("href").trim();
|
||||||
|
Element meta = item.selectFirst(".news_meta, .date, .news_date, .time");
|
||||||
|
|
||||||
|
JSONObject node = new JSONObject();
|
||||||
|
node.set("title", title);
|
||||||
|
node.set("date", meta == null ? "" : meta.text().trim());
|
||||||
|
node.set("url", url);
|
||||||
|
noticeList.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.set("grassroots", noticeList);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优先按栏目标题查找通知公告列表,找不到时再使用学校官网历史模板中的栏目位兜底。
|
||||||
|
*
|
||||||
|
* @param doc 工会网站首页文档
|
||||||
|
* @return 通知公告列表节点
|
||||||
|
*/
|
||||||
|
private Elements getNoticeItems(Document doc) {
|
||||||
|
for (Element post : doc.select(".post")) {
|
||||||
|
Element title = post.selectFirst(".tt .title, .tit .title, h3, h2");
|
||||||
|
if (title != null && title.text().contains("通知公告")) {
|
||||||
|
return post.select(".news_list li, .wp_article_list li");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc.select(".post-18 .news_list li, .post-18 .wp_article_list li");
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
-5
@@ -284,19 +284,52 @@ public class SiteCugApplyController {
|
|||||||
private List<int[]> buildDisabledRanges(NutMap site, String today) {
|
private List<int[]> buildDisabledRanges(NutMap site, String today) {
|
||||||
List<NutMap> disabledList = toNutMapList(site.get("notApplyTimeList"));
|
List<NutMap> disabledList = toNutMapList(site.get("notApplyTimeList"));
|
||||||
List<int[]> result = new ArrayList<>();
|
List<int[]> result = new ArrayList<>();
|
||||||
|
int targetWeekDay = toWeekDay(DateUtil.parseDate(today));
|
||||||
for (NutMap item : disabledList) {
|
for (NutMap item : disabledList) {
|
||||||
if (item == null || !StrUtil.equals(today, item.getString("date"))) {
|
if (item == null || StrUtil.hasBlank(item.getString("startTime"), item.getString("endTime"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Integer start = parseTimeToMinutes(item.getString("startTime"));
|
// 禁用时间兼容旧的按日期配置,同时支持新增的按星期配置。
|
||||||
Integer end = parseTimeToMinutes(item.getString("endTime"));
|
if (isDateDisabledRange(item, today) || isWeekDisabledRange(item, targetWeekDay)) {
|
||||||
if (start != null && end != null && end > start) {
|
addDisabledRange(result, item);
|
||||||
result.add(new int[]{start, end});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDateDisabledRange(NutMap item, String today) {
|
||||||
|
String type = item.getString("type");
|
||||||
|
return (StrUtil.isBlank(type) || StrUtil.equals("date", type))
|
||||||
|
&& StrUtil.equals(today, item.getString("date"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWeekDisabledRange(NutMap item, int targetWeekDay) {
|
||||||
|
Integer weekDay = parseWeekDay(item.get("weekDay"));
|
||||||
|
return StrUtil.equals("week", item.getString("type"))
|
||||||
|
&& weekDay != null
|
||||||
|
&& weekDay == targetWeekDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDisabledRange(List<int[]> result, NutMap item) {
|
||||||
|
Integer start = parseTimeToMinutes(item.getString("startTime"));
|
||||||
|
Integer end = parseTimeToMinutes(item.getString("endTime"));
|
||||||
|
if (start != null && end != null && end > start) {
|
||||||
|
result.add(new int[]{start, end});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer parseWeekDay(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int weekDay = Integer.parseInt(String.valueOf(value));
|
||||||
|
return weekDay >= 1 && weekDay <= 7 ? weekDay : null;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<int[]> buildReservedRanges(List<SiteCugApply> applyList, String today) {
|
private List<int[]> buildReservedRanges(List<SiteCugApply> applyList, String today) {
|
||||||
List<int[]> result = new ArrayList<>();
|
List<int[]> result = new ArrayList<>();
|
||||||
String dayStart = today + " 00:00:00";
|
String dayStart = today + " 00:00:00";
|
||||||
@@ -404,6 +437,11 @@ public class SiteCugApplyController {
|
|||||||
return week == 0 || week == 6;
|
return week == 0 || week == 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int toWeekDay(DateTime date) {
|
||||||
|
int week = date.dayOfWeek() - 1;
|
||||||
|
return week == 0 ? 7 : week;
|
||||||
|
}
|
||||||
|
|
||||||
private List<NutMap> buildAvailabilityBlocks(SiteCugInfo siteInfo, String day, List<SiteCugApply> applyList, Set<String> holidaySet) {
|
private List<NutMap> buildAvailabilityBlocks(SiteCugInfo siteInfo, String day, List<SiteCugApply> applyList, Set<String> holidaySet) {
|
||||||
if (siteInfo.getReserveTimeType() != null && siteInfo.getReserveTimeType() == 2) {
|
if (siteInfo.getReserveTimeType() != null && siteInfo.getReserveTimeType() == 2) {
|
||||||
return buildFullDayAvailabilityBlocks(siteInfo, day, applyList, holidaySet);
|
return buildFullDayAvailabilityBlocks(siteInfo, day, applyList, holidaySet);
|
||||||
@@ -802,6 +840,7 @@ public class SiteCugApplyController {
|
|||||||
.setReserveStartTime(apply.getReserveStartTime())
|
.setReserveStartTime(apply.getReserveStartTime())
|
||||||
.setReserveEndTime(apply.getReserveEndTime())
|
.setReserveEndTime(apply.getReserveEndTime())
|
||||||
.setJoinCount(apply.getJoinCount())
|
.setJoinCount(apply.getJoinCount())
|
||||||
|
.setCoffeeNeeded(apply.getCoffeeNeeded())
|
||||||
.setApplyCause(apply.getApplyCause())
|
.setApplyCause(apply.getApplyCause())
|
||||||
.setBackOption(apply.getBackOption())
|
.setBackOption(apply.getBackOption())
|
||||||
.setYearlyReserveEndDate(apply.getYearlyReserveEndDate());
|
.setYearlyReserveEndDate(apply.getYearlyReserveEndDate());
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.siteCug.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugApplyService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/siteCug/branchUnionAudit")
|
||||||
|
@Api("场馆分工会审核")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SiteCugBranchUnionAuditController {
|
||||||
|
|
||||||
|
private static final String AUDIT_TASK_NAME = "c4493b93-75c0-4980-b604-19df2be2c42c";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SiteCugApplyService applyService;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/siteCug/branchUnionAudit/index.html")
|
||||||
|
@SaCheckPermission("siteCug.branchUnionAudit")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/dayofficework/siteCug/branchUnionAudit/index.html")
|
||||||
|
@SaCheckPermission("h5.siteCug.branchUnionAudit")
|
||||||
|
public void h5Index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"siteCug.branchUnionAudit", "h5.siteCug.branchUnionAudit"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param("siteType") String siteType,
|
||||||
|
@Param("siteId") String siteId,
|
||||||
|
@Param("approval") Boolean approval) {
|
||||||
|
return Result.success(applyService.listAuditPage(pageForm, siteType, siteId, approval, AUDIT_TASK_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/executeTask")
|
||||||
|
@ApiOperation("执行审核任务")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"siteCug.branchUnionAudit", "h5.siteCug.branchUnionAudit"}, mode = SaMode.OR)
|
||||||
|
public Result executeTask(@Param("data") String data) {
|
||||||
|
return applyService.executeAuditTask(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/revokeTask")
|
||||||
|
@ApiOperation("撤回审核任务")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"siteCug.branchUnionAudit", "h5.siteCug.branchUnionAudit"}, mode = SaMode.OR)
|
||||||
|
public Result revokeTask(@Param("taskId") Long taskId, @Param("applyId") String applyId) {
|
||||||
|
return applyService.revokeAuditTask(taskId, applyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.siteCug.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugApplyService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/siteCug/deputySchoolUnion")
|
||||||
|
@Api("场馆校工会副主席审核")
|
||||||
|
@Ok("json:full")
|
||||||
|
public class SiteCugDeputySchoolUnionController {
|
||||||
|
|
||||||
|
private static final String AUDIT_TASK_NAME = "de7044e4-187b-43c8-ab47-87eb0998302a";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SiteCugApplyService applyService;
|
||||||
|
|
||||||
|
@At("/")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/siteCug/deputySchoolUnion/index.html")
|
||||||
|
@SaCheckPermission("siteCug.deputySchoolUnion")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/h5")
|
||||||
|
@Ok("beetl:/platform/zhghh5/dayofficework/siteCug/deputySchoolUnion/index.html")
|
||||||
|
@SaCheckPermission("h5.siteCug.deputySchoolUnion")
|
||||||
|
public void h5Index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@SaCheckPermission(value = {"siteCug.deputySchoolUnion", "h5.siteCug.deputySchoolUnion"}, mode = SaMode.OR)
|
||||||
|
public Result pageData(PageForm pageForm,
|
||||||
|
@Param("siteType") String siteType,
|
||||||
|
@Param("siteId") String siteId,
|
||||||
|
@Param("approval") Boolean approval) {
|
||||||
|
return Result.success(applyService.listAuditPage(pageForm, siteType, siteId, approval, AUDIT_TASK_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/executeTask")
|
||||||
|
@ApiOperation("执行审核任务")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"siteCug.deputySchoolUnion", "h5.siteCug.deputySchoolUnion"}, mode = SaMode.OR)
|
||||||
|
public Result executeTask(@Param("data") String data) {
|
||||||
|
return applyService.executeAuditTask(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/revokeTask")
|
||||||
|
@ApiOperation("撤回审核任务")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
@SaCheckPermission(value = {"siteCug.deputySchoolUnion", "h5.siteCug.deputySchoolUnion"}, mode = SaMode.OR)
|
||||||
|
public Result revokeTask(@Param("taskId") Long taskId, @Param("applyId") String applyId) {
|
||||||
|
return applyService.revokeAuditTask(taskId, applyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
-6
@@ -83,15 +83,11 @@ public class SiteCugManageController {
|
|||||||
public Object submit(@Param("data") SiteCugInfo info) {
|
public Object submit(@Param("data") SiteCugInfo info) {
|
||||||
List<NutMap> notApplyTimeList = info.getNotApplyTimeList();
|
List<NutMap> notApplyTimeList = info.getNotApplyTimeList();
|
||||||
if (notApplyTimeList != null) {
|
if (notApplyTimeList != null) {
|
||||||
boolean invalid = notApplyTimeList.stream().anyMatch(item ->
|
boolean invalid = notApplyTimeList.stream().anyMatch(this::isInvalidDisabledTime);
|
||||||
item == null
|
|
||||||
|| StrUtil.isBlank(item.getString("date"))
|
|
||||||
|| StrUtil.isBlank(item.getString("startTime"))
|
|
||||||
|| StrUtil.isBlank(item.getString("endTime"))
|
|
||||||
|| item.getString("startTime").compareTo(item.getString("endTime")) >= 0);
|
|
||||||
if (invalid) {
|
if (invalid) {
|
||||||
return Result.error("Invalid disabled time settings");
|
return Result.error("Invalid disabled time settings");
|
||||||
}
|
}
|
||||||
|
notApplyTimeList.forEach(this::normalizeDisabledTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.getReserveTimeType() == null) {
|
if (info.getReserveTimeType() == null) {
|
||||||
@@ -196,6 +192,62 @@ public class SiteCugManageController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInvalidDisabledTime(NutMap item) {
|
||||||
|
if (item == null
|
||||||
|
|| StrUtil.isBlank(item.getString("startTime"))
|
||||||
|
|| StrUtil.isBlank(item.getString("endTime"))
|
||||||
|
|| item.getString("startTime").compareTo(item.getString("endTime")) >= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String type = item.getString("type");
|
||||||
|
if (StrUtil.isBlank(type) || StrUtil.equals(type, "date")) {
|
||||||
|
return StrUtil.isBlank(item.getString("date"));
|
||||||
|
}
|
||||||
|
if (StrUtil.equals(type, "week")) {
|
||||||
|
return !isWeekDay(item.get("weekDay"));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeDisabledTime(NutMap item) {
|
||||||
|
if (item == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(item.getString("type"))) {
|
||||||
|
item.put("type", "date");
|
||||||
|
}
|
||||||
|
if (StrUtil.equals(item.getString("type"), "week")) {
|
||||||
|
int weekDay = Integer.parseInt(String.valueOf(item.get("weekDay")));
|
||||||
|
item.put("weekDay", weekDay);
|
||||||
|
item.put("weekName", getWeekName(weekDay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWeekDay(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int weekDay = Integer.parseInt(String.valueOf(value));
|
||||||
|
return weekDay >= 1 && weekDay <= 7;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getWeekName(int weekDay) {
|
||||||
|
return switch (weekDay) {
|
||||||
|
case 1 -> "星期一";
|
||||||
|
case 2 -> "星期二";
|
||||||
|
case 3 -> "星期三";
|
||||||
|
case 4 -> "星期四";
|
||||||
|
case 5 -> "星期五";
|
||||||
|
case 6 -> "星期六";
|
||||||
|
case 7 -> "星期日";
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private NutMap normalizeOpenHourTimeUnit(NutMap item) {
|
private NutMap normalizeOpenHourTimeUnit(NutMap item) {
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+5
-184
@@ -2,55 +2,29 @@ package com.budwk.app.zhgh.dayofficework.siteCug.controller;
|
|||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.dev33.satoken.annotation.SaMode;
|
import cn.dev33.satoken.annotation.SaMode;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
|
||||||
import cn.hutool.core.lang.Dict;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
|
||||||
import com.budwk.app.base.page.Pagination;
|
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
import com.budwk.app.base.utils.PageUtil;
|
|
||||||
import com.budwk.app.flow.constant.FlowConst;
|
|
||||||
import com.budwk.app.flow.entity.ProcessTask;
|
|
||||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
|
||||||
import com.budwk.app.flow.service.FlowCommonService;
|
|
||||||
import com.budwk.app.flow.service.ProcessTaskService;
|
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
|
||||||
import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugApply;
|
|
||||||
import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugApplyService;
|
import com.budwk.app.zhgh.dayofficework.siteCug.service.SiteCugApplyService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
import org.nutz.dao.Cnd;
|
|
||||||
import org.nutz.dao.Sqls;
|
|
||||||
import org.nutz.dao.sql.Sql;
|
|
||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
|
||||||
import org.nutz.ioc.aop.Aop;
|
import org.nutz.ioc.aop.Aop;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.lang.util.NutMap;
|
|
||||||
import org.nutz.json.Json;
|
|
||||||
import org.nutz.mvc.annotation.At;
|
import org.nutz.mvc.annotation.At;
|
||||||
import org.nutz.mvc.annotation.Ok;
|
import org.nutz.mvc.annotation.Ok;
|
||||||
import org.nutz.mvc.annotation.Param;
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@IocBean
|
@IocBean
|
||||||
@At("/platform/siteCug/schoolUnionAudit")
|
@At("/platform/siteCug/schoolUnionAudit")
|
||||||
@Api("场馆校工会审核")
|
@Api("场馆校工会主席审核")
|
||||||
@Ok("json:full")
|
@Ok("json:full")
|
||||||
public class SiteCugSchoolUnionAuditController {
|
public class SiteCugSchoolUnionAuditController {
|
||||||
|
|
||||||
private static final String YEARLY_BATCH_PREFIX = "YEARLY_BATCH:";
|
private static final String AUDIT_TASK_NAME = "c8c03407-cf26-4e0b-82f1-b2afc9c79996";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SiteCugApplyService applyService;
|
private SiteCugApplyService applyService;
|
||||||
@Inject
|
|
||||||
private ProcessTaskService processTaskService;
|
|
||||||
@Inject
|
|
||||||
private FlowCommonService flowCommonService;
|
|
||||||
|
|
||||||
@At("/")
|
@At("/")
|
||||||
@Ok("beetl:/platform/zhgh/dayofficework/siteCug/schoolUnionAudit/index.html")
|
@Ok("beetl:/platform/zhgh/dayofficework/siteCug/schoolUnionAudit/index.html")
|
||||||
@@ -71,102 +45,7 @@ public class SiteCugSchoolUnionAuditController {
|
|||||||
@Param("siteType") String siteType,
|
@Param("siteType") String siteType,
|
||||||
@Param("siteId") String siteId,
|
@Param("siteId") String siteId,
|
||||||
@Param("approval") Boolean approval) {
|
@Param("approval") Boolean approval) {
|
||||||
Sql sql = Sqls.create("""
|
return Result.success(applyService.listAuditPage(pageForm, siteType, siteId, approval, AUDIT_TASK_NAME));
|
||||||
SELECT
|
|
||||||
info.*,
|
|
||||||
si.name as siteName,
|
|
||||||
CASE WHEN info.reserveType = 'club' THEN info.clubName ELSE info.applyUnionName END AS reserveTargetName,
|
|
||||||
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,
|
|
||||||
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
|
||||||
CASE WHEN EXISTS (
|
|
||||||
SELECT 1 FROM wf_process_task rt
|
|
||||||
WHERE rt.processInstanceId = ins.id AND rt.taskParentId = t.id
|
|
||||||
) THEN 1 ELSE 0 END AS canRevoke,
|
|
||||||
CASE WHEN info.backOption LIKE 'YEARLY_BATCH:%' THEN 1 ELSE 0 END AS yearlyBatch,
|
|
||||||
CASE WHEN info.backOption LIKE 'YEARLY_BATCH:%' THEN (
|
|
||||||
SELECT COUNT(1) FROM site_cug_apply batch_info WHERE batch_info.backOption = info.backOption AND batch_info.createdBy = info.createdBy
|
|
||||||
) ELSE 1 END AS batchAuditCount
|
|
||||||
FROM
|
|
||||||
wf_process_task t
|
|
||||||
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
|
||||||
LEFT JOIN site_cug_apply info ON info.id = ins.businessNo
|
|
||||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
|
||||||
LEFT JOIN site_cug_info si ON info.siteId = si.id
|
|
||||||
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
|
||||||
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id
|
|
||||||
$condition
|
|
||||||
""");
|
|
||||||
Cnd cnd = Cnd.NEW();
|
|
||||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
|
||||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
|
||||||
seg.or(SiteCugApply::getApplyUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
|
||||||
seg.or(SiteCugApply::getApplyLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
|
||||||
cnd.and(seg);
|
|
||||||
}
|
|
||||||
cnd.andEX("si.typeId", "=", siteType);
|
|
||||||
cnd.andEX("info.siteId", "=", siteId);
|
|
||||||
cnd.and("t.taskName", "=", "c8c03407-cf26-4e0b-82f1-b2afc9c79996");
|
|
||||||
if (!StpUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
|
||||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
|
||||||
}
|
|
||||||
if (Boolean.TRUE.equals(approval)) {
|
|
||||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
|
||||||
} else {
|
|
||||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && StrUtil.isNotBlank(pageForm.getPageOrderBy())) {
|
|
||||||
cnd.orderBy(resolveOrderColumn(pageForm.getPageOrderName()), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
|
||||||
} else {
|
|
||||||
cnd.desc("info.createdAt");
|
|
||||||
}
|
|
||||||
cnd.groupBy("t.id");
|
|
||||||
sql.setCondition(cnd);
|
|
||||||
Pagination<NutMap> pageVO = applyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
|
||||||
return Result.success(pageVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String resolveOrderColumn(String pageOrderName) {
|
|
||||||
if (StrUtil.isBlank(pageOrderName)) {
|
|
||||||
return "info.createdAt";
|
|
||||||
}
|
|
||||||
switch (pageOrderName) {
|
|
||||||
case "siteName":
|
|
||||||
return "si.name";
|
|
||||||
case "applyUserName":
|
|
||||||
return "info.applyUserName";
|
|
||||||
case "applyLoginName":
|
|
||||||
return "info.applyLoginName";
|
|
||||||
case "yearlyBatch":
|
|
||||||
return "yearlyBatch";
|
|
||||||
case "reserveTargetName":
|
|
||||||
return "reserveTargetName";
|
|
||||||
case "reserveStartTime":
|
|
||||||
return "info.reserveStartTime";
|
|
||||||
case "reserveEndTime":
|
|
||||||
return "info.reserveEndTime";
|
|
||||||
case "applyMobile":
|
|
||||||
return "info.applyMobile";
|
|
||||||
case "curTaskName":
|
|
||||||
return "curTaskName";
|
|
||||||
case "instanceState":
|
|
||||||
return "ins.state";
|
|
||||||
default:
|
|
||||||
return "info.createdAt";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@At("/executeTask")
|
@At("/executeTask")
|
||||||
@@ -174,72 +53,14 @@ public class SiteCugSchoolUnionAuditController {
|
|||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
@SaCheckPermission(value = {"siteCug.schoolUnionAudit", "h5.siteCug.schoolUnionAudit"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"siteCug.schoolUnionAudit", "h5.siteCug.schoolUnionAudit"}, mode = SaMode.OR)
|
||||||
public Result executeTask(@Param("data") String data) {
|
public Result executeTask(@Param("data") String data) {
|
||||||
Dict args = Json.fromJson(Dict.class, data);
|
return applyService.executeAuditTask(data);
|
||||||
Long processTaskId = args.getLong(FlowConst.PROCESS_TASK_ID_KEY);
|
|
||||||
ProcessTask currentTask = processTaskService.getById(processTaskId);
|
|
||||||
if (currentTask == null) {
|
|
||||||
return Result.error("审核任务不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
SiteCugApply apply = applyService.fetch(args.getStr("applyId"));
|
|
||||||
if (apply == null) {
|
|
||||||
return Result.error("预约记录不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ProcessTask> taskList = new ArrayList<>();
|
|
||||||
if (StrUtil.isNotBlank(apply.getBackOption()) && apply.getBackOption().startsWith(YEARLY_BATCH_PREFIX)) {
|
|
||||||
List<SiteCugApply> batchList = applyService.query(Cnd.where("backOption", "=", apply.getBackOption()).and("createdBy", "=", apply.getCreatedBy()));
|
|
||||||
List<String> bizIds = batchList.stream().map(SiteCugApply::getId).toList();
|
|
||||||
taskList = processTaskService.getDoingTaskByBizIdTaskName(bizIds, currentTask.getTaskName());
|
|
||||||
}
|
|
||||||
if (taskList.isEmpty()) {
|
|
||||||
taskList.add(currentTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ProcessTask task : taskList) {
|
|
||||||
Dict cloneArgs = args.clone();
|
|
||||||
cloneArgs.put(FlowConst.PROCESS_TASK_ID_KEY, task.getId());
|
|
||||||
flowCommonService.executeTask(cloneArgs);
|
|
||||||
}
|
|
||||||
if (taskList.size() > 1) {
|
|
||||||
return Result.success("已完成该全年预约批次的审核");
|
|
||||||
}
|
|
||||||
return Result.success("提交成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@At("/revokeTask")
|
@At("/revokeTask")
|
||||||
@ApiOperation("撤回审核任务")
|
@ApiOperation("撤回审核任务")
|
||||||
@Aop(TransAop.READ_COMMITTED)
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
@SaCheckPermission(value = {"siteCug.schoolUnionAudit", "h5.siteCug.schoolUnionAudit"}, mode = SaMode.OR)
|
@SaCheckPermission(value = {"siteCug.schoolUnionAudit", "h5.siteCug.schoolUnionAudit"}, mode = SaMode.OR)
|
||||||
public Result revokeTask(@Param("taskId") Long taskId, @Param("applyId") String applyId) {
|
public Result revokeTask(@Param("taskId") Long taskId, @Param("applyId") String applyId) {
|
||||||
ProcessTask currentTask = processTaskService.getById(taskId);
|
return applyService.revokeAuditTask(taskId, applyId);
|
||||||
if (currentTask == null) {
|
|
||||||
return Result.error("撤回任务不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
SiteCugApply apply = applyService.fetch(applyId);
|
|
||||||
if (apply == null) {
|
|
||||||
return Result.error("预约记录不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ProcessTask> taskList = new ArrayList<>();
|
|
||||||
if (StrUtil.isNotBlank(apply.getBackOption()) && apply.getBackOption().startsWith(YEARLY_BATCH_PREFIX)) {
|
|
||||||
List<SiteCugApply> batchList = applyService.query(Cnd.where("backOption", "=", apply.getBackOption()).and("createdBy", "=", apply.getCreatedBy()));
|
|
||||||
List<String> bizIds = batchList.stream().map(SiteCugApply::getId).toList();
|
|
||||||
taskList = processTaskService.getDoneTaskByBizIdTaskName(bizIds, currentTask.getTaskName());
|
|
||||||
}
|
|
||||||
if (taskList.isEmpty()) {
|
|
||||||
taskList.add(currentTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ProcessTask task : taskList) {
|
|
||||||
flowCommonService.revokeTask(task.getId());
|
|
||||||
}
|
|
||||||
if (taskList.size() > 1) {
|
|
||||||
return Result.success("已撤回该全年预约批次的审核任务");
|
|
||||||
}
|
|
||||||
return Result.success("撤回成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ public class SiteCugApply extends BaseModel {
|
|||||||
@ColDefine(type = ColType.INT)
|
@ColDefine(type = ColType.INT)
|
||||||
private Integer joinCount;
|
private Integer joinCount;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("是否需要咖啡")
|
||||||
|
@ColDefine(type = ColType.INT)
|
||||||
|
private Integer coffeeNeeded;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("预约事由")
|
@Comment("预约事由")
|
||||||
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
||||||
|
|||||||
+13
@@ -1,10 +1,14 @@
|
|||||||
package com.budwk.app.zhgh.dayofficework.siteCug.service;
|
package com.budwk.app.zhgh.dayofficework.siteCug.service;
|
||||||
|
|
||||||
|
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.service.BaseService;
|
import com.budwk.app.base.service.BaseService;
|
||||||
import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugApply;
|
import com.budwk.app.zhgh.dayofficework.siteCug.model.SiteCugApply;
|
||||||
import com.budwk.app.zhgh.dayofficework.siteCug.param.SiteCugRecordPageForm;
|
import com.budwk.app.zhgh.dayofficework.siteCug.param.SiteCugRecordPageForm;
|
||||||
import org.nutz.dao.Cnd;
|
import org.nutz.dao.Cnd;
|
||||||
import org.nutz.dao.sql.Sql;
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -21,4 +25,13 @@ public interface SiteCugApplyService extends BaseService<SiteCugApply> {
|
|||||||
|
|
||||||
// 场馆预约查询页的导出逻辑统一放在 service,controller 只负责接收请求
|
// 场馆预约查询页的导出逻辑统一放在 service,controller 只负责接收请求
|
||||||
void exportRecord(SiteCugRecordPageForm pageForm, HttpServletResponse response);
|
void exportRecord(SiteCugRecordPageForm pageForm, HttpServletResponse response);
|
||||||
|
|
||||||
|
// 场馆预约审核页共用列表查询,按流程节点 taskName 区分不同审核页面
|
||||||
|
Pagination<NutMap> listAuditPage(PageForm pageForm, String siteType, String siteId, Boolean approval, String auditTaskName);
|
||||||
|
|
||||||
|
// 场馆预约审核提交共用同一套任务执行逻辑,兼容全年预约批次一起审核
|
||||||
|
Result executeAuditTask(String data);
|
||||||
|
|
||||||
|
// 场馆预约审核撤回共用同一套任务撤回逻辑,兼容全年预约批次一起撤回
|
||||||
|
Result revokeAuditTask(Long taskId, String applyId);
|
||||||
}
|
}
|
||||||
|
|||||||
+255
-5
@@ -4,14 +4,25 @@ import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
|||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.lang.Dict;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
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.service.impl.BaseServiceImpl;
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
import com.budwk.app.base.utils.PageUtil;
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
|
import com.budwk.app.flow.constant.FlowConst;
|
||||||
import com.budwk.app.flow.entity.ProcessInstance;
|
import com.budwk.app.flow.entity.ProcessInstance;
|
||||||
|
import com.budwk.app.flow.entity.ProcessTask;
|
||||||
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||||
|
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||||
|
import com.budwk.app.flow.service.FlowCommonService;
|
||||||
|
import com.budwk.app.flow.service.ProcessTaskService;
|
||||||
import com.budwk.app.sys.models.SysHoliday;
|
import com.budwk.app.sys.models.SysHoliday;
|
||||||
import com.budwk.app.sys.models.Sys_union;
|
import com.budwk.app.sys.models.Sys_union;
|
||||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
@@ -30,6 +41,7 @@ import org.nutz.dao.sql.Sql;
|
|||||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.json.Json;
|
||||||
import org.nutz.lang.util.NutMap;
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -44,8 +56,14 @@ import java.util.stream.Collectors;
|
|||||||
@IocBean(args = {"refer:dao"})
|
@IocBean(args = {"refer:dao"})
|
||||||
public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> implements SiteCugApplyService {
|
public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> implements SiteCugApplyService {
|
||||||
|
|
||||||
|
private static final String YEARLY_BATCH_PREFIX = "YEARLY_BATCH:";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SysClubService sysClubService;
|
private SysClubService sysClubService;
|
||||||
|
@Inject
|
||||||
|
private ProcessTaskService processTaskService;
|
||||||
|
@Inject
|
||||||
|
private FlowCommonService flowCommonService;
|
||||||
|
|
||||||
public SiteCugApplyServiceImpl(Dao dao) {
|
public SiteCugApplyServiceImpl(Dao dao) {
|
||||||
super(dao);
|
super(dao);
|
||||||
@@ -64,6 +82,11 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
|||||||
if (StrUtil.isBlank(apply.getReserveStartTime()) || StrUtil.isBlank(apply.getReserveEndTime())) {
|
if (StrUtil.isBlank(apply.getReserveStartTime()) || StrUtil.isBlank(apply.getReserveEndTime())) {
|
||||||
return Map.of(false, "预约时间不能为空");
|
return Map.of(false, "预约时间不能为空");
|
||||||
}
|
}
|
||||||
|
if (apply.getCoffeeNeeded() == null) {
|
||||||
|
apply.setCoffeeNeeded(0);
|
||||||
|
} else if (apply.getCoffeeNeeded() != 0 && apply.getCoffeeNeeded() != 1) {
|
||||||
|
return Map.of(false, "是否需要咖啡仅支持是/否");
|
||||||
|
}
|
||||||
if (!DateUtil.parseDateTime(apply.getReserveEndTime()).isAfter(DateUtil.parseDateTime(apply.getReserveStartTime()))) {
|
if (!DateUtil.parseDateTime(apply.getReserveEndTime()).isAfter(DateUtil.parseDateTime(apply.getReserveStartTime()))) {
|
||||||
return Map.of(false, "结束时间必须晚于开始时间");
|
return Map.of(false, "结束时间必须晚于开始时间");
|
||||||
}
|
}
|
||||||
@@ -204,6 +227,123 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
|||||||
CommonDownloadUtil.download("场馆预约查询.xlsx", workbook, response);
|
CommonDownloadUtil.download("场馆预约查询.xlsx", workbook, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pagination<NutMap> listAuditPage(PageForm pageForm, String siteType, String siteId, Boolean approval, String auditTaskName) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
si.name as siteName,
|
||||||
|
CASE WHEN info.reserveType = 'club' THEN info.clubName ELSE info.applyUnionName END AS reserveTargetName,
|
||||||
|
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,
|
||||||
|
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
||||||
|
CASE WHEN EXISTS (
|
||||||
|
SELECT 1 FROM wf_process_task rt
|
||||||
|
WHERE rt.processInstanceId = ins.id AND rt.taskParentId = t.id
|
||||||
|
) THEN 1 ELSE 0 END AS canRevoke,
|
||||||
|
CASE WHEN info.backOption LIKE 'YEARLY_BATCH:%' THEN 1 ELSE 0 END AS yearlyBatch,
|
||||||
|
CASE WHEN info.backOption LIKE 'YEARLY_BATCH:%' THEN (
|
||||||
|
SELECT COUNT(1) FROM site_cug_apply batch_info WHERE batch_info.backOption = info.backOption AND batch_info.createdBy = info.createdBy
|
||||||
|
) ELSE 1 END AS batchAuditCount
|
||||||
|
FROM
|
||||||
|
wf_process_task t
|
||||||
|
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||||
|
LEFT JOIN site_cug_apply info ON info.id = ins.businessNo
|
||||||
|
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||||
|
LEFT JOIN site_cug_info si ON info.siteId = si.id
|
||||||
|
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||||
|
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.or(SiteCugApply::getApplyUserName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
seg.or(SiteCugApply::getApplyLoginName, "like", "%" + pageForm.getSearchKeyword() + "%");
|
||||||
|
cnd.and(seg);
|
||||||
|
}
|
||||||
|
cnd.andEX("si.typeId", "=", siteType);
|
||||||
|
cnd.andEX("info.siteId", "=", siteId);
|
||||||
|
cnd.and("t.taskName", "=", auditTaskName);
|
||||||
|
if (!StpUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||||
|
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||||
|
}
|
||||||
|
if (Boolean.TRUE.equals(approval)) {
|
||||||
|
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||||
|
} else {
|
||||||
|
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && StrUtil.isNotBlank(pageForm.getPageOrderBy())) {
|
||||||
|
cnd.orderBy(resolveAuditOrderColumn(pageForm.getPageOrderName()), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
} else {
|
||||||
|
cnd.desc("info.createdAt");
|
||||||
|
}
|
||||||
|
cnd.groupBy("t.id");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result executeAuditTask(String data) {
|
||||||
|
Dict args = Json.fromJson(Dict.class, data);
|
||||||
|
Long processTaskId = args.getLong(FlowConst.PROCESS_TASK_ID_KEY);
|
||||||
|
ProcessTask currentTask = processTaskService.getById(processTaskId);
|
||||||
|
if (currentTask == null) {
|
||||||
|
return Result.error("审核任务不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
SiteCugApply apply = fetch(args.getStr("applyId"));
|
||||||
|
if (apply == null) {
|
||||||
|
return Result.error("预约记录不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProcessTask> taskList = getBatchDoingTaskList(apply, currentTask);
|
||||||
|
for (ProcessTask task : taskList) {
|
||||||
|
Dict cloneArgs = args.clone();
|
||||||
|
cloneArgs.put(FlowConst.PROCESS_TASK_ID_KEY, task.getId());
|
||||||
|
flowCommonService.executeTask(cloneArgs);
|
||||||
|
}
|
||||||
|
if (taskList.size() > 1) {
|
||||||
|
return Result.success("已完成该全年预约批次的审核");
|
||||||
|
}
|
||||||
|
return Result.success("提交成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result revokeAuditTask(Long taskId, String applyId) {
|
||||||
|
ProcessTask currentTask = processTaskService.getById(taskId);
|
||||||
|
if (currentTask == null) {
|
||||||
|
return Result.error("撤回任务不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
SiteCugApply apply = fetch(applyId);
|
||||||
|
if (apply == null) {
|
||||||
|
return Result.error("预约记录不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProcessTask> taskList = getBatchDoneTaskList(apply, currentTask);
|
||||||
|
for (ProcessTask task : taskList) {
|
||||||
|
flowCommonService.revokeTask(task.getId());
|
||||||
|
}
|
||||||
|
if (taskList.size() > 1) {
|
||||||
|
return Result.success("已撤回该全年预约批次的审核任务");
|
||||||
|
}
|
||||||
|
return Result.success("撤回成功");
|
||||||
|
}
|
||||||
|
|
||||||
// 场馆预约查询导出字段统一在 service 中定义,并与当前列表展示字段保持一致
|
// 场馆预约查询导出字段统一在 service 中定义,并与当前列表展示字段保持一致
|
||||||
private List<ExcelExportEntity> buildRecordExportEntities() {
|
private List<ExcelExportEntity> buildRecordExportEntities() {
|
||||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||||
@@ -218,6 +358,66 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
|||||||
return exportEntities;
|
return exportEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveAuditOrderColumn(String pageOrderName) {
|
||||||
|
if (StrUtil.isBlank(pageOrderName)) {
|
||||||
|
return "info.createdAt";
|
||||||
|
}
|
||||||
|
switch (pageOrderName) {
|
||||||
|
case "siteName":
|
||||||
|
return "si.name";
|
||||||
|
case "applyUserName":
|
||||||
|
return "info.applyUserName";
|
||||||
|
case "applyLoginName":
|
||||||
|
return "info.applyLoginName";
|
||||||
|
case "yearlyBatch":
|
||||||
|
return "yearlyBatch";
|
||||||
|
case "reserveTargetName":
|
||||||
|
return "reserveTargetName";
|
||||||
|
case "reserveStartTime":
|
||||||
|
return "info.reserveStartTime";
|
||||||
|
case "reserveEndTime":
|
||||||
|
return "info.reserveEndTime";
|
||||||
|
case "applyMobile":
|
||||||
|
return "info.applyMobile";
|
||||||
|
case "curTaskName":
|
||||||
|
return "curTaskName";
|
||||||
|
case "instanceState":
|
||||||
|
return "ins.state";
|
||||||
|
default:
|
||||||
|
return "info.createdAt";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProcessTask> getBatchDoingTaskList(SiteCugApply apply, ProcessTask currentTask) {
|
||||||
|
List<ProcessTask> taskList = new ArrayList<>();
|
||||||
|
if (isYearlyBatchApply(apply)) {
|
||||||
|
List<SiteCugApply> batchList = query(Cnd.where("backOption", "=", apply.getBackOption()).and("createdBy", "=", apply.getCreatedBy()));
|
||||||
|
List<String> bizIds = batchList.stream().map(SiteCugApply::getId).toList();
|
||||||
|
taskList = processTaskService.getDoingTaskByBizIdTaskName(bizIds, currentTask.getTaskName());
|
||||||
|
}
|
||||||
|
if (taskList.isEmpty()) {
|
||||||
|
taskList.add(currentTask);
|
||||||
|
}
|
||||||
|
return taskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProcessTask> getBatchDoneTaskList(SiteCugApply apply, ProcessTask currentTask) {
|
||||||
|
List<ProcessTask> taskList = new ArrayList<>();
|
||||||
|
if (isYearlyBatchApply(apply)) {
|
||||||
|
List<SiteCugApply> batchList = query(Cnd.where("backOption", "=", apply.getBackOption()).and("createdBy", "=", apply.getCreatedBy()));
|
||||||
|
List<String> bizIds = batchList.stream().map(SiteCugApply::getId).toList();
|
||||||
|
taskList = processTaskService.getDoneTaskByBizIdTaskName(bizIds, currentTask.getTaskName());
|
||||||
|
}
|
||||||
|
if (taskList.isEmpty()) {
|
||||||
|
taskList.add(currentTask);
|
||||||
|
}
|
||||||
|
return taskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isYearlyBatchApply(SiteCugApply apply) {
|
||||||
|
return StrUtil.isNotBlank(apply.getBackOption()) && apply.getBackOption().startsWith(YEARLY_BATCH_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
// 预约时间范围内只要包含周六或周日,就视为不可预约
|
// 预约时间范围内只要包含周六或周日,就视为不可预约
|
||||||
private boolean containsWeekend(String reserveStartTime, String reserveEndTime) {
|
private boolean containsWeekend(String reserveStartTime, String reserveEndTime) {
|
||||||
Date start = DateUtil.beginOfDay(DateUtil.parseDateTime(reserveStartTime));
|
Date start = DateUtil.beginOfDay(DateUtil.parseDateTime(reserveStartTime));
|
||||||
@@ -261,19 +461,69 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
|||||||
DateTime reserveStart = DateUtil.parseDateTime(reserveStartTime);
|
DateTime reserveStart = DateUtil.parseDateTime(reserveStartTime);
|
||||||
DateTime reserveEnd = DateUtil.parseDateTime(reserveEndTime);
|
DateTime reserveEnd = DateUtil.parseDateTime(reserveEndTime);
|
||||||
for (NutMap range : timeRanges) {
|
for (NutMap range : timeRanges) {
|
||||||
if (range == null || StrUtil.hasBlank(range.getString("date"), range.getString("startTime"), range.getString("endTime"))) {
|
if (range == null || StrUtil.hasBlank(range.getString("startTime"), range.getString("endTime"))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DateTime disabledStart = DateUtil.parseDateTime(range.getString("date") + " " + range.getString("startTime") + ":00");
|
if (isDateDisabledTime(range) && intersectsDateDisabledTime(range, reserveStart, reserveEnd)) {
|
||||||
DateTime disabledEnd = DateUtil.parseDateTime(range.getString("date") + " " + range.getString("endTime") + ":00");
|
return true;
|
||||||
boolean overlap = reserveStart.isBefore(disabledEnd) && reserveEnd.isAfter(disabledStart);
|
}
|
||||||
if (overlap) {
|
if (isWeekDisabledTime(range) && intersectsWeekDisabledTime(range, reserveStart, reserveEnd)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDateDisabledTime(NutMap range) {
|
||||||
|
String type = range.getString("type");
|
||||||
|
return (StrUtil.isBlank(type) || StrUtil.equals(type, "date")) && StrUtil.isNotBlank(range.getString("date"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWeekDisabledTime(NutMap range) {
|
||||||
|
return StrUtil.equals(range.getString("type"), "week") && range.get("weekDay") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean intersectsDateDisabledTime(NutMap range, DateTime reserveStart, DateTime reserveEnd) {
|
||||||
|
DateTime disabledStart = DateUtil.parseDateTime(range.getString("date") + " " + range.getString("startTime") + ":00");
|
||||||
|
DateTime disabledEnd = DateUtil.parseDateTime(range.getString("date") + " " + range.getString("endTime") + ":00");
|
||||||
|
return reserveStart.isBefore(disabledEnd) && reserveEnd.isAfter(disabledStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean intersectsWeekDisabledTime(NutMap range, DateTime reserveStart, DateTime reserveEnd) {
|
||||||
|
int disabledWeekDay = parseWeekDay(range.get("weekDay"));
|
||||||
|
if (disabledWeekDay == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Date current = DateUtil.beginOfDay(reserveStart);
|
||||||
|
Date end = DateUtil.beginOfDay(reserveEnd);
|
||||||
|
while (current.compareTo(end) <= 0) {
|
||||||
|
DateTime currentDay = DateUtil.date(current);
|
||||||
|
if (toWeekDay(currentDay) == disabledWeekDay) {
|
||||||
|
DateTime disabledStart = DateUtil.parseDateTime(DateUtil.formatDate(currentDay) + " " + range.getString("startTime") + ":00");
|
||||||
|
DateTime disabledEnd = DateUtil.parseDateTime(DateUtil.formatDate(currentDay) + " " + range.getString("endTime") + ":00");
|
||||||
|
if (reserveStart.isBefore(disabledEnd) && reserveEnd.isAfter(disabledStart)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current = DateUtil.offsetDay(current, 1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseWeekDay(Object value) {
|
||||||
|
try {
|
||||||
|
int weekDay = Integer.parseInt(String.valueOf(value));
|
||||||
|
return weekDay >= 1 && weekDay <= 7 ? weekDay : 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toWeekDay(DateTime currentDay) {
|
||||||
|
int weekDay = currentDay.dayOfWeek() - 1;
|
||||||
|
return weekDay == 0 ? 7 : weekDay;
|
||||||
|
}
|
||||||
|
|
||||||
// 按预约类型补齐最终落库数据,避免前端传错或被绕过
|
// 按预约类型补齐最终落库数据,避免前端传错或被绕过
|
||||||
private Map<Boolean, String> fillReserveTypeData(SiteCugApply apply) {
|
private Map<Boolean, String> fillReserveTypeData(SiteCugApply apply) {
|
||||||
if (StrUtil.isBlank(apply.getReserveType())) {
|
if (StrUtil.isBlank(apply.getReserveType())) {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
|
|
||||||
<work-template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
|
<work-template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
|
||||||
|
|
||||||
<jcdt :list="websiteNews"></jcdt>
|
<jcdt :list="websiteNews.grassroots"></jcdt>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -148,7 +148,9 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
el: '#v4-home-app',
|
el: '#v4-home-app',
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
websiteNews: [],
|
websiteNews: {
|
||||||
|
grassroots: []
|
||||||
|
},
|
||||||
homeBannerList: "${config.AppHomeImg!}".split(",").map(item => item.trim()).filter(item => item)
|
homeBannerList: "${config.AppHomeImg!}".split(",").map(item => item.trim()).filter(item => item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -167,7 +169,7 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
getWebSiteNews(){
|
getWebSiteNews(){
|
||||||
this.$axios.post('/platform/home/getNews').then(res => {
|
this.$axios.post('/platform/home/getNews').then(res => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.websiteNews = res.data
|
this.$set(this, 'websiteNews', res.data || {grassroots: []})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
const jcdt = {
|
const jcdt = {
|
||||||
template: /*language=HTML*/ `
|
template: [
|
||||||
<div class="jcdt-wrapper">
|
'<div class="jcdt-wrapper">',
|
||||||
<div class="jcdt-container">
|
' <div class="jcdt-container">',
|
||||||
<el-carousel height="360px" :interval="10000" indicator-position="none">
|
' <div class="jcdt-title">',
|
||||||
<el-carousel-item v-for="item,index in list" :key="index">
|
' <span>通知公告</span>',
|
||||||
<div class="jcdt-title">
|
' </div>',
|
||||||
<span>{{ item.label }}</span>
|
' <div class="jcdt-content">',
|
||||||
</div>
|
' <div class="jcdt-list">',
|
||||||
<div class="jcdt-content">
|
' <div class="jcdt-item" v-for="item in list" :key="item.url || item.title" @click="onLink(item)">',
|
||||||
<div class="jcdt-list">
|
' <div class="date" v-if="item.date">',
|
||||||
<div class="jcdt-item" v-for="o,i in item.value" :key="i" @click="onLink(o)">
|
' <i class="el-icon-alarm-clock"></i>',
|
||||||
<div class="date" v-if="o.time">
|
' <span>{{item.date}}</span>',
|
||||||
<i class="el-icon-alarm-clock"></i>
|
' </div>',
|
||||||
<span>{{o.time}}</span>
|
' <div style="display: flex; align-items: center">',
|
||||||
</div>
|
' <div class="jcdt-item-icon">',
|
||||||
<div style="display: flex; align-items: center">
|
' <i class="fa fa-bullhorn"></i>',
|
||||||
<div>
|
' </div>',
|
||||||
|
' <div class="title">{{item.title}}</div>',
|
||||||
</div>
|
' </div>',
|
||||||
<div class="title">{{o.text}}</div>
|
' </div>',
|
||||||
</div>
|
' </div>',
|
||||||
</div>
|
' </div>',
|
||||||
</div>
|
' </div>',
|
||||||
</div>
|
'</div>'
|
||||||
</el-carousel-item>
|
].join(''),
|
||||||
</el-carousel>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`,
|
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
@@ -39,144 +35,149 @@ const jcdt = {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onLink(item) {
|
onLink(item) {
|
||||||
const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href
|
if (!item.url) {
|
||||||
window.open(url)
|
return
|
||||||
},
|
}
|
||||||
isHttpOrHttps(url) {
|
window.open(item.url)
|
||||||
return /^(http:\/\/|https:\/\/)/i.test(url)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: /*language=CSS*/ `
|
style: [
|
||||||
.jcdt-wrapper {
|
'.jcdt-wrapper {',
|
||||||
width: 100%;
|
' width: 100%;',
|
||||||
background-size: cover;
|
' background-size: cover;',
|
||||||
background-position: center;
|
' background-position: center;',
|
||||||
background-repeat: no-repeat;
|
' background-repeat: no-repeat;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
.jcdt-container {
|
'.jcdt-container {',
|
||||||
width: 80%;
|
' width: 80%;',
|
||||||
max-width: 80%;
|
' max-width: 80%;',
|
||||||
margin: 0 auto 10px;
|
' margin: 0 auto 10px;',
|
||||||
background-color: #FFFFFF;
|
' background-color: #FFFFFF;',
|
||||||
border-radius: 12px;
|
' border-radius: 12px;',
|
||||||
padding: 20px;
|
' padding: 20px;',
|
||||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
|
' box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-title{
|
'/deep/ .jcdt-title{',
|
||||||
font-size: 30px;
|
' font-size: 30px;',
|
||||||
color: #000000;
|
' color: #000000;',
|
||||||
display: block;
|
' display: block;',
|
||||||
font-weight: bold;
|
' font-weight: bold;',
|
||||||
position: relative;
|
' position: relative;',
|
||||||
text-align: center;
|
' text-align: center;',
|
||||||
padding: 20px 0;
|
' padding: 20px 0;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-container .jcdt-title span::before {
|
'/deep/ .jcdt-container .jcdt-title span::before {',
|
||||||
content: '';
|
" content: '';",
|
||||||
width: 24px;
|
' width: 24px;',
|
||||||
height: 11px;
|
' height: 11px;',
|
||||||
background: url(https://www.ncu.edu.cn/images/titl.svg) no-repeat center;
|
' background: url(https://www.ncu.edu.cn/images/titl.svg) no-repeat center;',
|
||||||
background-size: 24px 11px;
|
' background-size: 24px 11px;',
|
||||||
display: inline-block;
|
' display: inline-block;',
|
||||||
margin-right: 0;
|
' margin-right: 0;',
|
||||||
vertical-align: middle;
|
' vertical-align: middle;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-container .jcdt-title span::after {
|
'/deep/ .jcdt-container .jcdt-title span::after {',
|
||||||
content: '';
|
" content: '';",
|
||||||
width: 24px;
|
' width: 24px;',
|
||||||
height: 11px;
|
' height: 11px;',
|
||||||
background: url(https://www.ncu.edu.cn/images/titr.svg) no-repeat center;
|
' background: url(https://www.ncu.edu.cn/images/titr.svg) no-repeat center;',
|
||||||
background-size: 24px 11px;
|
' background-size: 24px 11px;',
|
||||||
display: inline-block;
|
' display: inline-block;',
|
||||||
margin-left: 0;
|
' margin-left: 0;',
|
||||||
vertical-align: middle;
|
' vertical-align: middle;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-list {
|
'/deep/ .jcdt-list {',
|
||||||
display: grid;
|
' display: grid;',
|
||||||
grid-template-columns: repeat(4, 1fr);
|
' grid-template-columns: repeat(4, 1fr);',
|
||||||
gap: 20px;
|
' gap: 20px;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-item {
|
'/deep/ .jcdt-item {',
|
||||||
display: flex;
|
' display: flex;',
|
||||||
flex-direction: column;
|
' flex-direction: column;',
|
||||||
padding: 16px;
|
' padding: 16px;',
|
||||||
border: none;
|
' border: none;',
|
||||||
border-bottom: 3px solid transparent;
|
' border-bottom: 3px solid transparent;',
|
||||||
transition: all 0.3s ease;
|
' transition: all 0.3s ease;',
|
||||||
cursor: pointer;
|
' cursor: pointer;',
|
||||||
height: auto;
|
' height: auto;',
|
||||||
border-radius: 12px;
|
' border-radius: 12px;',
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
' box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);',
|
||||||
border-bottom-color: var(--color-primary);
|
' border-bottom-color: var(--color-primary);',
|
||||||
background: #ffffff;
|
' background: #ffffff;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-item:hover{
|
'/deep/ .jcdt-item:hover{',
|
||||||
transform: translateY(-4px);
|
' transform: translateY(-4px);',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-item .date {
|
'/deep/ .jcdt-item .date {',
|
||||||
font-size: 20px;
|
' font-size: 20px;',
|
||||||
font-weight: bold;
|
' font-weight: bold;',
|
||||||
white-space: nowrap;
|
' white-space: nowrap;',
|
||||||
text-align: left;
|
' text-align: left;',
|
||||||
margin-bottom: 8px;
|
' margin-bottom: 8px;',
|
||||||
transition: opacity 0.3s ease;
|
' transition: opacity 0.3s ease;',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-item .title {
|
'/deep/ .jcdt-item .title {',
|
||||||
font-size: 16px;
|
' font-size: 16px;',
|
||||||
font-weight: 600;
|
' font-weight: 600;',
|
||||||
/*margin-bottom: 12px;*/
|
' /*margin-bottom: 12px;*/',
|
||||||
line-height: 1.4;
|
' line-height: 1.4;',
|
||||||
display: -webkit-box;
|
' display: -webkit-box;',
|
||||||
-webkit-line-clamp: 2;
|
' -webkit-line-clamp: 2;',
|
||||||
-webkit-box-orient: vertical;
|
' -webkit-box-orient: vertical;',
|
||||||
overflow: hidden;
|
' overflow: hidden;',
|
||||||
/*height: 45px;*/
|
' /*height: 45px;*/',
|
||||||
}
|
'}',
|
||||||
|
'',
|
||||||
/deep/ .jcdt-item .image {
|
'/deep/ .jcdt-item-icon {',
|
||||||
width: 100%;
|
' color: #007aff;',
|
||||||
height: 180px;
|
' font-size: 22px;',
|
||||||
margin: 0 0 16px 0;
|
' margin-right: 8px;',
|
||||||
border-radius: 8px;
|
'}',
|
||||||
overflow: hidden;
|
'',
|
||||||
background: #f5f5f5;
|
'/deep/ .jcdt-item .image {',
|
||||||
display: flex;
|
' width: 100%;',
|
||||||
align-items: center;
|
' height: 180px;',
|
||||||
justify-content: center;
|
' margin: 0 0 16px 0;',
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
' border-radius: 8px;',
|
||||||
transition: transform 0.3s ease;
|
' overflow: hidden;',
|
||||||
}
|
' background: #f5f5f5;',
|
||||||
|
' display: flex;',
|
||||||
/deep/ .jcdt-item .image img {
|
' align-items: center;',
|
||||||
width: 100%;
|
' justify-content: center;',
|
||||||
height: 100%;
|
' box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);',
|
||||||
object-fit: cover;
|
' transition: transform 0.3s ease;',
|
||||||
transition: transform 0.3s ease;
|
'}',
|
||||||
}
|
'',
|
||||||
|
'/deep/ .jcdt-item .image img {',
|
||||||
/deep/ .jcdt-item .summary {
|
' width: 100%;',
|
||||||
font-size: 14px;
|
' height: 100%;',
|
||||||
color: #666;
|
' object-fit: cover;',
|
||||||
line-height: 1.6;
|
' transition: transform 0.3s ease;',
|
||||||
display: -webkit-box;
|
'}',
|
||||||
-webkit-line-clamp: 3;
|
'',
|
||||||
-webkit-box-orient: vertical;
|
'/deep/ .jcdt-item .summary {',
|
||||||
overflow: hidden;
|
' font-size: 14px;',
|
||||||
text-align: justify;
|
' color: #666;',
|
||||||
margin-bottom: 12px;
|
' line-height: 1.6;',
|
||||||
}
|
' display: -webkit-box;',
|
||||||
|
' -webkit-line-clamp: 3;',
|
||||||
/deep/ .jcdt-item i {
|
' -webkit-box-orient: vertical;',
|
||||||
color: #007aff;
|
' overflow: hidden;',
|
||||||
}
|
' text-align: justify;',
|
||||||
`
|
' margin-bottom: 12px;',
|
||||||
|
'}',
|
||||||
|
'',
|
||||||
|
'/deep/ .jcdt-item i {',
|
||||||
|
' color: #007aff;',
|
||||||
|
'}'
|
||||||
|
].join('')
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ const apply = {
|
|||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="预约开始时间" prop="reserveStartTime">
|
<el-form-item label="预约开始时间" prop="reserveStartTime">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
:key="'start-' + pickerRefreshKey"
|
:key="'start-' + pickerRefreshKey"
|
||||||
@@ -172,6 +172,24 @@ const apply = {
|
|||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="是否需要咖啡" prop="coffeeNeeded">
|
||||||
|
<el-radio-group v-model="formData.coffeeNeeded">
|
||||||
|
<el-radio :label="0">否</el-radio>
|
||||||
|
<el-radio :label="1">是</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="预约人数" prop="joinCount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.joinCount"
|
||||||
|
:min="1"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 160px">
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="批量预约">
|
<el-form-item label="批量预约">
|
||||||
<div style="display: flex; align-items: flex-start; column-gap: 12px; flex-wrap: wrap; line-height: 1.7;">
|
<div style="display: flex; align-items: flex-start; column-gap: 12px; flex-wrap: wrap; line-height: 1.7;">
|
||||||
@@ -239,6 +257,7 @@ const apply = {
|
|||||||
reserveStartTime: '',
|
reserveStartTime: '',
|
||||||
reserveEndTime: '',
|
reserveEndTime: '',
|
||||||
yearlyReserveEndDate: '',
|
yearlyReserveEndDate: '',
|
||||||
|
coffeeNeeded: 0,
|
||||||
joinCount: 1,
|
joinCount: 1,
|
||||||
applyCause: '',
|
applyCause: '',
|
||||||
},
|
},
|
||||||
@@ -251,7 +270,26 @@ const apply = {
|
|||||||
applyMobile: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
applyMobile: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
reserveStartTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
reserveStartTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
reserveEndTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
reserveEndTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
joinCount: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
coffeeNeeded: [{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value !== 0 && value !== 1) {
|
||||||
|
callback(new Error('请选择是否需要咖啡'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
}],
|
||||||
|
joinCount: [{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (!Number.isInteger(Number(value)) || Number(value) <= 0) {
|
||||||
|
callback(new Error('预约人数必须为大于0的整数'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
}],
|
||||||
applyCause: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
applyCause: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
clubId: [{
|
clubId: [{
|
||||||
validator: (rule, value, callback) => {
|
validator: (rule, value, callback) => {
|
||||||
@@ -451,6 +489,7 @@ const apply = {
|
|||||||
reserveStartTime: '',
|
reserveStartTime: '',
|
||||||
reserveEndTime: '',
|
reserveEndTime: '',
|
||||||
yearlyReserveEndDate: '',
|
yearlyReserveEndDate: '',
|
||||||
|
coffeeNeeded: 0,
|
||||||
joinCount: 1,
|
joinCount: 1,
|
||||||
applyCause: '',
|
applyCause: '',
|
||||||
}
|
}
|
||||||
@@ -679,10 +718,31 @@ const apply = {
|
|||||||
}
|
}
|
||||||
return timeStr.length === 5 ? timeStr + ':00' : timeStr
|
return timeStr.length === 5 ? timeStr + ':00' : timeStr
|
||||||
},
|
},
|
||||||
|
getDayWeekDay(dayStr) {
|
||||||
|
const target = this.$moment(dayStr, 'YYYY-MM-DD')
|
||||||
|
if (!target.isValid()) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
const weekDay = target.day()
|
||||||
|
return weekDay === 0 ? 7 : weekDay
|
||||||
|
},
|
||||||
|
isDateDisabledTime(item, dayStr) {
|
||||||
|
if (!item || !item.date) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const type = item.type || 'date'
|
||||||
|
return type === 'date' && this.$moment(item.date).format('YYYY-MM-DD') === dayStr
|
||||||
|
},
|
||||||
|
isWeekDisabledTime(item, dayStr) {
|
||||||
|
if (!item || item.type !== 'week') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return Number(item.weekDay) === this.getDayWeekDay(dayStr)
|
||||||
|
},
|
||||||
getDisabledRangesByDay(dayStr) {
|
getDisabledRangesByDay(dayStr) {
|
||||||
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
||||||
return list
|
return list
|
||||||
.filter(item => item && item.date && this.$moment(item.date).format('YYYY-MM-DD') === dayStr)
|
.filter(item => item && item.startTime && item.endTime && (this.isDateDisabledTime(item, dayStr) || this.isWeekDisabledTime(item, dayStr)))
|
||||||
.sort((a, b) => this.normalizeTime(a.startTime).localeCompare(this.normalizeTime(b.startTime)))
|
.sort((a, b) => this.normalizeTime(a.startTime).localeCompare(this.normalizeTime(b.startTime)))
|
||||||
},
|
},
|
||||||
buildSelectableRange(dateTimeValue) {
|
buildSelectableRange(dateTimeValue) {
|
||||||
@@ -742,15 +802,22 @@ const apply = {
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
overlapsDisabledRange(start, end) {
|
overlapsDisabledRange(start, end) {
|
||||||
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
const current = start.clone().startOf('day')
|
||||||
return list.some(item => {
|
const endDay = end.clone().startOf('day')
|
||||||
if (!item || !item.date || !item.startTime || !item.endTime) {
|
while (current.isSameOrBefore(endDay)) {
|
||||||
return false
|
const dayStr = current.format('YYYY-MM-DD')
|
||||||
|
const disabledRanges = this.getDisabledRangesByDay(dayStr)
|
||||||
|
const matched = disabledRanges.some(item => {
|
||||||
|
const rangeStart = this.$moment(dayStr + ' ' + this.normalizeTime(item.startTime))
|
||||||
|
const rangeEnd = this.$moment(dayStr + ' ' + this.normalizeTime(item.endTime))
|
||||||
|
return start.isBefore(rangeEnd) && end.isAfter(rangeStart)
|
||||||
|
})
|
||||||
|
if (matched) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
const rangeStart = this.$moment(this.$moment(item.date).format('YYYY-MM-DD') + ' ' + this.normalizeTime(item.startTime))
|
current.add(1, 'day')
|
||||||
const rangeEnd = this.$moment(this.$moment(item.date).format('YYYY-MM-DD') + ' ' + this.normalizeTime(item.endTime))
|
}
|
||||||
return start.isBefore(rangeEnd) && end.isAfter(rangeStart)
|
return false
|
||||||
})
|
|
||||||
},
|
},
|
||||||
validateTimeLimit(showMessage = true, startTime = this.formData.reserveStartTime, endTime = this.formData.reserveEndTime) {
|
validateTimeLimit(showMessage = true, startTime = this.formData.reserveStartTime, endTime = this.formData.reserveEndTime) {
|
||||||
if (!startTime || !endTime) {
|
if (!startTime || !endTime) {
|
||||||
|
|||||||
+368
@@ -0,0 +1,368 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
<style>
|
||||||
|
.audit-batch-toggle {
|
||||||
|
padding: 0;
|
||||||
|
color: #409EFF;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-empty {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-row {
|
||||||
|
background: #fafcff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #7a8a9a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-label::before {
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
height: 1px;
|
||||||
|
background: #c8d3df;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="姓名/工号">
|
||||||
|
<el-input
|
||||||
|
v-model="pageForm.searchKeyword"
|
||||||
|
placeholder="请输入姓名或工号"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="doSearch">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="活动场地">
|
||||||
|
<el-select
|
||||||
|
v-model="pageForm.siteId"
|
||||||
|
@change="doSearch"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择活动场地"
|
||||||
|
filterable
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in siteOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="场地类型">
|
||||||
|
<el-select
|
||||||
|
v-model="pageForm.siteType"
|
||||||
|
@change="doSearch"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择场地类型"
|
||||||
|
filterable
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in typeOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="分工会审核列表">
|
||||||
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</table-tool>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
:row-class-name="tableRowClassName"
|
||||||
|
@sort-change="pageOrder"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column label="" width="54" align="center" header-align="center">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button
|
||||||
|
v-if="row._hasFoldChildren"
|
||||||
|
class="audit-batch-toggle"
|
||||||
|
type="text"
|
||||||
|
@click="toggleBatchGroup(row)">
|
||||||
|
<i :class="row._expanded ? 'el-icon-caret-bottom' : 'el-icon-caret-right'"></i>
|
||||||
|
</el-button>
|
||||||
|
<span v-else class="audit-batch-empty"></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column type="index" width="50" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
:key="column.prop"
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'siteName'">
|
||||||
|
<span v-if="row._isBatchChild" class="audit-batch-child-label">{{ row.siteName }}</span>
|
||||||
|
<span v-else>{{ row.siteName }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'reserveTargetName'">
|
||||||
|
<span>{{ row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-') }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'yearlyBatch'">
|
||||||
|
<span>{{ normalizeBatchFlag(row) ? '是' : '否' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="220">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="!row._isBatchChild && row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
|
||||||
|
<el-button v-if="!row._isBatchChild && canRevoke(row)" :loading="revokeLoading" :disabled="revokeLoading" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<info ref="infoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">
|
||||||
|
{{ formData.taskName }}
|
||||||
|
</div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" class="flow-task-form">
|
||||||
|
<el-form-item
|
||||||
|
label="审批意见"
|
||||||
|
prop="tf_opinion"
|
||||||
|
:rules="[{ required: true, message: '必填', trigger: ['change', 'blur'] }]">
|
||||||
|
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end">
|
||||||
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
|
<el-button @click="handleTaskAction(6)" :loading="auditLoading" :disabled="auditLoading" size="small" type="info">退回到发起人</el-button>
|
||||||
|
<el-button @click="handleTaskAction(2)" :loading="auditLoading" :disabled="auditLoading" size="small" type="danger">拒绝申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(1)" :loading="auditLoading" :disabled="auditLoading" size="small" type="primary">同意申请</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</info>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/applyInfo.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
info: siteCugApplyInfo,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
approval: false,
|
||||||
|
},
|
||||||
|
rawTableData: [],
|
||||||
|
expandedBatchKeys: {},
|
||||||
|
tableColumns: [
|
||||||
|
{ prop: 'siteName', label: '场地名称', sortable: 'custom' },
|
||||||
|
{ prop: 'applyUserName', label: '预约人', sortable: 'custom' },
|
||||||
|
{ prop: 'applyLoginName', label: '工号', sortable: 'custom' },
|
||||||
|
{ prop: 'yearlyBatch', label: '是否批量预约', sortable: 'custom', width: 130 },
|
||||||
|
{ prop: 'reserveTargetName', label: '预约单位', sortable: 'custom' },
|
||||||
|
{ prop: 'reserveStartTime', label: '开始时间', sortable: 'custom' },
|
||||||
|
{ prop: 'reserveEndTime', label: '结束时间', sortable: 'custom' },
|
||||||
|
{ prop: 'applyMobile', label: '联系方式', sortable: 'custom' },
|
||||||
|
{ prop: 'curTaskName', label: '当前节点', sortable: 'custom' },
|
||||||
|
{ prop: 'instanceState', label: '流程状态', sortable: 'custom', width: 120 },
|
||||||
|
],
|
||||||
|
typeOptions: [],
|
||||||
|
siteOptions: [],
|
||||||
|
formData: {},
|
||||||
|
formRules: {},
|
||||||
|
showApprovalForm: false,
|
||||||
|
auditLoading: false,
|
||||||
|
revokeLoading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
normalizeBatchFlag(row) {
|
||||||
|
return row && (row.yearlyBatch === 1 || row.yearlyBatch === '1' || row.yearlyBatch === true)
|
||||||
|
},
|
||||||
|
getBatchGroupKey(row) {
|
||||||
|
if (!this.normalizeBatchFlag(row)) {
|
||||||
|
return 'single_' + row.id
|
||||||
|
}
|
||||||
|
const batchNo = row.backOption || row.id
|
||||||
|
return 'batch_' + batchNo + '_' + (row.applyUserName || '') + '_' + (row.siteName || '')
|
||||||
|
},
|
||||||
|
buildTableData(rows) {
|
||||||
|
const groups = new Map()
|
||||||
|
;(rows || []).forEach(row => {
|
||||||
|
const key = this.getBatchGroupKey(row)
|
||||||
|
if (!groups.has(key)) {
|
||||||
|
groups.set(key, [])
|
||||||
|
}
|
||||||
|
groups.get(key).push({ ...row })
|
||||||
|
})
|
||||||
|
const displayRows = []
|
||||||
|
groups.forEach((groupRows, key) => {
|
||||||
|
const sortedRows = groupRows.slice().sort((a, b) => {
|
||||||
|
return (b.reserveStartTime || '').localeCompare(a.reserveStartTime || '')
|
||||||
|
})
|
||||||
|
const parent = { ...sortedRows[0] }
|
||||||
|
const children = sortedRows.slice(1).map(item => ({
|
||||||
|
...item,
|
||||||
|
_isBatchChild: true,
|
||||||
|
_groupKey: key,
|
||||||
|
_hasFoldChildren: false,
|
||||||
|
}))
|
||||||
|
parent._groupKey = key
|
||||||
|
parent._isBatchChild = false
|
||||||
|
parent._hasFoldChildren = children.length > 0
|
||||||
|
parent._expanded = !!this.expandedBatchKeys[key]
|
||||||
|
parent._batchCount = sortedRows.length
|
||||||
|
parent._foldedRecords = children
|
||||||
|
displayRows.push(parent)
|
||||||
|
if (parent._expanded) {
|
||||||
|
displayRows.push(...children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return displayRows
|
||||||
|
},
|
||||||
|
tableRowClassName({ row }) {
|
||||||
|
return row && row._isBatchChild ? 'audit-batch-child-row' : ''
|
||||||
|
},
|
||||||
|
toggleBatchGroup(row) {
|
||||||
|
if (!row || !row._groupKey || !row._hasFoldChildren) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$set(this.expandedBatchKeys, row._groupKey, !this.expandedBatchKeys[row._groupKey])
|
||||||
|
this.tableData = this.buildTableData(this.rawTableData)
|
||||||
|
},
|
||||||
|
canRevoke(row) {
|
||||||
|
return Number(row.instanceState) === 20
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
applyId: row.id,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_opinion: '',
|
||||||
|
yearlyBatch: row.yearlyBatch,
|
||||||
|
batchAuditCount: row.batchAuditCount || row._batchCount,
|
||||||
|
}
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleTaskAction(val) {
|
||||||
|
if (this.auditLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const message = this.formData.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||||
|
: '您确定要提交吗?'
|
||||||
|
this.$confirm(message, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}).then(() => {
|
||||||
|
this.auditLoading = true
|
||||||
|
this.$axios.post(loc() + '/executeTask', {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: val,
|
||||||
|
}),
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.guava.index()
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
if (!this.canRevoke(row) || this.revokeLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const message = this.normalizeBatchFlag(row)
|
||||||
|
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || row._batchCount || 0) + ' 条审核任务,是否继续?')
|
||||||
|
: '您确定要撤回吗?'
|
||||||
|
this.$confirm(message, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'info',
|
||||||
|
}).then(() => {
|
||||||
|
this.revokeLoading = true
|
||||||
|
this.$axios.post(loc() + '/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.revokeLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
querySiteType() {
|
||||||
|
this.$axios.post('/platform/siteCug/function/type/queryFunctionType').then((res) => {
|
||||||
|
this.typeOptions = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySites() {
|
||||||
|
this.$axios.post('/platform/siteCug/manage/querySites').then((res) => {
|
||||||
|
this.siteOptions = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pageData() {
|
||||||
|
this.$axios.post(loc() + '/pageData', this.pageForm).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.rawTableData = Array.isArray(res.data.list) ? res.data.list : []
|
||||||
|
this.tableData = this.buildTableData(this.rawTableData)
|
||||||
|
this.pageForm.totalCount = res.data.totalCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.querySiteType()
|
||||||
|
this.querySites()
|
||||||
|
this.pageData()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -14,8 +14,9 @@ const siteCugApplyInfo = {
|
|||||||
<el-descriptions-item label="预约主体">{{ reserveTargetName }}</el-descriptions-item>
|
<el-descriptions-item label="预约主体">{{ reserveTargetName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="开始时间">{{ viewData.reserveStartTime }}</el-descriptions-item>
|
<el-descriptions-item label="开始时间">{{ viewData.reserveStartTime }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="结束时间">{{ viewData.reserveEndTime }}</el-descriptions-item>
|
<el-descriptions-item label="结束时间">{{ viewData.reserveEndTime }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否需要咖啡">{{ viewData.coffeeNeeded === 1 ? '是' : '否' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="预约人数">{{ viewData.joinCount || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="联系电话">{{ viewData.applyMobile }}</el-descriptions-item>
|
<el-descriptions-item label="联系电话">{{ viewData.applyMobile }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="预约人数">{{ viewData.joinCount }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="预约事由" :span="2">{{ viewData.applyCause }}</el-descriptions-item>
|
<el-descriptions-item label="预约事由" :span="2">{{ viewData.applyCause }}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
<template v-for="task in doneTasks">
|
<template v-for="task in doneTasks">
|
||||||
|
|||||||
+368
@@ -0,0 +1,368 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
<style>
|
||||||
|
.audit-batch-toggle {
|
||||||
|
padding: 0;
|
||||||
|
color: #409EFF;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-empty {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-row {
|
||||||
|
background: #fafcff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
color: #7a8a9a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.audit-batch-child-label::before {
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
height: 1px;
|
||||||
|
background: #c8d3df;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<guava ref="guava">
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="姓名/工号">
|
||||||
|
<el-input
|
||||||
|
v-model="pageForm.searchKeyword"
|
||||||
|
placeholder="请输入姓名或工号"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="doSearch">
|
||||||
|
</el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="活动场地">
|
||||||
|
<el-select
|
||||||
|
v-model="pageForm.siteId"
|
||||||
|
@change="doSearch"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择活动场地"
|
||||||
|
filterable
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in siteOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="场地类型">
|
||||||
|
<el-select
|
||||||
|
v-model="pageForm.siteType"
|
||||||
|
@change="doSearch"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择场地类型"
|
||||||
|
filterable
|
||||||
|
clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in typeOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool label="校工会副主席审核列表">
|
||||||
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</table-tool>
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
:row-class-name="tableRowClassName"
|
||||||
|
@sort-change="pageOrder"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-table-column label="" width="54" align="center" header-align="center">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button
|
||||||
|
v-if="row._hasFoldChildren"
|
||||||
|
class="audit-batch-toggle"
|
||||||
|
type="text"
|
||||||
|
@click="toggleBatchGroup(row)">
|
||||||
|
<i :class="row._expanded ? 'el-icon-caret-bottom' : 'el-icon-caret-right'"></i>
|
||||||
|
</el-button>
|
||||||
|
<span v-else class="audit-batch-empty"></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column type="index" width="50" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in tableColumns"
|
||||||
|
:key="column.prop"
|
||||||
|
:label="column.label"
|
||||||
|
:prop="column.prop"
|
||||||
|
:width="column.width"
|
||||||
|
:sortable="column.sortable"
|
||||||
|
align="center"
|
||||||
|
header-align="center"
|
||||||
|
show-overflow-tooltip>
|
||||||
|
<template v-slot="{ row }" v-if="column.prop === 'siteName'">
|
||||||
|
<span v-if="row._isBatchChild" class="audit-batch-child-label">{{ row.siteName }}</span>
|
||||||
|
<span v-else>{{ row.siteName }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'reserveTargetName'">
|
||||||
|
<span>{{ row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-') }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'yearlyBatch'">
|
||||||
|
<span>{{ normalizeBatchFlag(row) ? '是' : '否' }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-slot="{ row }" v-else-if="column.prop === 'instanceState'">
|
||||||
|
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="220">
|
||||||
|
<template v-slot="{ row }">
|
||||||
|
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||||
|
<el-button v-if="!row._isBatchChild && row.taskState === 10" @click="onAudit(row)" size="mini" type="primary">审核</el-button>
|
||||||
|
<el-button v-if="!row._isBatchChild && canRevoke(row)" :loading="revokeLoading" :disabled="revokeLoading" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<template #edit>
|
||||||
|
<info ref="infoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">
|
||||||
|
{{ formData.taskName }}
|
||||||
|
</div>
|
||||||
|
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" class="flow-task-form">
|
||||||
|
<el-form-item
|
||||||
|
label="审批意见"
|
||||||
|
prop="tf_opinion"
|
||||||
|
:rules="[{ required: true, message: '必填', trigger: ['change', 'blur'] }]">
|
||||||
|
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-row type="flex" justify="end">
|
||||||
|
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
|
||||||
|
<el-button @click="handleTaskAction(6)" :loading="auditLoading" :disabled="auditLoading" size="small" type="info">退回到发起人</el-button>
|
||||||
|
<el-button @click="handleTaskAction(2)" :loading="auditLoading" :disabled="auditLoading" size="small" type="danger">拒绝申请</el-button>
|
||||||
|
<el-button @click="handleTaskAction(1)" :loading="auditLoading" :disabled="auditLoading" size="small" type="primary">同意申请</el-button>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</info>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</guava>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/applyInfo.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
info: siteCugApplyInfo,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
approval: false,
|
||||||
|
},
|
||||||
|
rawTableData: [],
|
||||||
|
expandedBatchKeys: {},
|
||||||
|
tableColumns: [
|
||||||
|
{ prop: 'siteName', label: '场地名称', sortable: 'custom' },
|
||||||
|
{ prop: 'applyUserName', label: '预约人', sortable: 'custom' },
|
||||||
|
{ prop: 'applyLoginName', label: '工号', sortable: 'custom' },
|
||||||
|
{ prop: 'yearlyBatch', label: '是否批量预约', sortable: 'custom', width: 130 },
|
||||||
|
{ prop: 'reserveTargetName', label: '预约单位', sortable: 'custom' },
|
||||||
|
{ prop: 'reserveStartTime', label: '开始时间', sortable: 'custom' },
|
||||||
|
{ prop: 'reserveEndTime', label: '结束时间', sortable: 'custom' },
|
||||||
|
{ prop: 'applyMobile', label: '联系方式', sortable: 'custom' },
|
||||||
|
{ prop: 'curTaskName', label: '当前节点', sortable: 'custom' },
|
||||||
|
{ prop: 'instanceState', label: '流程状态', sortable: 'custom', width: 120 },
|
||||||
|
],
|
||||||
|
typeOptions: [],
|
||||||
|
siteOptions: [],
|
||||||
|
formData: {},
|
||||||
|
formRules: {},
|
||||||
|
showApprovalForm: false,
|
||||||
|
auditLoading: false,
|
||||||
|
revokeLoading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
normalizeBatchFlag(row) {
|
||||||
|
return row && (row.yearlyBatch === 1 || row.yearlyBatch === '1' || row.yearlyBatch === true)
|
||||||
|
},
|
||||||
|
getBatchGroupKey(row) {
|
||||||
|
if (!this.normalizeBatchFlag(row)) {
|
||||||
|
return 'single_' + row.id
|
||||||
|
}
|
||||||
|
const batchNo = row.backOption || row.id
|
||||||
|
return 'batch_' + batchNo + '_' + (row.applyUserName || '') + '_' + (row.siteName || '')
|
||||||
|
},
|
||||||
|
buildTableData(rows) {
|
||||||
|
const groups = new Map()
|
||||||
|
;(rows || []).forEach(row => {
|
||||||
|
const key = this.getBatchGroupKey(row)
|
||||||
|
if (!groups.has(key)) {
|
||||||
|
groups.set(key, [])
|
||||||
|
}
|
||||||
|
groups.get(key).push({ ...row })
|
||||||
|
})
|
||||||
|
const displayRows = []
|
||||||
|
groups.forEach((groupRows, key) => {
|
||||||
|
const sortedRows = groupRows.slice().sort((a, b) => {
|
||||||
|
return (b.reserveStartTime || '').localeCompare(a.reserveStartTime || '')
|
||||||
|
})
|
||||||
|
const parent = { ...sortedRows[0] }
|
||||||
|
const children = sortedRows.slice(1).map(item => ({
|
||||||
|
...item,
|
||||||
|
_isBatchChild: true,
|
||||||
|
_groupKey: key,
|
||||||
|
_hasFoldChildren: false,
|
||||||
|
}))
|
||||||
|
parent._groupKey = key
|
||||||
|
parent._isBatchChild = false
|
||||||
|
parent._hasFoldChildren = children.length > 0
|
||||||
|
parent._expanded = !!this.expandedBatchKeys[key]
|
||||||
|
parent._batchCount = sortedRows.length
|
||||||
|
parent._foldedRecords = children
|
||||||
|
displayRows.push(parent)
|
||||||
|
if (parent._expanded) {
|
||||||
|
displayRows.push(...children)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return displayRows
|
||||||
|
},
|
||||||
|
tableRowClassName({ row }) {
|
||||||
|
return row && row._isBatchChild ? 'audit-batch-child-row' : ''
|
||||||
|
},
|
||||||
|
toggleBatchGroup(row) {
|
||||||
|
if (!row || !row._groupKey || !row._hasFoldChildren) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$set(this.expandedBatchKeys, row._groupKey, !this.expandedBatchKeys[row._groupKey])
|
||||||
|
this.tableData = this.buildTableData(this.rawTableData)
|
||||||
|
},
|
||||||
|
canRevoke(row) {
|
||||||
|
return Number(row.instanceState) === 20
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.$refs.guava.edit(() => {
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
applyId: row.id,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_opinion: '',
|
||||||
|
yearlyBatch: row.yearlyBatch,
|
||||||
|
batchAuditCount: row.batchAuditCount || row._batchCount,
|
||||||
|
}
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleTaskAction(val) {
|
||||||
|
if (this.auditLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const message = this.formData.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||||
|
: '您确定要提交吗?'
|
||||||
|
this.$confirm(message, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}).then(() => {
|
||||||
|
this.auditLoading = true
|
||||||
|
this.$axios.post(loc() + '/executeTask', {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: val,
|
||||||
|
}),
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.guava.index()
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
if (!this.canRevoke(row) || this.revokeLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const message = this.normalizeBatchFlag(row)
|
||||||
|
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || row._batchCount || 0) + ' 条审核任务,是否继续?')
|
||||||
|
: '您确定要撤回吗?'
|
||||||
|
this.$confirm(message, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'info',
|
||||||
|
}).then(() => {
|
||||||
|
this.revokeLoading = true
|
||||||
|
this.$axios.post(loc() + '/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.revokeLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
querySiteType() {
|
||||||
|
this.$axios.post('/platform/siteCug/function/type/queryFunctionType').then((res) => {
|
||||||
|
this.typeOptions = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySites() {
|
||||||
|
this.$axios.post('/platform/siteCug/manage/querySites').then((res) => {
|
||||||
|
this.siteOptions = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pageData() {
|
||||||
|
this.$axios.post(loc() + '/pageData', this.pageForm).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.rawTableData = Array.isArray(res.data.list) ? res.data.list : []
|
||||||
|
this.tableData = this.buildTableData(this.rawTableData)
|
||||||
|
this.pageForm.totalCount = res.data.totalCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.querySiteType()
|
||||||
|
this.querySites()
|
||||||
|
this.pageData()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="禁用时间">
|
<el-form-item label="禁用时间">
|
||||||
<el-button type="primary" @click="openSetUpTime" size="small">点击设置禁用时间</el-button>
|
<el-button type="primary" @click="openSetUpTime" size="small">点击设置禁用时间</el-button>
|
||||||
<span style="color: #c64120">您已设置{{ formData.notApplyTimeList ? formData.notApplyTimeList.length : 0 }}个禁用时间</span>
|
<span style="color: #c64120">您已设置{{ disabledTimeCount }}个禁用时间</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -224,84 +224,167 @@
|
|||||||
<el-button @click="onSubmit" type="primary">正式提交</el-button>
|
<el-button @click="onSubmit" type="primary">正式提交</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="setUpTimeDialog" title="设置时间">
|
<el-dialog append-to-body :close-on-click-modal="false" :visible.sync="setUpTimeDialog" title="设置禁用时间" width="70%">
|
||||||
<div class="left-span-label">选择日期</div>
|
<el-tabs v-model="disabledTimeTab">
|
||||||
<el-date-picker
|
<el-tab-pane label="按日期" name="date">
|
||||||
@change="setUpDateChange"
|
<div class="left-span-label">选择日期</div>
|
||||||
placeholder="请选择一个或多个日期"
|
<el-date-picker
|
||||||
style="width: 100%"
|
@change="setUpDateChange"
|
||||||
type="dates"
|
placeholder="请选择一个或多个日期"
|
||||||
v-model="formData.setUpDate"
|
style="width: 100%"
|
||||||
value-format="yyyy-MM-dd">
|
type="dates"
|
||||||
</el-date-picker>
|
v-model="formData.setUpDate"
|
||||||
<div class="left-span-label mt20">设置禁用时间</div>
|
value-format="yyyy-MM-dd">
|
||||||
<el-row>
|
</el-date-picker>
|
||||||
<el-time-select
|
<div class="left-span-label mt20">设置禁用时间</div>
|
||||||
:picker-options="{
|
<el-row>
|
||||||
start: '00:00',
|
|
||||||
step: '00:05',
|
|
||||||
end: '23:55'
|
|
||||||
}"
|
|
||||||
placeholder="开始时间"
|
|
||||||
v-model="timeOneKeySet.startTime">
|
|
||||||
</el-time-select>
|
|
||||||
<el-time-select
|
|
||||||
:picker-options="{
|
|
||||||
start: '00:00',
|
|
||||||
step: '00:05',
|
|
||||||
end: '23:55'
|
|
||||||
}"
|
|
||||||
placeholder="结束时间"
|
|
||||||
v-model="timeOneKeySet.endTime">
|
|
||||||
</el-time-select>
|
|
||||||
<el-button @click="oneKeySetStartEndTime" type="primary">一键设置开始/结束时间</el-button>
|
|
||||||
</el-row>
|
|
||||||
<el-table :data="formData.notApplyTimeList" class="mt10" max-height="520px" size="mini" @selection-change="handleSelectionChange">
|
|
||||||
<el-table-column type="selection" width="55"></el-table-column>
|
|
||||||
<el-table-column label="日期" width="200">
|
|
||||||
<template v-slot="{row}">
|
|
||||||
<i class="el-icon-time"></i>
|
|
||||||
{{$moment(row.date).format('YYYY-MM-DD')}}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="开始时间">
|
|
||||||
<template v-slot="{row}">
|
|
||||||
<el-time-select
|
<el-time-select
|
||||||
size="mini"
|
|
||||||
:picker-options="{
|
:picker-options="{
|
||||||
start: '00:00',
|
start: '00:00',
|
||||||
step: '00:05',
|
step: '00:05',
|
||||||
end: '23:55'
|
end: '23:55'
|
||||||
}"
|
}"
|
||||||
v-model="row.startTime">
|
placeholder="开始时间"
|
||||||
|
v-model="timeOneKeySet.startTime">
|
||||||
</el-time-select>
|
</el-time-select>
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="结束时间">
|
|
||||||
<template v-slot="{row}">
|
|
||||||
<el-time-select
|
<el-time-select
|
||||||
size="mini"
|
|
||||||
:picker-options="{
|
:picker-options="{
|
||||||
start: '00:00',
|
start: '00:00',
|
||||||
step: '00:05',
|
step: '00:05',
|
||||||
end: '23:55'
|
end: '23:55'
|
||||||
}"
|
}"
|
||||||
v-model="row.endTime">
|
placeholder="结束时间"
|
||||||
|
v-model="timeOneKeySet.endTime">
|
||||||
</el-time-select>
|
</el-time-select>
|
||||||
</template>
|
<el-button @click="oneKeySetStartEndTime" type="primary">一键设置开始/结束时间</el-button>
|
||||||
</el-table-column>
|
</el-row>
|
||||||
<el-table-column label="操作" width="200">
|
<el-table :data="dateDisabledTimeList" class="mt10" max-height="520px" size="mini" @selection-change="handleSelectionChange">
|
||||||
<template v-slot="{row, $index}">
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
<el-button
|
<el-table-column label="日期" width="200">
|
||||||
size="mini"
|
<template v-slot="{row}">
|
||||||
@click="formData.notApplyTimeList.splice($index,0,{date:row.date,startTime:'',endTime:''})"
|
<i class="el-icon-time"></i>
|
||||||
type="primary">
|
{{$moment(row.date).format('YYYY-MM-DD')}}
|
||||||
新增同天时段
|
</template>
|
||||||
</el-button>
|
</el-table-column>
|
||||||
<el-button size="mini" @click="removeSetUpTableRow(row,$index)" type="danger">删除</el-button>
|
<el-table-column label="开始时间">
|
||||||
</template>
|
<template v-slot="{row}">
|
||||||
</el-table-column>
|
<el-time-select
|
||||||
</el-table>
|
size="mini"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
v-model="row.startTime">
|
||||||
|
</el-time-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="结束时间">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<el-time-select
|
||||||
|
size="mini"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
v-model="row.endTime">
|
||||||
|
</el-time-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="260" fixed="right">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
@click="addSameDayTime(row)"
|
||||||
|
type="primary">
|
||||||
|
新增同天时段
|
||||||
|
</el-button>
|
||||||
|
<el-button size="mini" @click="removeDisabledTimeRow(row)" type="danger">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="按星期" name="week">
|
||||||
|
<div class="left-span-label">选择星期</div>
|
||||||
|
<el-checkbox-group v-model="formData.setUpWeekDays" @change="setUpWeekChange">
|
||||||
|
<el-checkbox-button
|
||||||
|
v-for="item in weekOptions"
|
||||||
|
:label="item.value"
|
||||||
|
:key="item.value">
|
||||||
|
{{ item.label }}
|
||||||
|
</el-checkbox-button>
|
||||||
|
</el-checkbox-group>
|
||||||
|
<div class="left-span-label mt20">设置禁用时间</div>
|
||||||
|
<el-row>
|
||||||
|
<el-time-select
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
placeholder="开始时间"
|
||||||
|
v-model="timeOneKeySet.startTime">
|
||||||
|
</el-time-select>
|
||||||
|
<el-time-select
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
placeholder="结束时间"
|
||||||
|
v-model="timeOneKeySet.endTime">
|
||||||
|
</el-time-select>
|
||||||
|
<el-button @click="oneKeySetStartEndTime" type="primary">一键设置开始/结束时间</el-button>
|
||||||
|
</el-row>
|
||||||
|
<el-table :data="weekDisabledTimeList" class="mt10" max-height="520px" size="mini" @selection-change="handleWeekSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
|
<el-table-column label="星期" width="200">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<i class="el-icon-date"></i>
|
||||||
|
{{ row.weekName || getWeekName(row.weekDay) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="开始时间">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<el-time-select
|
||||||
|
size="mini"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
v-model="row.startTime">
|
||||||
|
</el-time-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="结束时间">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<el-time-select
|
||||||
|
size="mini"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:05',
|
||||||
|
end: '23:55'
|
||||||
|
}"
|
||||||
|
v-model="row.endTime">
|
||||||
|
</el-time-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="260" fixed="right">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
@click="addSameWeekTime(row)"
|
||||||
|
type="primary">
|
||||||
|
新增同星期时段
|
||||||
|
</el-button>
|
||||||
|
<el-button size="mini" @click="removeDisabledTimeRow(row)" type="danger">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
<el-row class="mt20" justify="end" type="flex">
|
<el-row class="mt20" justify="end" type="flex">
|
||||||
<el-button @click="setUpTimeDialog = false">取消</el-button>
|
<el-button @click="setUpTimeDialog = false">取消</el-button>
|
||||||
<el-button @click="doConfirmSetUpCourse" type="primary">确定</el-button>
|
<el-button @click="doConfirmSetUpCourse" type="primary">确定</el-button>
|
||||||
@@ -349,11 +432,22 @@
|
|||||||
reserveTimeType: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
reserveTimeType: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||||
},
|
},
|
||||||
setUpTimeDialog: false,
|
setUpTimeDialog: false,
|
||||||
|
disabledTimeTab: 'date',
|
||||||
|
weekOptions: [
|
||||||
|
{ value: 1, label: '星期一' },
|
||||||
|
{ value: 2, label: '星期二' },
|
||||||
|
{ value: 3, label: '星期三' },
|
||||||
|
{ value: 4, label: '星期四' },
|
||||||
|
{ value: 5, label: '星期五' },
|
||||||
|
{ value: 6, label: '星期六' },
|
||||||
|
{ value: 7, label: '星期日' },
|
||||||
|
],
|
||||||
timeOneKeySet: {
|
timeOneKeySet: {
|
||||||
startTime: "",
|
startTime: "",
|
||||||
endTime: ""
|
endTime: ""
|
||||||
},
|
},
|
||||||
multipleSelection: [],
|
multipleSelection: [],
|
||||||
|
weekMultipleSelection: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -368,6 +462,17 @@
|
|||||||
this.$set(this.formData.openHours[0], 'timeUnit', 30)
|
this.$set(this.formData.openHours[0], 'timeUnit', 30)
|
||||||
}
|
}
|
||||||
return this.formData.openHours[0]
|
return this.formData.openHours[0]
|
||||||
|
},
|
||||||
|
dateDisabledTimeList() {
|
||||||
|
this.normalizeDisabledTimeList()
|
||||||
|
return this.formData.notApplyTimeList.filter(item => this.isDateDisabledTime(item))
|
||||||
|
},
|
||||||
|
weekDisabledTimeList() {
|
||||||
|
this.normalizeDisabledTimeList()
|
||||||
|
return this.formData.notApplyTimeList.filter(item => this.isWeekDisabledTime(item))
|
||||||
|
},
|
||||||
|
disabledTimeCount() {
|
||||||
|
return Array.isArray(this.formData.notApplyTimeList) ? this.formData.notApplyTimeList.length : 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -400,6 +505,7 @@
|
|||||||
},
|
},
|
||||||
buildSubmitFormData() {
|
buildSubmitFormData() {
|
||||||
this.syncOpenHoursCache()
|
this.syncOpenHoursCache()
|
||||||
|
this.normalizeDisabledTimeList()
|
||||||
const submitData = clone(this.formData)
|
const submitData = clone(this.formData)
|
||||||
submitData.segmentedOpenHours = clone(this.segmentedOpenHoursCache || [])
|
submitData.segmentedOpenHours = clone(this.segmentedOpenHoursCache || [])
|
||||||
submitData.fullDayOpenHour = clone(this.fullDayOpenHourCache || { startTime: '', endTime: '', timeUnit: 30 })
|
submitData.fullDayOpenHour = clone(this.fullDayOpenHourCache || { startTime: '', endTime: '', timeUnit: 30 })
|
||||||
@@ -571,7 +677,16 @@
|
|||||||
doConfirmSetUpCourse() {
|
doConfirmSetUpCourse() {
|
||||||
const timeList = this.formData.notApplyTimeList
|
const timeList = this.formData.notApplyTimeList
|
||||||
if (timeList && timeList.length > 0) {
|
if (timeList && timeList.length > 0) {
|
||||||
const valid = timeList.every(v => v.date && v.startTime && v.endTime && (v.startTime < v.endTime))
|
const valid = timeList.every(v => {
|
||||||
|
const timeValid = v.startTime && v.endTime && (v.startTime < v.endTime)
|
||||||
|
if (!timeValid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (this.isWeekDisabledTime(v)) {
|
||||||
|
return !!v.weekDay
|
||||||
|
}
|
||||||
|
return !!v.date
|
||||||
|
})
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
this.$message.warning("时间不完整或者有误")
|
this.$message.warning("时间不完整或者有误")
|
||||||
return
|
return
|
||||||
@@ -579,58 +694,139 @@
|
|||||||
}
|
}
|
||||||
this.setUpTimeDialog = false
|
this.setUpTimeDialog = false
|
||||||
},
|
},
|
||||||
removeSetUpTableRow(row, index) {
|
normalizeDisabledTimeList() {
|
||||||
this.formData.notApplyTimeList.splice(index, 1)
|
if (!Array.isArray(this.formData.notApplyTimeList)) {
|
||||||
const dateArray = this.formData.notApplyTimeList.map(v => this.$moment(v.date).format("YYYY-MM-DD"))
|
this.$set(this.formData, 'notApplyTimeList', [])
|
||||||
const setUpDate = this.formData.setUpDate || []
|
}
|
||||||
this.formData.setUpDate = setUpDate.filter(v => {
|
this.formData.notApplyTimeList.forEach(item => {
|
||||||
return dateArray.includes(this.$moment(v).format("YYYY-MM-DD"))
|
if (!item) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (item.date && !item.type) {
|
||||||
|
this.$set(item, 'type', 'date')
|
||||||
|
}
|
||||||
|
if (item.type === 'week') {
|
||||||
|
this.$set(item, 'weekDay', Number(item.weekDay))
|
||||||
|
this.$set(item, 'weekName', item.weekName || this.getWeekName(item.weekDay))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
isDateDisabledTime(item) {
|
||||||
|
return item && (!item.type || item.type === 'date') && item.date
|
||||||
|
},
|
||||||
|
isWeekDisabledTime(item) {
|
||||||
|
return item && item.type === 'week'
|
||||||
|
},
|
||||||
|
getWeekName(weekDay) {
|
||||||
|
const current = this.weekOptions.find(item => Number(item.value) === Number(weekDay))
|
||||||
|
return current ? current.label : ''
|
||||||
|
},
|
||||||
|
removeDisabledTimeRow(row) {
|
||||||
|
const index = this.formData.notApplyTimeList.indexOf(row)
|
||||||
|
if (index >= 0) {
|
||||||
|
this.formData.notApplyTimeList.splice(index, 1)
|
||||||
|
}
|
||||||
|
this.refreshDisabledTimeSelectCache()
|
||||||
|
},
|
||||||
|
refreshDisabledTimeSelectCache() {
|
||||||
|
const dateArray = this.dateDisabledTimeList.map(v => this.$moment(v.date).format("YYYY-MM-DD"))
|
||||||
|
const setUpDate = this.formData.setUpDate || []
|
||||||
|
this.$set(this.formData, 'setUpDate', setUpDate.filter(v => {
|
||||||
|
return dateArray.includes(this.$moment(v).format("YYYY-MM-DD"))
|
||||||
|
}))
|
||||||
|
const weekDayArray = this.weekDisabledTimeList.map(v => Number(v.weekDay))
|
||||||
|
const setUpWeekDays = this.formData.setUpWeekDays || []
|
||||||
|
this.$set(this.formData, 'setUpWeekDays', setUpWeekDays.filter(v => {
|
||||||
|
return weekDayArray.includes(Number(v))
|
||||||
|
}))
|
||||||
|
},
|
||||||
handleSelectionChange(val) {
|
handleSelectionChange(val) {
|
||||||
this.multipleSelection = val
|
this.multipleSelection = val
|
||||||
},
|
},
|
||||||
|
handleWeekSelectionChange(val) {
|
||||||
|
this.weekMultipleSelection = val
|
||||||
|
},
|
||||||
oneKeySetStartEndTime() {
|
oneKeySetStartEndTime() {
|
||||||
if (this.multipleSelection.length === 0) {
|
const selection = this.disabledTimeTab === 'week' ? this.weekMultipleSelection : this.multipleSelection
|
||||||
|
if (selection.length === 0) {
|
||||||
this.$message.warning('请在下面表格多选框中选择需要一键设置的时间')
|
this.$message.warning('请在下面表格多选框中选择需要一键设置的时间')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { startTime, endTime } = this.timeOneKeySet
|
const { startTime, endTime } = this.timeOneKeySet
|
||||||
this.formData.notApplyTimeList.forEach(v => {
|
selection.forEach(v => {
|
||||||
const selected = this.multipleSelection.find(o => o.date === v.date && o.startTime === v.startTime && o.endTime === v.endTime)
|
this.$set(v, "startTime", startTime)
|
||||||
if (selected) {
|
this.$set(v, "endTime", endTime)
|
||||||
this.$set(v, "startTime", startTime)
|
|
||||||
this.$set(v, "endTime", endTime)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
this.$forceUpdate()
|
this.$forceUpdate()
|
||||||
},
|
},
|
||||||
setUpDateChange(val) {
|
setUpDateChange(val) {
|
||||||
|
const weekList = (this.formData.notApplyTimeList || []).filter(v => this.isWeekDisabledTime(v))
|
||||||
if (!val) {
|
if (!val) {
|
||||||
this.formData.notApplyTimeList = []
|
this.$set(this.formData, 'notApplyTimeList', weekList)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.formData.notApplyTimeList === undefined) {
|
if (this.formData.notApplyTimeList === undefined) {
|
||||||
this.$set(this.formData, "notApplyTimeList", [])
|
this.$set(this.formData, "notApplyTimeList", [])
|
||||||
}
|
}
|
||||||
const dateSet = new Set(this.formData.notApplyTimeList.map(v => this.$moment(v.date).format("YYYY-MM-DD")))
|
const dateSet = new Set(this.dateDisabledTimeList.map(v => this.$moment(v.date).format("YYYY-MM-DD")))
|
||||||
val.forEach(v => {
|
val.forEach(v => {
|
||||||
if (!dateSet.has(v)) {
|
if (!dateSet.has(v)) {
|
||||||
this.formData.notApplyTimeList.push({
|
this.formData.notApplyTimeList.push({
|
||||||
date: v, startTime: "", endTime: ""
|
type: 'date', date: v, startTime: "", endTime: ""
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.formData.notApplyTimeList = this.formData.notApplyTimeList.filter(v => {
|
const dateList = this.dateDisabledTimeList.filter(v => {
|
||||||
return val.includes(this.$moment(v.date).format("YYYY-MM-DD"))
|
return val.includes(this.$moment(v.date).format("YYYY-MM-DD"))
|
||||||
})
|
}).sort((a, b) => {
|
||||||
this.formData.notApplyTimeList.sort((a, b) => {
|
|
||||||
return Date.parse(a.date) - Date.parse(b.date)
|
return Date.parse(a.date) - Date.parse(b.date)
|
||||||
})
|
})
|
||||||
|
this.$set(this.formData, 'notApplyTimeList', dateList.concat(weekList))
|
||||||
|
},
|
||||||
|
setUpWeekChange(val) {
|
||||||
|
const dateList = (this.formData.notApplyTimeList || []).filter(v => this.isDateDisabledTime(v))
|
||||||
|
const weekSet = new Set(this.weekDisabledTimeList.map(v => Number(v.weekDay)))
|
||||||
|
val.forEach(v => {
|
||||||
|
if (!weekSet.has(Number(v))) {
|
||||||
|
this.formData.notApplyTimeList.push({
|
||||||
|
type: 'week',
|
||||||
|
weekDay: Number(v),
|
||||||
|
weekName: this.getWeekName(v),
|
||||||
|
startTime: '',
|
||||||
|
endTime: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const weekList = this.weekDisabledTimeList.filter(v => {
|
||||||
|
return val.map(item => Number(item)).includes(Number(v.weekDay))
|
||||||
|
}).sort((a, b) => {
|
||||||
|
return Number(a.weekDay) - Number(b.weekDay)
|
||||||
|
})
|
||||||
|
this.$set(this.formData, 'notApplyTimeList', dateList.concat(weekList))
|
||||||
|
},
|
||||||
|
addSameDayTime(row) {
|
||||||
|
const index = this.formData.notApplyTimeList.indexOf(row)
|
||||||
|
const data = { type: 'date', date: row.date, startTime: '', endTime: '' }
|
||||||
|
if (index >= 0) {
|
||||||
|
this.formData.notApplyTimeList.splice(index + 1, 0, data)
|
||||||
|
} else {
|
||||||
|
this.formData.notApplyTimeList.push(data)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addSameWeekTime(row) {
|
||||||
|
const index = this.formData.notApplyTimeList.indexOf(row)
|
||||||
|
const data = { type: 'week', weekDay: Number(row.weekDay), weekName: this.getWeekName(row.weekDay), startTime: '', endTime: '' }
|
||||||
|
if (index >= 0) {
|
||||||
|
this.formData.notApplyTimeList.splice(index + 1, 0, data)
|
||||||
|
} else {
|
||||||
|
this.formData.notApplyTimeList.push(data)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
openSetUpTime() {
|
openSetUpTime() {
|
||||||
|
this.normalizeDisabledTimeList()
|
||||||
if (this.formData.notApplyTimeList) {
|
if (this.formData.notApplyTimeList) {
|
||||||
this.$set(this.formData, 'setUpDate', this.formData.notApplyTimeList.map(o => o.date))
|
this.$set(this.formData, 'setUpDate', Array.from(new Set(this.dateDisabledTimeList.map(o => o.date))))
|
||||||
|
this.$set(this.formData, 'setUpWeekDays', Array.from(new Set(this.weekDisabledTimeList.map(o => Number(o.weekDay)))))
|
||||||
}
|
}
|
||||||
this.activeTab = 'siteSetting'
|
this.activeTab = 'siteSetting'
|
||||||
this.setUpTimeDialog = true
|
this.setUpTimeDialog = true
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ const siteInfo = {
|
|||||||
<el-descriptions-item label="禁用时间" :span="2">
|
<el-descriptions-item label="禁用时间" :span="2">
|
||||||
<el-table v-if="viewData.notApplyTimeList && viewData.notApplyTimeList.length > 0"
|
<el-table v-if="viewData.notApplyTimeList && viewData.notApplyTimeList.length > 0"
|
||||||
:data="viewData.notApplyTimeList" max-height="300" size="mini">
|
:data="viewData.notApplyTimeList" max-height="300" size="mini">
|
||||||
<el-table-column prop="date" label="日期"></el-table-column>
|
<el-table-column label="日期/星期">
|
||||||
|
<template v-slot="{row}">
|
||||||
|
{{ getDisabledTimeLabel(row) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="startTime" label="开始时间"></el-table-column>
|
<el-table-column prop="startTime" label="开始时间"></el-table-column>
|
||||||
<el-table-column prop="endTime" label="结束时间"></el-table-column>
|
<el-table-column prop="endTime" label="结束时间"></el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -92,6 +96,27 @@ const siteInfo = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getWeekName(weekDay) {
|
||||||
|
const weekNameMap = {
|
||||||
|
1: '星期一',
|
||||||
|
2: '星期二',
|
||||||
|
3: '星期三',
|
||||||
|
4: '星期四',
|
||||||
|
5: '星期五',
|
||||||
|
6: '星期六',
|
||||||
|
7: '星期日',
|
||||||
|
}
|
||||||
|
return weekNameMap[Number(weekDay)] || ''
|
||||||
|
},
|
||||||
|
getDisabledTimeLabel(item) {
|
||||||
|
if (!item) {
|
||||||
|
return '--'
|
||||||
|
}
|
||||||
|
if (item.type === 'week') {
|
||||||
|
return item.weekName || this.getWeekName(item.weekDay) || '--'
|
||||||
|
}
|
||||||
|
return item.date || '--'
|
||||||
|
},
|
||||||
onOpen(row) {
|
onOpen(row) {
|
||||||
this.activeTab = 'basicInfo'
|
this.activeTab = 'basicInfo'
|
||||||
this.viewData = row
|
this.viewData = row
|
||||||
|
|||||||
+3
-3
@@ -82,7 +82,7 @@ layout("/layouts/platform.html"){
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<table-tool label="申请列表">
|
<table-tool label="校工会主席审核列表">
|
||||||
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
|
||||||
<el-radio-button :label="true">已审核</el-radio-button>
|
<el-radio-button :label="true">已审核</el-radio-button>
|
||||||
<el-radio-button :label="false">未审核</el-radio-button>
|
<el-radio-button :label="false">未审核</el-radio-button>
|
||||||
@@ -296,7 +296,7 @@ layout("/layouts/platform.html"){
|
|||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.auditLoading = true
|
this.auditLoading = true
|
||||||
this.$axios.post('/platform/siteCug/schoolUnionAudit/executeTask', {
|
this.$axios.post(loc() + '/executeTask', {
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
...this.formData,
|
...this.formData,
|
||||||
submitType: val,
|
submitType: val,
|
||||||
@@ -325,7 +325,7 @@ layout("/layouts/platform.html"){
|
|||||||
type: 'info',
|
type: 'info',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.revokeLoading = true
|
this.revokeLoading = true
|
||||||
this.$axios.post('/platform/siteCug/schoolUnionAudit/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
this.$axios.post(loc() + '/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.$message.success(res.msg)
|
this.$message.success(res.msg)
|
||||||
this.doSearch()
|
this.doSearch()
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ new Vue({
|
|||||||
reserveStartTime: '',
|
reserveStartTime: '',
|
||||||
reserveEndTime: '',
|
reserveEndTime: '',
|
||||||
yearlyReserveEndDate: '',
|
yearlyReserveEndDate: '',
|
||||||
|
coffeeNeeded: 0,
|
||||||
joinCount: 1,
|
joinCount: 1,
|
||||||
applyCause: '',
|
applyCause: '',
|
||||||
},
|
},
|
||||||
@@ -219,6 +220,7 @@ new Vue({
|
|||||||
reserveStartTime: '',
|
reserveStartTime: '',
|
||||||
reserveEndTime: '',
|
reserveEndTime: '',
|
||||||
yearlyReserveEndDate: '',
|
yearlyReserveEndDate: '',
|
||||||
|
coffeeNeeded: 0,
|
||||||
joinCount: 1,
|
joinCount: 1,
|
||||||
applyCause: '',
|
applyCause: '',
|
||||||
}
|
}
|
||||||
@@ -700,6 +702,48 @@ new Vue({
|
|||||||
}
|
}
|
||||||
return timeStr.length === 5 ? timeStr + ':00' : timeStr
|
return timeStr.length === 5 ? timeStr + ':00' : timeStr
|
||||||
},
|
},
|
||||||
|
getWeekName(weekDay) {
|
||||||
|
const weekNameMap = {
|
||||||
|
1: '星期一',
|
||||||
|
2: '星期二',
|
||||||
|
3: '星期三',
|
||||||
|
4: '星期四',
|
||||||
|
5: '星期五',
|
||||||
|
6: '星期六',
|
||||||
|
7: '星期日',
|
||||||
|
}
|
||||||
|
return weekNameMap[Number(weekDay)] || ''
|
||||||
|
},
|
||||||
|
getDisabledTimeLabel(item) {
|
||||||
|
if (!item) {
|
||||||
|
return '--'
|
||||||
|
}
|
||||||
|
if (item.type === 'week') {
|
||||||
|
return item.weekName || this.getWeekName(item.weekDay) || '--'
|
||||||
|
}
|
||||||
|
return item.date || '--'
|
||||||
|
},
|
||||||
|
getDayWeekDay(dayStr) {
|
||||||
|
const target = this.$moment(dayStr, 'YYYY-MM-DD')
|
||||||
|
if (!target.isValid()) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
const weekDay = target.day()
|
||||||
|
return weekDay === 0 ? 7 : weekDay
|
||||||
|
},
|
||||||
|
isDateDisabledTime(item, dayStr) {
|
||||||
|
if (!item || !item.date) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const type = item.type || 'date'
|
||||||
|
return type === 'date' && this.$moment(item.date).format('YYYY-MM-DD') === dayStr
|
||||||
|
},
|
||||||
|
isWeekDisabledTime(item, dayStr) {
|
||||||
|
if (!item || item.type !== 'week') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return Number(item.weekDay) === this.getDayWeekDay(dayStr)
|
||||||
|
},
|
||||||
isDisabledDate(time) {
|
isDisabledDate(time) {
|
||||||
const day = this.$moment(time).format('YYYY-MM-DD')
|
const day = this.$moment(time).format('YYYY-MM-DD')
|
||||||
const today = this.$moment().startOf('day')
|
const today = this.$moment().startOf('day')
|
||||||
@@ -715,7 +759,7 @@ new Vue({
|
|||||||
getDisabledRangesByDay(dayStr) {
|
getDisabledRangesByDay(dayStr) {
|
||||||
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
||||||
return list
|
return list
|
||||||
.filter(item => item && item.date && this.$moment(item.date).format('YYYY-MM-DD') === dayStr)
|
.filter(item => item && item.startTime && item.endTime && (this.isDateDisabledTime(item, dayStr) || this.isWeekDisabledTime(item, dayStr)))
|
||||||
.sort((a, b) => this.normalizeTime(a.startTime).localeCompare(this.normalizeTime(b.startTime)))
|
.sort((a, b) => this.normalizeTime(a.startTime).localeCompare(this.normalizeTime(b.startTime)))
|
||||||
},
|
},
|
||||||
isDateTimeBlocked(dateTimeStr) {
|
isDateTimeBlocked(dateTimeStr) {
|
||||||
@@ -752,15 +796,22 @@ new Vue({
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
overlapsDisabledRange(start, end) {
|
overlapsDisabledRange(start, end) {
|
||||||
const list = Array.isArray(this.timeLimitConfig.notApplyTimeList) ? this.timeLimitConfig.notApplyTimeList : []
|
const current = start.clone().startOf('day')
|
||||||
return list.some(item => {
|
const endDay = end.clone().startOf('day')
|
||||||
if (!item || !item.date || !item.startTime || !item.endTime) {
|
while (current.isSameOrBefore(endDay)) {
|
||||||
return false
|
const dayStr = current.format('YYYY-MM-DD')
|
||||||
|
const disabledRanges = this.getDisabledRangesByDay(dayStr)
|
||||||
|
const matched = disabledRanges.some(item => {
|
||||||
|
const rangeStart = this.$moment(dayStr + ' ' + this.normalizeTime(item.startTime))
|
||||||
|
const rangeEnd = this.$moment(dayStr + ' ' + this.normalizeTime(item.endTime))
|
||||||
|
return start.isBefore(rangeEnd) && end.isAfter(rangeStart)
|
||||||
|
})
|
||||||
|
if (matched) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
const rangeStart = this.$moment(this.$moment(item.date).format('YYYY-MM-DD') + ' ' + this.normalizeTime(item.startTime))
|
current.add(1, 'day')
|
||||||
const rangeEnd = this.$moment(this.$moment(item.date).format('YYYY-MM-DD') + ' ' + this.normalizeTime(item.endTime))
|
}
|
||||||
return start.isBefore(rangeEnd) && end.isAfter(rangeStart)
|
return false
|
||||||
})
|
|
||||||
},
|
},
|
||||||
showSubmitError(message) {
|
showSubmitError(message) {
|
||||||
return this.$dialog.alert({
|
return this.$dialog.alert({
|
||||||
|
|||||||
+24
-2
@@ -379,8 +379,8 @@ layout("/layouts/platform_h5.html"){
|
|||||||
<div
|
<div
|
||||||
class="disabled-time-item"
|
class="disabled-time-item"
|
||||||
v-for="(item, index) in timeLimitConfig.notApplyTimeList"
|
v-for="(item, index) in timeLimitConfig.notApplyTimeList"
|
||||||
:key="item.date + item.startTime + item.endTime + index">
|
:key="(item.type || 'date') + (item.date || item.weekDay || '') + item.startTime + item.endTime + index">
|
||||||
{{ item.date }} {{ item.startTime }} - {{ item.endTime }}
|
{{ getDisabledTimeLabel(item) }} {{ item.startTime }} - {{ item.endTime }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>暂无禁用时段</div>
|
<div v-else>暂无禁用时段</div>
|
||||||
@@ -458,6 +458,28 @@ layout("/layouts/platform_h5.html"){
|
|||||||
@click="openAvailabilityPopup">
|
@click="openAvailabilityPopup">
|
||||||
</van-field>
|
</van-field>
|
||||||
<div v-if="selectionSummary" class="selection-summary">当前已选:{{ selectionSummary }}</div>
|
<div v-if="selectionSummary" class="selection-summary">当前已选:{{ selectionSummary }}</div>
|
||||||
|
<van-field
|
||||||
|
label="是否需要咖啡"
|
||||||
|
name="coffeeNeeded"
|
||||||
|
:rules="[{ validator: (value) => value === 0 || value === 1, message: '请选择是否需要咖啡' }]">
|
||||||
|
<template #input>
|
||||||
|
<van-radio-group
|
||||||
|
v-model="formData.coffeeNeeded"
|
||||||
|
direction="horizontal">
|
||||||
|
<van-radio :name="0">否</van-radio>
|
||||||
|
<van-radio :name="1">是</van-radio>
|
||||||
|
</van-radio-group>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field
|
||||||
|
v-model="formData.joinCount"
|
||||||
|
label="预约人数"
|
||||||
|
name="joinCount"
|
||||||
|
type="number"
|
||||||
|
required
|
||||||
|
placeholder="请输入预约人数"
|
||||||
|
:rules="[{ required: true, message: '请输入预约人数' }, { validator: (value) => Number.isInteger(Number(value)) && Number(value) > 0, message: '预约人数必须为大于0的整数' }]">
|
||||||
|
</van-field>
|
||||||
<van-cell title="批量预约">
|
<van-cell title="批量预约">
|
||||||
<template #default>
|
<template #default>
|
||||||
<van-switch v-model="yearlyReserve" size="22px"></van-switch>
|
<van-switch v-model="yearlyReserve" size="22px"></van-switch>
|
||||||
|
|||||||
+335
@@ -0,0 +1,335 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform_h5.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.site-cug-audit-page {
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f4f6f8;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.site-cug-audit-sticky {
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
.site-cug-audit-list-scroll {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 18px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.site-cug-audit-search /deep/ .van-search__content,
|
||||||
|
.site-cug-audit-search .van-search__content {
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
.site-cug-card-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.site-cug-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 22px;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #eef6ff;
|
||||||
|
color: #0b75bd;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.site-cug-tag.gray {
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
.site-cug-tag.warn {
|
||||||
|
background: #fff3e5;
|
||||||
|
color: #d97706;
|
||||||
|
}
|
||||||
|
.action-btn.disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.action-btn.loading {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.action-btn .van-loading {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" class="site-cug-audit-page" v-cloak>
|
||||||
|
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||||
|
|
||||||
|
<van-sticky offset-top="46px" class="site-cug-audit-sticky">
|
||||||
|
<van-search
|
||||||
|
class="site-cug-audit-search"
|
||||||
|
v-model="pageForm.searchKeyword"
|
||||||
|
show-action
|
||||||
|
clearable
|
||||||
|
input-align="left"
|
||||||
|
placeholder="请输入姓名/工号/场地搜索"
|
||||||
|
@search="doSearch"
|
||||||
|
@clear="doSearch">
|
||||||
|
<template #action>
|
||||||
|
<div @click="doSearch">搜索</div>
|
||||||
|
</template>
|
||||||
|
</van-search>
|
||||||
|
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||||
|
<van-dropdown-item v-model="pageForm.siteType" :options="typeOptions" :multiple="false" @change="doSearch"></van-dropdown-item>
|
||||||
|
<van-dropdown-item v-model="pageForm.siteId" :options="siteOptions" :multiple="false" @change="doSearch"></van-dropdown-item>
|
||||||
|
</van-dropdown-menu>
|
||||||
|
<van-tabs v-model="pageForm.approvalText" @change="onApprovalTabChange">
|
||||||
|
<van-tab title="已审核" name="1"></van-tab>
|
||||||
|
<van-tab title="未审核" name="0"></van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
</van-sticky>
|
||||||
|
|
||||||
|
<div class="site-cug-audit-list-scroll">
|
||||||
|
<table-list api="/platform/siteCug/branchUnionAudit/pageData" :page_form.sync="pageForm" ref="tableListRef" title="applyUserName" @ready="onReady">
|
||||||
|
<template v-slot="{index,row}">
|
||||||
|
<div class="site-cug-card-tags">
|
||||||
|
<span v-if="row.applyLoginName" class="site-cug-tag">{{ row.applyLoginName }}</span>
|
||||||
|
<span class="site-cug-tag gray">{{ reserveTypeText(row) }}</span>
|
||||||
|
<span v-if="row.yearlyBatch" class="site-cug-tag warn">预约本年</span>
|
||||||
|
</div>
|
||||||
|
<table-column label="场地名称">{{row.siteName}}</table-column>
|
||||||
|
<table-column label="预约主体">{{row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-')}}</table-column>
|
||||||
|
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
|
||||||
|
<table-column label="开始时间">{{row.reserveStartTime}}</table-column>
|
||||||
|
<table-column label="结束时间">{{row.reserveEndTime}}</table-column>
|
||||||
|
<table-column label="当前节点">{{row.curTaskName || '-'}}</table-column>
|
||||||
|
</template>
|
||||||
|
<template #actions="{index,row}">
|
||||||
|
<div class="action-btn" @click="onView(row)">
|
||||||
|
<i class="fa fa-eye"></i>
|
||||||
|
<span>查看</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn" v-if="row.taskState === 10" @click="onAudit(row)">
|
||||||
|
<i class="fa fa-edit"></i>
|
||||||
|
<span>审核</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn delete" v-if="canRevoke(row)" :class="{ loading: revokeLoading }" @click="onRevoke(row)">
|
||||||
|
<van-loading v-if="revokeLoading" size="14px" color="#fff"></van-loading>
|
||||||
|
<i v-else class="fa fa-reply"></i>
|
||||||
|
<span>撤回</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</table-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<info ref="infoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">{{formData.taskName}}</div>
|
||||||
|
<van-form ref="formRef">
|
||||||
|
<van-field
|
||||||
|
v-model="formData.tf_opinion"
|
||||||
|
name="tf_opinion"
|
||||||
|
label="审批意见"
|
||||||
|
placeholder="请输入审批意见"
|
||||||
|
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||||
|
required
|
||||||
|
maxlength="100"
|
||||||
|
show-word-limit
|
||||||
|
></van-field>
|
||||||
|
</van-form>
|
||||||
|
<div style="display:flex;justify-content:space-between;column-gap:10px;padding:10px;">
|
||||||
|
<van-button type="info" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||||
|
<van-button type="danger" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(2)">不同意</van-button>
|
||||||
|
<van-button type="primary" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</info>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/applyInfo.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
store,
|
||||||
|
components: {
|
||||||
|
info: siteCugApplyInfoH5,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
pageNumber: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
totalCount: 0,
|
||||||
|
searchKeyword: '',
|
||||||
|
approvalText: '0',
|
||||||
|
approval: false,
|
||||||
|
siteType: null,
|
||||||
|
siteId: null,
|
||||||
|
},
|
||||||
|
typeOptions: [
|
||||||
|
{
|
||||||
|
text: '全部类型',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
siteOptions: [
|
||||||
|
{
|
||||||
|
text: '全部场地',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
formData: {},
|
||||||
|
showApprovalForm: false,
|
||||||
|
auditLoading: false,
|
||||||
|
revokeLoading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
historyBack,
|
||||||
|
async onReady() {
|
||||||
|
await this.querySiteType()
|
||||||
|
await this.querySites()
|
||||||
|
this.doSearch()
|
||||||
|
},
|
||||||
|
onApprovalTabChange(val) {
|
||||||
|
this.pageForm.approval = val === '1'
|
||||||
|
this.doSearch()
|
||||||
|
},
|
||||||
|
canRevoke(row) {
|
||||||
|
return Number(row.instanceState) === 20
|
||||||
|
},
|
||||||
|
reserveTypeText(row) {
|
||||||
|
return row && row.reserveType === 'club' ? '协会预约' : '分工会预约'
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
applyId: row.id,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_opinion: '',
|
||||||
|
yearlyBatch: row.yearlyBatch,
|
||||||
|
batchAuditCount: row.batchAuditCount,
|
||||||
|
}
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
},
|
||||||
|
async handleTaskAction(submitType) {
|
||||||
|
if (this.auditLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.$refs.formRef.validate()
|
||||||
|
this.$dialog.confirm({
|
||||||
|
title: '提示',
|
||||||
|
message: this.formData.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||||
|
: '您确定要提交吗?',
|
||||||
|
}).then(() => {
|
||||||
|
this.auditLoading = true
|
||||||
|
this.$axios.post('/platform/siteCug/branchUnionAudit/executeTask', {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: submitType,
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.infoRef.onClose()
|
||||||
|
this.$toast.success(res.msg || '提交成功')
|
||||||
|
this.doSearch()
|
||||||
|
} else {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: res.msg || '提交失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: (err && err.msg) || '提交失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}).finally(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
if (!this.canRevoke(row) || this.revokeLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$dialog.confirm({
|
||||||
|
title: '提示',
|
||||||
|
message: row.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || 0) + ' 条审核任务,是否继续?')
|
||||||
|
: '您确定要撤回吗?',
|
||||||
|
}).then(() => {
|
||||||
|
this.revokeLoading = true
|
||||||
|
this.$axios.post('/platform/siteCug/branchUnionAudit/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$toast.success(res.msg || '撤回成功')
|
||||||
|
this.doSearch()
|
||||||
|
} else {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: res.msg || '撤回失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: (err && err.msg) || '撤回失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}).finally(() => {
|
||||||
|
this.revokeLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
querySiteType() {
|
||||||
|
return this.$axios.post('/platform/siteCug/function/type/queryFunctionType').then((res) => {
|
||||||
|
const list = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.typeOptions = [
|
||||||
|
{
|
||||||
|
text: '全部类型',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
].concat(list.map((item) => ({
|
||||||
|
text: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySites() {
|
||||||
|
return this.$axios.post('/platform/siteCug/manage/querySites').then((res) => {
|
||||||
|
const list = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.siteOptions = [
|
||||||
|
{
|
||||||
|
text: '全部场地',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
].concat(list.map((item) => ({
|
||||||
|
text: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
doSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.pageForm.pageNumber = 1
|
||||||
|
this.pageForm.totalCount = 0
|
||||||
|
this.$refs.tableListRef.doSearch()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -13,6 +13,8 @@ const siteCugApplyInfoH5 = {
|
|||||||
<van-cell title="预约主体">{{ reserveTargetName }}</van-cell>
|
<van-cell title="预约主体">{{ reserveTargetName }}</van-cell>
|
||||||
<van-cell title="开始时间">{{ viewData.reserveStartTime }}</van-cell>
|
<van-cell title="开始时间">{{ viewData.reserveStartTime }}</van-cell>
|
||||||
<van-cell title="结束时间">{{ viewData.reserveEndTime }}</van-cell>
|
<van-cell title="结束时间">{{ viewData.reserveEndTime }}</van-cell>
|
||||||
|
<van-cell title="是否需要咖啡">{{ viewData.coffeeNeeded ? '是' : '否' }}</van-cell>
|
||||||
|
<van-cell title="预约人数">{{ viewData.joinCount || '-' }}</van-cell>
|
||||||
<van-cell title="联系电话">{{ viewData.applyMobile }}</van-cell>
|
<van-cell title="联系电话">{{ viewData.applyMobile }}</van-cell>
|
||||||
<van-cell title="预约事由" class="direction-column-cell">{{ viewData.applyCause }}</van-cell>
|
<van-cell title="预约事由" class="direction-column-cell">{{ viewData.applyCause }}</van-cell>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ const siteInfo = {
|
|||||||
<table class="table-class">
|
<table class="table-class">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>日期</th>
|
<th>日期/星期</th>
|
||||||
<th>开始时间</th>
|
<th>开始时间</th>
|
||||||
<th>结束时间</th>
|
<th>结束时间</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(item, index) in viewData.notApplyTimeList" :key="item.date + item.startTime + item.endTime + index">
|
<tr v-for="(item, index) in viewData.notApplyTimeList" :key="(item.type || 'date') + (item.date || item.weekDay || '') + item.startTime + item.endTime + index">
|
||||||
<td>{{ item.date }}</td>
|
<td>{{ getDisabledTimeLabel(item) }}</td>
|
||||||
<td>{{ item.startTime }}</td>
|
<td>{{ item.startTime }}</td>
|
||||||
<td>{{ item.endTime }}</td>
|
<td>{{ item.endTime }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -71,6 +71,27 @@ const siteInfo = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getWeekName(weekDay) {
|
||||||
|
const weekNameMap = {
|
||||||
|
1: '星期一',
|
||||||
|
2: '星期二',
|
||||||
|
3: '星期三',
|
||||||
|
4: '星期四',
|
||||||
|
5: '星期五',
|
||||||
|
6: '星期六',
|
||||||
|
7: '星期日',
|
||||||
|
}
|
||||||
|
return weekNameMap[Number(weekDay)] || ''
|
||||||
|
},
|
||||||
|
getDisabledTimeLabel(item) {
|
||||||
|
if (!item) {
|
||||||
|
return '--'
|
||||||
|
}
|
||||||
|
if (item.type === 'week') {
|
||||||
|
return item.weekName || this.getWeekName(item.weekDay) || '--'
|
||||||
|
}
|
||||||
|
return item.date || '--'
|
||||||
|
},
|
||||||
onOpen(row) {
|
onOpen(row) {
|
||||||
this.viewData = row
|
this.viewData = row
|
||||||
this.visible = true
|
this.visible = true
|
||||||
|
|||||||
+335
@@ -0,0 +1,335 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform_h5.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.site-cug-audit-page {
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f4f6f8;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.site-cug-audit-sticky {
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
.site-cug-audit-list-scroll {
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 18px;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.site-cug-audit-search /deep/ .van-search__content,
|
||||||
|
.site-cug-audit-search .van-search__content {
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
.site-cug-card-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.site-cug-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 22px;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #eef6ff;
|
||||||
|
color: #0b75bd;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.site-cug-tag.gray {
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
.site-cug-tag.warn {
|
||||||
|
background: #fff3e5;
|
||||||
|
color: #d97706;
|
||||||
|
}
|
||||||
|
.action-btn.disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.action-btn.loading {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.action-btn .van-loading {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" class="site-cug-audit-page" v-cloak>
|
||||||
|
<van-nav-bar title="校工会副主席审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||||
|
|
||||||
|
<van-sticky offset-top="46px" class="site-cug-audit-sticky">
|
||||||
|
<van-search
|
||||||
|
class="site-cug-audit-search"
|
||||||
|
v-model="pageForm.searchKeyword"
|
||||||
|
show-action
|
||||||
|
clearable
|
||||||
|
input-align="left"
|
||||||
|
placeholder="请输入姓名/工号/场地搜索"
|
||||||
|
@search="doSearch"
|
||||||
|
@clear="doSearch">
|
||||||
|
<template #action>
|
||||||
|
<div @click="doSearch">搜索</div>
|
||||||
|
</template>
|
||||||
|
</van-search>
|
||||||
|
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||||
|
<van-dropdown-item v-model="pageForm.siteType" :options="typeOptions" :multiple="false" @change="doSearch"></van-dropdown-item>
|
||||||
|
<van-dropdown-item v-model="pageForm.siteId" :options="siteOptions" :multiple="false" @change="doSearch"></van-dropdown-item>
|
||||||
|
</van-dropdown-menu>
|
||||||
|
<van-tabs v-model="pageForm.approvalText" @change="onApprovalTabChange">
|
||||||
|
<van-tab title="已审核" name="1"></van-tab>
|
||||||
|
<van-tab title="未审核" name="0"></van-tab>
|
||||||
|
</van-tabs>
|
||||||
|
</van-sticky>
|
||||||
|
|
||||||
|
<div class="site-cug-audit-list-scroll">
|
||||||
|
<table-list api="/platform/siteCug/deputySchoolUnion/pageData" :page_form.sync="pageForm" ref="tableListRef" title="applyUserName" @ready="onReady">
|
||||||
|
<template v-slot="{index,row}">
|
||||||
|
<div class="site-cug-card-tags">
|
||||||
|
<span v-if="row.applyLoginName" class="site-cug-tag">{{ row.applyLoginName }}</span>
|
||||||
|
<span class="site-cug-tag gray">{{ reserveTypeText(row) }}</span>
|
||||||
|
<span v-if="row.yearlyBatch" class="site-cug-tag warn">预约本年</span>
|
||||||
|
</div>
|
||||||
|
<table-column label="场地名称">{{row.siteName}}</table-column>
|
||||||
|
<table-column label="预约主体">{{row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-')}}</table-column>
|
||||||
|
<table-column label="所属单位">{{row.applyUnitName}}</table-column>
|
||||||
|
<table-column label="开始时间">{{row.reserveStartTime}}</table-column>
|
||||||
|
<table-column label="结束时间">{{row.reserveEndTime}}</table-column>
|
||||||
|
<table-column label="当前节点">{{row.curTaskName || '-'}}</table-column>
|
||||||
|
</template>
|
||||||
|
<template #actions="{index,row}">
|
||||||
|
<div class="action-btn" @click="onView(row)">
|
||||||
|
<i class="fa fa-eye"></i>
|
||||||
|
<span>查看</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn" v-if="row.taskState === 10" @click="onAudit(row)">
|
||||||
|
<i class="fa fa-edit"></i>
|
||||||
|
<span>审核</span>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn delete" v-if="canRevoke(row)" :class="{ loading: revokeLoading }" @click="onRevoke(row)">
|
||||||
|
<van-loading v-if="revokeLoading" size="14px" color="#fff"></van-loading>
|
||||||
|
<i v-else class="fa fa-reply"></i>
|
||||||
|
<span>撤回</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</table-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<info ref="infoRef">
|
||||||
|
<div v-if="showApprovalForm">
|
||||||
|
<div class="process-title">{{formData.taskName}}</div>
|
||||||
|
<van-form ref="formRef">
|
||||||
|
<van-field
|
||||||
|
v-model="formData.tf_opinion"
|
||||||
|
name="tf_opinion"
|
||||||
|
label="审批意见"
|
||||||
|
placeholder="请输入审批意见"
|
||||||
|
:rules="[{ required: true, message: '请填写审批意见' }]"
|
||||||
|
required
|
||||||
|
maxlength="100"
|
||||||
|
show-word-limit
|
||||||
|
></van-field>
|
||||||
|
</van-form>
|
||||||
|
<div style="display:flex;justify-content:space-between;column-gap:10px;padding:10px;">
|
||||||
|
<van-button type="info" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(6)">退回</van-button>
|
||||||
|
<van-button type="danger" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(2)">不同意</van-button>
|
||||||
|
<van-button type="primary" block :loading="auditLoading" :disabled="auditLoading" @click="handleTaskAction(1)">同意</van-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</info>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script nonce="${cspNonce!}">
|
||||||
|
<!--#include('../common/applyInfo.js'){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
store,
|
||||||
|
components: {
|
||||||
|
info: siteCugApplyInfoH5,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
pageNumber: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
totalCount: 0,
|
||||||
|
searchKeyword: '',
|
||||||
|
approvalText: '0',
|
||||||
|
approval: false,
|
||||||
|
siteType: null,
|
||||||
|
siteId: null,
|
||||||
|
},
|
||||||
|
typeOptions: [
|
||||||
|
{
|
||||||
|
text: '全部类型',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
siteOptions: [
|
||||||
|
{
|
||||||
|
text: '全部场地',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
formData: {},
|
||||||
|
showApprovalForm: false,
|
||||||
|
auditLoading: false,
|
||||||
|
revokeLoading: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
historyBack,
|
||||||
|
async onReady() {
|
||||||
|
await this.querySiteType()
|
||||||
|
await this.querySites()
|
||||||
|
this.doSearch()
|
||||||
|
},
|
||||||
|
onApprovalTabChange(val) {
|
||||||
|
this.pageForm.approval = val === '1'
|
||||||
|
this.doSearch()
|
||||||
|
},
|
||||||
|
canRevoke(row) {
|
||||||
|
return Number(row.instanceState) === 20
|
||||||
|
},
|
||||||
|
reserveTypeText(row) {
|
||||||
|
return row && row.reserveType === 'club' ? '协会预约' : '分工会预约'
|
||||||
|
},
|
||||||
|
onView(row) {
|
||||||
|
this.showApprovalForm = false
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
},
|
||||||
|
onAudit(row) {
|
||||||
|
this.showApprovalForm = true
|
||||||
|
this.formData = {
|
||||||
|
processTaskId: row.taskId,
|
||||||
|
applyId: row.id,
|
||||||
|
taskName: row.curTaskName,
|
||||||
|
tf_opinion: '',
|
||||||
|
yearlyBatch: row.yearlyBatch,
|
||||||
|
batchAuditCount: row.batchAuditCount,
|
||||||
|
}
|
||||||
|
this.$refs.infoRef.onOpen(row)
|
||||||
|
},
|
||||||
|
async handleTaskAction(submitType) {
|
||||||
|
if (this.auditLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.$refs.formRef.validate()
|
||||||
|
this.$dialog.confirm({
|
||||||
|
title: '提示',
|
||||||
|
message: this.formData.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||||
|
: '您确定要提交吗?',
|
||||||
|
}).then(() => {
|
||||||
|
this.auditLoading = true
|
||||||
|
this.$axios.post('/platform/siteCug/deputySchoolUnion/executeTask', {
|
||||||
|
data: JSON.stringify({
|
||||||
|
...this.formData,
|
||||||
|
submitType: submitType,
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$refs.infoRef.onClose()
|
||||||
|
this.$toast.success(res.msg || '提交成功')
|
||||||
|
this.doSearch()
|
||||||
|
} else {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: res.msg || '提交失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: (err && err.msg) || '提交失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}).finally(() => {
|
||||||
|
this.auditLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRevoke(row) {
|
||||||
|
if (!this.canRevoke(row) || this.revokeLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$dialog.confirm({
|
||||||
|
title: '提示',
|
||||||
|
message: row.yearlyBatch
|
||||||
|
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || 0) + ' 条审核任务,是否继续?')
|
||||||
|
: '您确定要撤回吗?',
|
||||||
|
}).then(() => {
|
||||||
|
this.revokeLoading = true
|
||||||
|
this.$axios.post('/platform/siteCug/deputySchoolUnion/revokeTask', { taskId: row.taskId, applyId: row.id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$toast.success(res.msg || '撤回成功')
|
||||||
|
this.doSearch()
|
||||||
|
} else {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: res.msg || '撤回失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
this.$dialog.alert({
|
||||||
|
title: '提示',
|
||||||
|
message: (err && err.msg) || '撤回失败',
|
||||||
|
}).catch(() => {})
|
||||||
|
}).finally(() => {
|
||||||
|
this.revokeLoading = false
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
|
querySiteType() {
|
||||||
|
return this.$axios.post('/platform/siteCug/function/type/queryFunctionType').then((res) => {
|
||||||
|
const list = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.typeOptions = [
|
||||||
|
{
|
||||||
|
text: '全部类型',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
].concat(list.map((item) => ({
|
||||||
|
text: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
querySites() {
|
||||||
|
return this.$axios.post('/platform/siteCug/manage/querySites').then((res) => {
|
||||||
|
const list = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.siteOptions = [
|
||||||
|
{
|
||||||
|
text: '全部场地',
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
].concat(list.map((item) => ({
|
||||||
|
text: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
doSearch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.pageForm.pageNumber = 1
|
||||||
|
this.pageForm.totalCount = 0
|
||||||
|
this.$refs.tableListRef.doSearch()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
+1
-1
@@ -65,7 +65,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="app" class="site-cug-audit-page" v-cloak>
|
<div id="app" class="site-cug-audit-page" v-cloak>
|
||||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
<van-nav-bar title="校工会主席审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||||
|
|
||||||
<van-sticky offset-top="46px" class="site-cug-audit-sticky">
|
<van-sticky offset-top="46px" class="site-cug-audit-sticky">
|
||||||
<van-search
|
<van-search
|
||||||
|
|||||||
Reference in New Issue
Block a user