Merge branch 'main' of https://dd3skj.picp.vip/JyuHsin/zhgh_cug_v4
This commit is contained in:
+27
@@ -307,6 +307,9 @@ public class SiteCugApplyController {
|
||||
if (item == null || StrUtil.hasBlank(item.getReserveStartTime(), item.getReserveEndTime())) {
|
||||
continue;
|
||||
}
|
||||
if (isOccupiedByCurrentUser(item)) {
|
||||
continue;
|
||||
}
|
||||
DateTime reserveStart = DateUtil.parseDateTime(item.getReserveStartTime());
|
||||
DateTime reserveEnd = DateUtil.parseDateTime(item.getReserveEndTime());
|
||||
if (!reserveEnd.isAfter(reserveStart)) {
|
||||
@@ -389,6 +392,13 @@ public class SiteCugApplyController {
|
||||
}
|
||||
}
|
||||
|
||||
// 当前登录人占用了该预约时,该预约占用的时间块对当前登录人放开,对其他人仍保持锁定
|
||||
private boolean isOccupiedByCurrentUser(SiteCugApply apply) {
|
||||
return apply != null
|
||||
&& StrUtil.isNotBlank(apply.getOccupyUserId())
|
||||
&& StrUtil.equals(apply.getOccupyUserId(), SecurityUtil.getUserId());
|
||||
}
|
||||
|
||||
private boolean intersectsAny(int start, int end, List<int[]> ranges) {
|
||||
for (int[] range : ranges) {
|
||||
if (range != null && start < range[1] && end > range[0]) {
|
||||
@@ -821,5 +831,22 @@ public class SiteCugApplyController {
|
||||
for (ProcessTask task : doingTaskList) {
|
||||
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
|
||||
}
|
||||
if (applyService.shouldDirectFinishOccupiedApply(apply)) {
|
||||
directFinishOccupiedApply(instance, args);
|
||||
}
|
||||
}
|
||||
|
||||
// 占用人提交与占用时间交叉的预约时,复用已有流程引擎自动结束后续审核任务
|
||||
private void directFinishOccupiedApply(ProcessInstance instance, Dict args) {
|
||||
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
|
||||
if (doingTaskList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Dict directArgs = args.clone();
|
||||
directArgs.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.AGREE.getCode());
|
||||
directArgs.set(FlowConst.APPROVAL_COMMENT, "占用预约自动通过");
|
||||
for (ProcessTask task : doingTaskList) {
|
||||
flowEngine.executeAndJumpToEnd(task.getId(), FlowConst.AUTO_ID, directArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -105,6 +105,13 @@ public class SiteCugManageController {
|
||||
if ((fullDayOpenHour == null || fullDayOpenHour.isEmpty()) && info.getReserveTimeType() == 2 && info.getOpenHours() != null && !info.getOpenHours().isEmpty()) {
|
||||
fullDayOpenHour = info.getOpenHours().get(0);
|
||||
}
|
||||
// 场地预约次数限制作为后续提交校验的依据,保存场地时必须配置为正整数
|
||||
if (info.getUnionYearReserveLimit() == null || info.getUnionYearReserveLimit() <= 0) {
|
||||
return Result.error("分工会每年预约次数必须大于0");
|
||||
}
|
||||
if (info.getClubWeekReserveLimit() == null || info.getClubWeekReserveLimit() <= 0) {
|
||||
return Result.error("社团每周预约次数必须大于0");
|
||||
}
|
||||
if (info.getReserveTimeType() == 1) {
|
||||
if (segmentedOpenHours == null || segmentedOpenHours.isEmpty()) {
|
||||
return Result.error("Please add at least one booking slot");
|
||||
|
||||
+24
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.siteCug.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
@@ -24,6 +25,7 @@ import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@@ -87,6 +89,28 @@ public class SiteCugRecordController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("占用预约记录")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("siteCug.record")
|
||||
public Result occupy(@Param("id") String id, @Param("message") String message) {
|
||||
Map<Boolean, String> result = applyService.occupyRecord(id, message, false);
|
||||
return result.containsKey(false) ? Result.error(result.get(false)) : Result.success(result.get(true));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("批量占用预约记录")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("siteCug.record")
|
||||
public Result occupyBatch(@Param("ids") String ids, @Param("message") String message) {
|
||||
if (StrUtil.isBlank(ids)) {
|
||||
return Result.error("请选择需要占用的预约");
|
||||
}
|
||||
List<String> idList = StrUtil.split(ids, ",").stream().filter(StrUtil::isNotBlank).toList();
|
||||
Map<Boolean, String> result = applyService.occupyRecords(idList, message, false);
|
||||
return result.containsKey(false) ? Result.error(result.get(false)) : Result.success(result.get(true));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@ApiOperation("导出预约记录")
|
||||
|
||||
@@ -110,5 +110,15 @@ public class SiteCugApply extends BaseModel {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String backOption;
|
||||
|
||||
@Column
|
||||
@Comment("占用人ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String occupyUserId;
|
||||
|
||||
@Column
|
||||
@Comment("占用通知消息")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
||||
private String occupyMessage;
|
||||
|
||||
private String yearlyReserveEndDate;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,18 @@ public class SiteCugInfo extends BaseModel {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||
private String termEndDate;
|
||||
|
||||
@Column
|
||||
@Comment("分工会每年预约次数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
@Default("2")
|
||||
private Integer unionYearReserveLimit;
|
||||
|
||||
@Column
|
||||
@Comment("社团每周预约次数")
|
||||
@ColDefine(type = ColType.INT)
|
||||
@Default("2")
|
||||
private Integer clubWeekReserveLimit;
|
||||
|
||||
@Column
|
||||
@Comment("场地的禁用时间")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
|
||||
+10
@@ -7,6 +7,7 @@ import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface SiteCugApplyService extends BaseService<SiteCugApply> {
|
||||
@@ -21,4 +22,13 @@ public interface SiteCugApplyService extends BaseService<SiteCugApply> {
|
||||
|
||||
// 场馆预约查询页的导出逻辑统一放在 service,controller 只负责接收请求
|
||||
void exportRecord(SiteCugRecordPageForm pageForm, HttpServletResponse response);
|
||||
|
||||
// 占用单条预约记录,保存占用人和通知内容;真实发送消息代码当前保留为注释,便于测试流程
|
||||
Map<Boolean, String> occupyRecord(String id, String message, boolean sendMsg);
|
||||
|
||||
// 批量占用预约记录,先统一校验再保存,避免出现部分记录已占用、部分记录失败的状态
|
||||
Map<Boolean, String> occupyRecords(List<String> ids, String message, boolean sendMsg);
|
||||
|
||||
// 判断当前预约是否命中当前登录人的占用时间段,命中后提交预约可自动通过审核
|
||||
boolean shouldDirectFinishOccupiedApply(SiteCugApply apply);
|
||||
}
|
||||
|
||||
+246
-7
@@ -10,10 +10,10 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||
import com.budwk.app.sys.models.SysHoliday;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.services.SysMsgService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.club.model.SysClub;
|
||||
import com.budwk.app.zhgh.club.service.SysClubService;
|
||||
@@ -46,6 +46,8 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
|
||||
@Inject
|
||||
private SysClubService sysClubService;
|
||||
@Inject
|
||||
private SysMsgService sysMsgService;
|
||||
|
||||
public SiteCugApplyServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
@@ -78,6 +80,10 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
if (!Boolean.TRUE.equals(siteInfo.getState())) {
|
||||
return Map.of(false, "该场地未开启预约");
|
||||
}
|
||||
Map<Boolean, String> termDateRangeValidate = validateTermDateRange(apply, siteInfo);
|
||||
if (termDateRangeValidate.containsKey(false)) {
|
||||
return termDateRangeValidate;
|
||||
}
|
||||
if (apply.getJoinCount() == null || apply.getJoinCount() <= 0) {
|
||||
return Map.of(false, "预约人数必须大于0");
|
||||
}
|
||||
@@ -96,6 +102,10 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
if (intersectsDisabledTime(siteInfo, apply.getReserveStartTime(), apply.getReserveEndTime())) {
|
||||
return Map.of(false, "预约时间落在禁用时间内");
|
||||
}
|
||||
Map<Boolean, String> reserveLimitValidate = validateReserveLimit(apply, siteInfo);
|
||||
if (reserveLimitValidate.containsKey(false)) {
|
||||
return reserveLimitValidate;
|
||||
}
|
||||
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
@@ -108,8 +118,7 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and(SiteCugApply::getSiteId, "=", apply.getSiteId());
|
||||
cnd.andEX("sa.id", "!=", apply.getId());
|
||||
List<Integer> stateList = List.of(ProcessInstanceStateEnum.DOING.getCode(), ProcessInstanceStateEnum.FINISHED.getCode(), ProcessInstanceStateEnum.PENDING.getCode());
|
||||
cnd.and(ProcessInstance::getState, "in", stateList);
|
||||
cnd.and("ins.state", "in", buildEffectiveProcessStateList());
|
||||
sql.setCondition(cnd);
|
||||
List<SiteCugApply> applyList = listEntity(sql);
|
||||
|
||||
@@ -118,6 +127,9 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
boolean overlap = DateUtil.parseDateTime(item.getReserveStartTime()).isBefore(DateUtil.parseDateTime(apply.getReserveEndTime()))
|
||||
&& DateUtil.parseDateTime(item.getReserveEndTime()).isAfter(DateUtil.parseDateTime(apply.getReserveStartTime()));
|
||||
if (overlap) {
|
||||
if (isOccupiedByCurrentUser(item)) {
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isBlank(apply.getId()) && StrUtil.equals(item.getApplyUserId(), SecurityUtil.getUserId())) {
|
||||
return Map.of(false, "该时间段您已存在预约");
|
||||
}
|
||||
@@ -127,6 +139,236 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
return Map.of(true, "");
|
||||
}
|
||||
|
||||
// 分工会预约必须落在后台配置的本学期时间内,批量预约逐条复用该校验防止接口越权提交学期外日期
|
||||
private Map<Boolean, String> validateTermDateRange(SiteCugApply apply, SiteCugInfo siteInfo) {
|
||||
if (!StrUtil.equals(apply.getReserveType(), "union")
|
||||
|| StrUtil.hasBlank(siteInfo.getTermStartDate(), siteInfo.getTermEndDate())) {
|
||||
return Map.of(true, "");
|
||||
}
|
||||
try {
|
||||
DateTime reserveStart = DateUtil.parseDateTime(apply.getReserveStartTime());
|
||||
DateTime reserveEnd = DateUtil.parseDateTime(apply.getReserveEndTime());
|
||||
Date termStart = DateUtil.beginOfDay(DateUtil.parseDate(siteInfo.getTermStartDate()));
|
||||
Date termEnd = DateUtil.endOfDay(DateUtil.parseDate(siteInfo.getTermEndDate()));
|
||||
if (reserveStart.isBefore(termStart) || reserveEnd.isAfter(termEnd)) {
|
||||
return Map.of(false, "预约时间必须在本学期时间范围内");
|
||||
}
|
||||
return Map.of(true, "");
|
||||
} catch (Exception e) {
|
||||
return Map.of(false, "本学期时间配置有误,请联系管理员处理");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Boolean, String> occupyRecord(String id, String message, boolean sendMsg) {
|
||||
if (StrUtil.isBlank(message)) {
|
||||
return Map.of(false, "请填写通知消息");
|
||||
}
|
||||
SiteCugApply apply = fetch(id);
|
||||
if (apply == null) {
|
||||
return Map.of(false, "记录不存在");
|
||||
}
|
||||
Map<Boolean, String> validate = validateOccupyApply(apply);
|
||||
if (validate.containsKey(false)) {
|
||||
return validate;
|
||||
}
|
||||
saveOccupyApply(apply, message, sendMsg);
|
||||
return Map.of(true, "占用成功");
|
||||
}
|
||||
|
||||
// 已通过校验后统一保存占用信息;测试阶段真实发送消息代码保留注释
|
||||
private void saveOccupyApply(SiteCugApply apply, String message, boolean sendMsg) {
|
||||
// 保存占用人和通知内容,后续预约校验据此只放行当前占用人
|
||||
apply.setOccupyUserId(SecurityUtil.getUserId());
|
||||
apply.setOccupyMessage(message);
|
||||
updateIgnoreNull(apply);
|
||||
// 测试占用流程时先不真实发送消息,保留日志用于确认保存和跳转链路是否正常
|
||||
log.info("场地预约占用测试消息,applyId={},receiverLoginName={},message={}", apply.getId(), apply.getApplyLoginName(), message);
|
||||
if (sendMsg) {
|
||||
// sysMsgService.sendMsgInSys(List.of(apply.getApplyLoginName()), "场地预约占用通知", message, SecurityUtil.getUserId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Boolean, String> occupyRecords(List<String> ids, String message, boolean sendMsg) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return Map.of(false, "请选择需要占用的预约");
|
||||
}
|
||||
if (StrUtil.isBlank(message)) {
|
||||
return Map.of(false, "请填写通知消息");
|
||||
}
|
||||
List<SiteCugApply> applyList = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
SiteCugApply apply = fetch(id);
|
||||
if (apply == null) {
|
||||
return Map.of(false, "记录不存在");
|
||||
}
|
||||
Map<Boolean, String> validate = validateOccupyApply(apply);
|
||||
if (validate.containsKey(false)) {
|
||||
return validate;
|
||||
}
|
||||
applyList.add(apply);
|
||||
}
|
||||
for (SiteCugApply apply : applyList) {
|
||||
saveOccupyApply(apply, message, sendMsg);
|
||||
}
|
||||
return Map.of(true, "占用成功");
|
||||
}
|
||||
|
||||
// 占用前统一校验预约状态,避免单条和批量接口出现不同判断
|
||||
private Map<Boolean, String> validateOccupyApply(SiteCugApply apply) {
|
||||
if (StrUtil.isBlank(apply.getApplyLoginName())) {
|
||||
return Map.of(false, "预约人工号为空,无法发送消息");
|
||||
}
|
||||
if (StrUtil.isBlank(apply.getReserveStartTime()) || !DateUtil.parseDateTime(apply.getReserveStartTime()).isAfter(DateUtil.date())) {
|
||||
return Map.of(false, "预约已开始,不能占用");
|
||||
}
|
||||
Integer state = queryInstanceState(apply.getId());
|
||||
if (state == null || state != ProcessInstanceStateEnum.FINISHED.getCode()) {
|
||||
return Map.of(false, "仅可占用已通过且未开始的预约记录");
|
||||
}
|
||||
if (StrUtil.isNotBlank(apply.getOccupyUserId()) && !StrUtil.equals(apply.getOccupyUserId(), SecurityUtil.getUserId())) {
|
||||
return Map.of(false, "该预约已被其他人占用");
|
||||
}
|
||||
return Map.of(true, "");
|
||||
}
|
||||
|
||||
private Integer queryInstanceState(String id) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
ins.state AS instanceState
|
||||
FROM
|
||||
site_cug_apply info
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
|
||||
WHERE info.id = @id
|
||||
""");
|
||||
sql.params().set("id", id);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
dao().execute(sql);
|
||||
List<NutMap> list = sql.getList(NutMap.class);
|
||||
return list != null && !list.isEmpty() ? list.get(0).getInt("instanceState") : null;
|
||||
}
|
||||
|
||||
// 当前登录人占用了该记录时,允许其再次提交与该记录有交叉的预约
|
||||
private boolean isOccupiedByCurrentUser(SiteCugApply apply) {
|
||||
return apply != null
|
||||
&& StrUtil.isNotBlank(apply.getOccupyUserId())
|
||||
&& StrUtil.equals(apply.getOccupyUserId(), SecurityUtil.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDirectFinishOccupiedApply(SiteCugApply apply) {
|
||||
if (apply == null || StrUtil.hasBlank(apply.getSiteId(), apply.getReserveStartTime(), apply.getReserveEndTime())) {
|
||||
return false;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
sa.*
|
||||
from
|
||||
site_cug_apply sa
|
||||
left join wf_process_instance ins on ins.businessNo = sa.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("sa.siteId", "=", apply.getSiteId());
|
||||
cnd.andEX("sa.id", "!=", apply.getId());
|
||||
cnd.and("sa.occupyUserId", "=", SecurityUtil.getUserId());
|
||||
cnd.and("ins.state", "=", ProcessInstanceStateEnum.FINISHED.getCode());
|
||||
sql.setCondition(cnd);
|
||||
List<SiteCugApply> applyList = listEntity(sql);
|
||||
|
||||
// 只要新预约时间和当前登录人占用的已通过预约有交叉,就允许本次预约免审通过
|
||||
return applyList.stream().anyMatch(item ->
|
||||
DateUtil.parseDateTime(item.getReserveStartTime()).isBefore(DateUtil.parseDateTime(apply.getReserveEndTime()))
|
||||
&& DateUtil.parseDateTime(item.getReserveEndTime()).isAfter(DateUtil.parseDateTime(apply.getReserveStartTime()))
|
||||
);
|
||||
}
|
||||
|
||||
// 按预约主体统计有效预约次数,批量预约同一个批次号只计一次,避免一次批量提交占用多次额度
|
||||
private Map<Boolean, String> validateReserveLimit(SiteCugApply apply, SiteCugInfo siteInfo) {
|
||||
if (StrUtil.equals(apply.getReserveType(), "union")) {
|
||||
if (siteInfo.getUnionYearReserveLimit() == null || siteInfo.getUnionYearReserveLimit() <= 0) {
|
||||
return Map.of(false, "请先配置分工会每年预约次数");
|
||||
}
|
||||
String[] range = buildYearRange(apply.getReserveStartTime());
|
||||
long count = countEffectiveReserveTimes(apply, "sa.applyUnionId", apply.getApplyUnionId(), range[0], range[1]);
|
||||
if (count >= siteInfo.getUnionYearReserveLimit()) {
|
||||
return Map.of(false, "该分工会本年度预约次数已达" + siteInfo.getUnionYearReserveLimit() + "次,不能继续预约");
|
||||
}
|
||||
}
|
||||
if (StrUtil.equals(apply.getReserveType(), "club")) {
|
||||
if (siteInfo.getClubWeekReserveLimit() == null || siteInfo.getClubWeekReserveLimit() <= 0) {
|
||||
return Map.of(false, "请先配置社团每周预约次数");
|
||||
}
|
||||
String[] range = buildWeekRange(apply.getReserveStartTime());
|
||||
long count = countEffectiveReserveTimes(apply, "sa.clubId", apply.getClubId(), range[0], range[1]);
|
||||
if (count >= siteInfo.getClubWeekReserveLimit()) {
|
||||
return Map.of(false, "该协会本周预约次数已达" + siteInfo.getClubWeekReserveLimit() + "次,不能继续预约");
|
||||
}
|
||||
}
|
||||
return Map.of(true, "");
|
||||
}
|
||||
|
||||
// 分工会每年次数按预约开始时间所在自然年统计
|
||||
private String[] buildYearRange(String reserveStartTime) {
|
||||
DateTime reserveStart = DateUtil.parseDateTime(reserveStartTime);
|
||||
String year = String.valueOf(reserveStart.year());
|
||||
return new String[]{year + "-01-01 00:00:00", year + "-12-31 23:59:59"};
|
||||
}
|
||||
|
||||
// 协会每周次数按自然周统计,周一为开始、周日为结束
|
||||
private String[] buildWeekRange(String reserveStartTime) {
|
||||
DateTime reserveStart = DateUtil.parseDateTime(reserveStartTime);
|
||||
int week = reserveStart.dayOfWeek() - 1;
|
||||
int offsetToMonday = week == 0 ? -6 : 1 - week;
|
||||
DateTime weekStart = DateUtil.offsetDay(reserveStart, offsetToMonday);
|
||||
DateTime weekEnd = DateUtil.offsetDay(weekStart, 6);
|
||||
return new String[]{DateUtil.formatDate(weekStart) + " 00:00:00", DateUtil.formatDate(weekEnd) + " 23:59:59"};
|
||||
}
|
||||
|
||||
// 统计预约主体在指定时间范围内的有效预约次数,所有场地合计,不按场地过滤
|
||||
private long countEffectiveReserveTimes(SiteCugApply apply, String targetField, String targetId, String rangeStart, String rangeEnd) {
|
||||
if (StrUtil.isBlank(targetId)) {
|
||||
return 0;
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
select
|
||||
sa.*
|
||||
from
|
||||
site_cug_apply sa
|
||||
left join wf_process_instance ins on ins.businessNo = sa.id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("sa.reserveType", "=", apply.getReserveType());
|
||||
cnd.andEX(targetField, "=", targetId);
|
||||
cnd.andEX("sa.reserveStartTime", ">=", rangeStart);
|
||||
cnd.andEX("sa.reserveStartTime", "<=", rangeEnd);
|
||||
if (StrUtil.isNotBlank(apply.getId())) {
|
||||
cnd.andEX("sa.id", "!=", apply.getId());
|
||||
}
|
||||
cnd.and("ins.state", "in", buildEffectiveProcessStateList());
|
||||
sql.setCondition(cnd);
|
||||
List<SiteCugApply> applyList = listEntity(sql);
|
||||
return applyList.stream()
|
||||
.map(this::buildReserveCountKey)
|
||||
.distinct()
|
||||
.count();
|
||||
}
|
||||
|
||||
// 只有待审核、办理中、已通过的流程占用预约次数,驳回记录不占额度
|
||||
private List<Integer> buildEffectiveProcessStateList() {
|
||||
return List.of(ProcessInstanceStateEnum.DOING.getCode(), ProcessInstanceStateEnum.FINISHED.getCode(), ProcessInstanceStateEnum.PENDING.getCode());
|
||||
}
|
||||
|
||||
// 批量预约同一批次号只算一次,普通预约按单条申请计算
|
||||
private String buildReserveCountKey(SiteCugApply apply) {
|
||||
if (apply != null && StrUtil.isNotBlank(apply.getBackOption()) && apply.getBackOption().startsWith("YEARLY_BATCH:")) {
|
||||
return apply.getBackOption();
|
||||
}
|
||||
return apply == null ? "" : apply.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sql buildRecordSql() {
|
||||
// 场馆预约查询页和导出页共用同一套返回字段,统一在 service 中维护,避免 controller 重复拼 SQL
|
||||
@@ -135,6 +377,7 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
info.*,
|
||||
si.name AS siteName,
|
||||
ins.id AS instanceId,
|
||||
ins.state AS instanceState,
|
||||
ins.processDefineId instanceProcessDefineId,
|
||||
CASE WHEN info.backOption LIKE 'YEARLY_BATCH:%' THEN 1 ELSE 0 END AS yearlyBatch,
|
||||
CASE WHEN info.reserveType = 'club' THEN '协会预约' ELSE '分工会预约' END AS reserveTypeName,
|
||||
@@ -315,7 +558,3 @@ public class SiteCugApplyServiceImpl extends BaseServiceImpl<SiteCugApply> imple
|
||||
return Map.of(false, "预约类型不合法");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -175,9 +175,9 @@ const apply = {
|
||||
<el-col :span="24">
|
||||
<el-form-item label="批量预约">
|
||||
<div style="display: flex; align-items: flex-start; column-gap: 12px; flex-wrap: wrap; line-height: 1.7;">
|
||||
<el-checkbox v-model="yearlyReserve">预约本年后续每周同一时段</el-checkbox>
|
||||
<el-checkbox v-model="yearlyReserve">预约本月后续每周同一时段</el-checkbox>
|
||||
<span style="color: #909399;">
|
||||
例如先选某个周一 09:00-11:00,勾选后会自动预约本年剩余所有周一的这个时段。
|
||||
例如先选某个周一 09:00-11:00,勾选后会自动预约本月剩余所有周一的这个时段。
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="yearlyReserve" style="margin-top: 10px; max-width: 320px;">
|
||||
@@ -344,7 +344,10 @@ const apply = {
|
||||
if (!this.formData.reserveStartTime) {
|
||||
return false
|
||||
}
|
||||
return this.$moment(time).format('YYYY-MM-DD') < this.formData.reserveStartTime.slice(0, 10)
|
||||
const targetDay = this.$moment(time).format('YYYY-MM-DD')
|
||||
const startDay = this.formData.reserveStartTime.slice(0, 10)
|
||||
const monthEndDay = this.$moment(this.formData.reserveStartTime).endOf('month').format('YYYY-MM-DD')
|
||||
return targetDay < startDay || targetDay > monthEndDay
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -397,10 +400,10 @@ const apply = {
|
||||
return ''
|
||||
}
|
||||
if (!this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
return '请先选择开始和结束时间后,再批量预约本年同星期时段'
|
||||
return '请先选择开始和结束时间后,再批量预约本月同星期时段'
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
return '当前时间段无法生成本年批量预约日期'
|
||||
return '当前时间段无法生成本月批量预约日期'
|
||||
}
|
||||
return '将从 ' + this.yearlyReserveDates[0] + ' 开始,自动预约到 ' + this.yearlyReserveDates[this.yearlyReserveDates.length - 1] + ',共 ' + this.yearlyReserveDates.length + ' 个时段'
|
||||
},
|
||||
@@ -498,6 +501,10 @@ const apply = {
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate < this.formData.reserveStartTime.slice(0, 10)) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
return
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate > defaultDate) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
}
|
||||
},
|
||||
getInitialScheduleDate() {
|
||||
@@ -1020,12 +1027,16 @@ const apply = {
|
||||
this.$message.warning('批量预约截止日期不能早于开始日期')
|
||||
return false
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate > this.$moment(this.formData.reserveStartTime).endOf('month').format('YYYY-MM-DD')) {
|
||||
this.$message.warning('批量预约截止日期不能超过预约开始时间所在月份')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('当前选择的时间段在截止日期内无法生成可批量预约的日期')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('当前选择的时间段无法生成本年批量预约日期')
|
||||
this.$message.warning('当前选择的时间段无法生成本月批量预约日期')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -1038,7 +1049,7 @@ const apply = {
|
||||
if (!this.yearlyReserve) {
|
||||
return baseText + ',是否确定提交预约?'
|
||||
}
|
||||
return baseText + '。系统将继续预约本年后续 ' + this.yearlyReserveDates.length + ' 个同星期时段,是否确定提交?'
|
||||
return baseText + '。系统将继续预约本月后续 ' + this.yearlyReserveDates.length + ' 个同星期时段,是否确定提交?'
|
||||
},
|
||||
validateYearlyReserve() {
|
||||
if (!this.yearlyReserve) {
|
||||
@@ -1052,6 +1063,10 @@ const apply = {
|
||||
this.$message.warning('批量预约截止日期不能早于开始日期')
|
||||
return false
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate > this.$moment(this.formData.reserveStartTime).endOf('month').format('YYYY-MM-DD')) {
|
||||
this.$message.warning('批量预约截止日期不能超过预约开始时间所在月份')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('当前选择的时间段在截止日期内无法生成可批量预约的日期')
|
||||
return false
|
||||
|
||||
@@ -138,6 +138,33 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20" type="flex">
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="unionYearReserveLimit" label="分工会每年预约次数">
|
||||
<el-input-number
|
||||
v-model="formData.unionYearReserveLimit"
|
||||
:min="1"
|
||||
:step="1"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
style="width: 160px">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="clubWeekReserveLimit" label="社团每周预约次数">
|
||||
<el-input-number
|
||||
v-model="formData.clubWeekReserveLimit"
|
||||
:min="1"
|
||||
:step="1"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
style="width: 160px">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider content-position="left">场次信息</el-divider>
|
||||
|
||||
<div v-if="formData.reserveTimeType === 1">
|
||||
@@ -339,6 +366,8 @@
|
||||
state: true,
|
||||
sexLimit: 0,
|
||||
termDateRange: [],
|
||||
unionYearReserveLimit: 2,
|
||||
clubWeekReserveLimit: 2,
|
||||
filterHolidays: false,
|
||||
reserveTimeType: 1,
|
||||
openHours: [{ startTime: '', endTime: '', timeUnit: 30 }],
|
||||
@@ -358,6 +387,8 @@
|
||||
maxNum: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
typeId: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
sexLimit: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
unionYearReserveLimit: [{required: true, type: 'number', min: 1, message: '必填且必须大于0', trigger: ['blur', 'change']}],
|
||||
clubWeekReserveLimit: [{required: true, type: 'number', min: 1, message: '必填且必须大于0', trigger: ['blur', 'change']}],
|
||||
filterHolidays: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
state: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
reserveTimeType: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
@@ -687,6 +718,8 @@
|
||||
state: true,
|
||||
sexLimit: 0,
|
||||
termDateRange: [],
|
||||
unionYearReserveLimit: 2,
|
||||
clubWeekReserveLimit: 2,
|
||||
filterHolidays: false,
|
||||
reserveTimeType: 1,
|
||||
openHours: [{ startTime: '', endTime: '', timeUnit: 30 }],
|
||||
|
||||
@@ -9,9 +9,7 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
|
||||
.record-batch-empty {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.record-batch-child-row {
|
||||
@@ -31,6 +29,13 @@ layout("/layouts/platform.html"){
|
||||
height: 1px;
|
||||
background: #c8d3df;
|
||||
}
|
||||
|
||||
.record-site-name-cell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
@@ -113,25 +118,16 @@ layout("/layouts/platform.html"){
|
||||
|
||||
<el-card shadow="never">
|
||||
<table-tool label="申请列表">
|
||||
<el-button v-if="$auth.hasRole('SYSADMIN')" type="primary" size="small" @click="openBatchOccupyDialog">占用</el-button>
|
||||
<el-button type="primary" size="small" @click="doExport">导出表格</el-button>
|
||||
</table-tool>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
:row-class-name="tableRowClassName"
|
||||
@selection-change="handleSelectionChange"
|
||||
@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="record-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="record-batch-empty"></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="$auth.hasRole('SYSADMIN')" type="selection" width="48" :selectable="canSelectOccupy"></el-table-column>
|
||||
<el-table-column type="index" width="50" label="序号" :index="indexMethod"></el-table-column>
|
||||
<el-table-column
|
||||
v-for="column in tableColumns"
|
||||
@@ -144,8 +140,18 @@ layout("/layouts/platform.html"){
|
||||
header-align="center"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot="{ row }" v-if="column.prop === 'siteName'">
|
||||
<span v-if="row._isBatchChild" class="record-batch-child-label">{{ row.siteName }}</span>
|
||||
<span v-else>{{ row.siteName }}</span>
|
||||
<span class="record-site-name-cell">
|
||||
<el-button
|
||||
v-if="row._hasFoldChildren"
|
||||
class="record-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="record-batch-empty"></span>
|
||||
<span v-if="row._isBatchChild" class="record-batch-child-label">{{ row.siteName }}</span>
|
||||
<span v-else>{{ row.siteName }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot="{ row }" v-else-if="column.prop === 'reserveTargetName'">
|
||||
<span>{{ row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-') }}</span>
|
||||
@@ -154,7 +160,7 @@ layout("/layouts/platform.html"){
|
||||
<span>{{ normalizeBatchFlag(row) ? '是' : '否' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="180">
|
||||
<el-table-column label="操作" fixed="right" width="150">
|
||||
<template v-slot="{ row }">
|
||||
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
|
||||
<el-button @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
|
||||
@@ -163,6 +169,32 @@ layout("/layouts/platform.html"){
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-dialog title="占用预约" :visible.sync="occupyDialogVisible" width="520px" append-to-body :close-on-click-modal="false">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="预约信息">
|
||||
<div v-if="occupyForm.batch">已选择 {{ occupyForm.count }} 条预约</div>
|
||||
<template v-else>
|
||||
<div>{{ occupyForm.siteName || '-' }}</div>
|
||||
<div>{{ occupyForm.applyUserName || '-' }}:{{ occupyForm.reserveStartTime }} 至 {{ occupyForm.reserveEndTime }}</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知内容" required>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
v-model="occupyForm.message"
|
||||
placeholder="请输入发送给预约人的通知内容">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeOccupyDialog">取消</el-button>
|
||||
<el-button type="primary" :loading="occupySubmitting" @click="submitOccupy">确定占用</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<template #edit>
|
||||
@@ -195,6 +227,20 @@ layout("/layouts/platform.html"){
|
||||
siteOptions: [],
|
||||
rawTableData: [],
|
||||
expandedBatchKeys: {},
|
||||
selectedOccupyRows: [],
|
||||
occupyDialogVisible: false,
|
||||
occupySubmitting: false,
|
||||
occupyForm: {
|
||||
id: '',
|
||||
ids: '',
|
||||
batch: false,
|
||||
count: 0,
|
||||
siteName: '',
|
||||
applyUserName: '',
|
||||
reserveStartTime: '',
|
||||
reserveEndTime: '',
|
||||
message: '',
|
||||
},
|
||||
tableColumns: [
|
||||
{ prop: 'siteName', label: '场地名称', sortable: 'custom' },
|
||||
{ prop: 'applyUserName', label: '预约人', sortable: 'custom' },
|
||||
@@ -267,6 +313,99 @@ layout("/layouts/platform.html"){
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
})
|
||||
},
|
||||
canSelectOccupy(row) {
|
||||
return this.canOccupy(row)
|
||||
},
|
||||
handleSelectionChange(rows) {
|
||||
this.$set(this, 'selectedOccupyRows', rows || [])
|
||||
},
|
||||
canOccupy(row) {
|
||||
if (!row || !row.reserveStartTime) {
|
||||
return false
|
||||
}
|
||||
const currentUserId = (this.$store.state.user && this.$store.state.user.id) || ''
|
||||
if (row.occupyUserId && row.occupyUserId !== currentUserId) {
|
||||
return false
|
||||
}
|
||||
return Number(row.instanceState) === 20 && this.$moment(row.reserveStartTime).isAfter(this.$moment())
|
||||
},
|
||||
buildOccupyMessage(row) {
|
||||
return '您预约的' + (row.siteName || '场地') + '(' + row.reserveStartTime + ' 至 ' + row.reserveEndTime + ')因场地安排需要被占用,请您知悉并重新协调预约时间。'
|
||||
},
|
||||
openOccupyDialog(row) {
|
||||
const occupyForm = {
|
||||
id: row.id || '',
|
||||
ids: row.id || '',
|
||||
batch: false,
|
||||
count: 1,
|
||||
siteName: row.siteName || '',
|
||||
applyUserName: row.applyUserName || '',
|
||||
reserveStartTime: row.reserveStartTime || '',
|
||||
reserveEndTime: row.reserveEndTime || '',
|
||||
message: row.occupyMessage || this.buildOccupyMessage(row),
|
||||
}
|
||||
Object.keys(occupyForm).forEach(key => {
|
||||
this.$set(this.occupyForm, key, occupyForm[key])
|
||||
})
|
||||
this.$set(this, 'occupyDialogVisible', true)
|
||||
},
|
||||
openBatchOccupyDialog() {
|
||||
if (!this.selectedOccupyRows || this.selectedOccupyRows.length === 0) {
|
||||
this.$message.warning('请选择需要占用的预约')
|
||||
return
|
||||
}
|
||||
const ids = this.selectedOccupyRows.map(row => row.id).filter(id => !!id)
|
||||
if (ids.length === 0) {
|
||||
this.$message.warning('请选择需要占用的预约')
|
||||
return
|
||||
}
|
||||
const occupyForm = {
|
||||
id: '',
|
||||
ids: ids.join(','),
|
||||
batch: true,
|
||||
count: ids.length,
|
||||
siteName: '',
|
||||
applyUserName: '',
|
||||
reserveStartTime: '',
|
||||
reserveEndTime: '',
|
||||
message: '您预约的场地因场地安排需要被占用,请您知悉并重新协调预约时间。',
|
||||
}
|
||||
Object.keys(occupyForm).forEach(key => {
|
||||
this.$set(this.occupyForm, key, occupyForm[key])
|
||||
})
|
||||
this.$set(this, 'occupyDialogVisible', true)
|
||||
},
|
||||
closeOccupyDialog() {
|
||||
this.$set(this, 'occupyDialogVisible', false)
|
||||
},
|
||||
async submitOccupy() {
|
||||
if (!this.occupyForm.message || !this.occupyForm.message.trim()) {
|
||||
this.$message.warning('请填写通知内容')
|
||||
return
|
||||
}
|
||||
this.$set(this, 'occupySubmitting', true)
|
||||
try {
|
||||
const url = this.occupyForm.batch ? '/platform/siteCug/record/occupyBatch' : '/platform/siteCug/record/occupy'
|
||||
const params = {
|
||||
message: this.occupyForm.message,
|
||||
}
|
||||
if (this.occupyForm.batch) {
|
||||
this.$set(params, 'ids', this.occupyForm.ids)
|
||||
} else {
|
||||
this.$set(params, 'id', this.occupyForm.id)
|
||||
}
|
||||
const res = await this.$axios.post(url, params)
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg || '占用成功')
|
||||
this.closeOccupyDialog()
|
||||
window.location.href = '/platform/siteCug/apply'
|
||||
} else {
|
||||
this.$message.warning(res.msg || '占用失败')
|
||||
}
|
||||
} finally {
|
||||
this.$set(this, 'occupySubmitting', false)
|
||||
}
|
||||
},
|
||||
onDelete(id) {
|
||||
this.$confirm('您确定要删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -299,6 +438,7 @@ layout("/layouts/platform.html"){
|
||||
if (res.code === 0) {
|
||||
this.rawTableData = Array.isArray(res.data.list) ? res.data.list : []
|
||||
this.tableData = this.buildTableData(this.rawTableData)
|
||||
this.$set(this, 'selectedOccupyRows', [])
|
||||
this.pageForm.totalCount = res.data.totalCount
|
||||
}
|
||||
})
|
||||
|
||||
+2
-2
@@ -288,7 +288,7 @@ layout("/layouts/platform.html"){
|
||||
return
|
||||
}
|
||||
const message = this.formData.yearlyBatch
|
||||
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||
? ('该记录属于“预约本月”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||
: '您确定要提交吗?'
|
||||
this.$confirm(message, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -317,7 +317,7 @@ layout("/layouts/platform.html"){
|
||||
return
|
||||
}
|
||||
const message = this.normalizeBatchFlag(row)
|
||||
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || row._batchCount || 0) + ' 条审核任务,是否继续?')
|
||||
? ('该记录属于“预约本月”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || row._batchCount || 0) + ' 条审核任务,是否继续?')
|
||||
: '您确定要撤回吗?'
|
||||
this.$confirm(message, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
|
||||
@@ -142,7 +142,10 @@ new Vue({
|
||||
return base.startOf('day').toDate()
|
||||
},
|
||||
yearlyReserveMaxDate() {
|
||||
return this.$moment().add(2, 'year').endOf('year').toDate()
|
||||
const base = this.formData.reserveStartTime
|
||||
? this.$moment(this.formData.reserveStartTime)
|
||||
: (this.scheduleDate ? this.$moment(this.scheduleDate, 'YYYY-MM-DD') : this.$moment())
|
||||
return base.endOf('month').toDate()
|
||||
},
|
||||
yearlyReserveDates() {
|
||||
if (!this.yearlyReserve || !this.formData.reserveStartTime || !this.formData.reserveEndTime || !this.formData.yearlyReserveEndDate) {
|
||||
@@ -255,6 +258,10 @@ new Vue({
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate < this.formData.reserveStartTime.slice(0, 10)) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
return
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate > defaultDate) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
}
|
||||
},
|
||||
openReserveTypePicker() {
|
||||
@@ -488,6 +495,20 @@ new Vue({
|
||||
result.push('slot-block--closed')
|
||||
return result
|
||||
},
|
||||
formatSlotLabel(block) {
|
||||
const label = block && block.label ? block.label : ''
|
||||
const match = label.match(/^(.+?)\s+(\d{2}:\d{2}(?::\d{2})?\s*-\s*\d{2}:\d{2}(?::\d{2})?)$/)
|
||||
if (match) {
|
||||
return {
|
||||
name: match[1],
|
||||
time: match[2],
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: label,
|
||||
time: '',
|
||||
}
|
||||
},
|
||||
onAvailabilityBlockClick(block) {
|
||||
if (!block || !block.key) {
|
||||
return
|
||||
@@ -847,6 +868,10 @@ new Vue({
|
||||
this.$toast('批量预约截止日期不能早于开始日期')
|
||||
return false
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate > this.$moment(this.formData.reserveStartTime).endOf('month').format('YYYY-MM-DD')) {
|
||||
this.$toast('批量预约截止日期不能超过预约开始时间所在月份')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$toast('当前截止日期内没有可批量预约的同星期时段')
|
||||
return false
|
||||
|
||||
+33
-7
@@ -165,21 +165,30 @@ layout("/layouts/platform_h5.html"){
|
||||
.availability-popup__tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 12px 16px 0;
|
||||
padding: 12px 16px 8px;
|
||||
overflow-x: auto;
|
||||
background: #f8fafc;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.availability-popup__tabs::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.availability-tab {
|
||||
flex: 0 0 auto;
|
||||
min-width: 72px;
|
||||
height: 34px;
|
||||
padding: 0 14px;
|
||||
min-height: 34px;
|
||||
padding: 6px 14px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
color: #475569;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -244,12 +253,13 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
.slot-block {
|
||||
min-height: 48px;
|
||||
padding: 0 12px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #dbe4ee;
|
||||
border-radius: 14px;
|
||||
background: #ffffff;
|
||||
color: #475569;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
@@ -259,6 +269,21 @@ layout("/layouts/platform_h5.html"){
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.slot-block__name,
|
||||
.slot-block__time {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.slot-block__time {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.slot-block--available {
|
||||
border-color: #86efac;
|
||||
background: rgba(34, 197, 94, 0.1);
|
||||
@@ -464,7 +489,7 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</van-cell>
|
||||
<div v-if="yearlyReserve" class="batch-panel">
|
||||
<div class="section-tip">将自动预约截止日期内每周同一时段,默认到本月底。</div>
|
||||
<div class="section-tip">预约本月后续每周同一时段,默认到本月底。</div>
|
||||
<van-field
|
||||
:value="formData.yearlyReserveEndDate"
|
||||
label="截至日期"
|
||||
@@ -548,7 +573,8 @@ layout("/layouts/platform_h5.html"){
|
||||
type="button"
|
||||
:class="getBlockClass(block)"
|
||||
@click="onAvailabilityBlockClick(block)">
|
||||
<span>{{ block.label }}</span>
|
||||
<span class="slot-block__name">{{ formatSlotLabel(block).name }}</span>
|
||||
<span class="slot-block__time">{{ formatSlotLabel(block).time }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,54 @@ layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
|
||||
.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;
|
||||
}
|
||||
.site-cug-tag.info {
|
||||
background: #eef2ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
.site-cug-tag.muted {
|
||||
background: #f8fafc;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.site-cug-batch-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: #e0f2fe;
|
||||
color: #0369a1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.site-cug-batch-child {
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid #dbeafe;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
@@ -18,18 +65,35 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<table-list api="/platform/siteCug/mine/pageData" :page_form.sync="pageForm" ref="tableListRef" title="siteName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div :class="row._isBatchChild ? 'site-cug-batch-child' : ''">
|
||||
<div class="site-cug-card-tags">
|
||||
<span v-if="row.applyLoginName" class="site-cug-tag">{{ row.applyLoginName }}</span>
|
||||
<span class="site-cug-tag gray">{{ row.reserveType === 'club' ? '协会预约' : '分工会预约' }}</span>
|
||||
<span v-if="row.yearlyBatch" class="site-cug-tag warn">预约本月</span>
|
||||
<span v-if="row._isBatchChild" class="site-cug-tag muted">明细</span>
|
||||
<span v-if="row._batchCount > 1 && !row._isBatchChild" class="site-cug-tag info">共 {{ row._batchCount }} 条</span>
|
||||
<button
|
||||
v-if="row._hasFoldChildren && !row._isBatchChild"
|
||||
type="button"
|
||||
class="site-cug-batch-toggle"
|
||||
@click.stop="toggleBatchGroup(row)">
|
||||
<i :class="row._expanded ? 'fa fa-angle-up' : 'fa fa-angle-down'"></i>
|
||||
<span>{{ row._expanded ? '收起' : '展开' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<table-column label="预约人">{{row.applyUserName || '-'}}</table-column>
|
||||
<table-column label="预约类型">{{row.reserveType === 'club' ? '协会预约' : '分工会预约'}}</table-column>
|
||||
<table-column label="开始时间">{{row.reserveStartTime}}</table-column>
|
||||
<table-column label="结束时间">{{row.reserveEndTime}}</table-column>
|
||||
<table-column label="当前节点">{{row.taskName || '-'}}</table-column>
|
||||
</div>
|
||||
</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 delete" @click="onDelete(row)" v-if="row.canCancel">
|
||||
<div class="action-btn delete" @click="onDelete(row)" v-if="!row._isBatchChild && row.canCancel">
|
||||
<i class="fa fa-trash"></i>
|
||||
<span>取消预约</span>
|
||||
</div>
|
||||
@@ -68,14 +132,113 @@ layout("/layouts/platform_h5.html"){
|
||||
value: null,
|
||||
}
|
||||
],
|
||||
expandedBatchKeys: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onReady() {
|
||||
this.installTableListFoldHook()
|
||||
await this.querySiteType()
|
||||
await this.querySites()
|
||||
this.doSearch()
|
||||
},
|
||||
normalizeBatchFlag(row) {
|
||||
return row && (row.yearlyBatch === 1 || row.yearlyBatch === '1' || row.yearlyBatch === true)
|
||||
},
|
||||
getBatchGroupKey(row) {
|
||||
if (!this.normalizeBatchFlag(row)) {
|
||||
return 'single_' + row.id
|
||||
}
|
||||
return 'batch_' + (row.backOption || row.id) + '_' + (row.createdBy || '')
|
||||
},
|
||||
buildFoldedTableData(rows) {
|
||||
const groups = {}
|
||||
;(rows || []).forEach((row) => {
|
||||
const key = this.getBatchGroupKey(row)
|
||||
if (!groups[key]) {
|
||||
groups[key] = []
|
||||
}
|
||||
groups[key].push(Object.assign({}, row))
|
||||
})
|
||||
const displayRows = []
|
||||
Object.keys(groups).forEach((key) => {
|
||||
const sortedRows = groups[key].slice().sort((a, b) => {
|
||||
return (a.reserveStartTime || '').localeCompare(b.reserveStartTime || '')
|
||||
})
|
||||
const parent = Object.assign({}, sortedRows[0])
|
||||
const children = sortedRows.slice(1).map((item) => {
|
||||
return Object.assign({}, 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 = parent.batchDeleteCount || sortedRows.length
|
||||
parent._foldedRecords = children
|
||||
displayRows.push(parent)
|
||||
if (parent._expanded) {
|
||||
children.forEach((child) => displayRows.push(child))
|
||||
}
|
||||
})
|
||||
return displayRows
|
||||
},
|
||||
refreshFoldedTableData() {
|
||||
const tableList = this.$refs.tableListRef
|
||||
if (!tableList) {
|
||||
return
|
||||
}
|
||||
tableList.tableData = this.buildFoldedTableData(tableList._rawTableData || [])
|
||||
},
|
||||
toggleBatchGroup(row) {
|
||||
if (!row || !row._groupKey || !row._hasFoldChildren) {
|
||||
return
|
||||
}
|
||||
this.$set(this.expandedBatchKeys, row._groupKey, !this.expandedBatchKeys[row._groupKey])
|
||||
this.refreshFoldedTableData()
|
||||
},
|
||||
installTableListFoldHook() {
|
||||
const tableList = this.$refs.tableListRef
|
||||
if (!tableList || tableList._siteCugBatchFoldHooked) {
|
||||
return
|
||||
}
|
||||
tableList._siteCugBatchFoldHooked = true
|
||||
tableList._rawTableData = []
|
||||
tableList.pageData = () => {
|
||||
return this.loadFoldedMinePageData(tableList)
|
||||
}
|
||||
tableList.doSearch = () => {
|
||||
tableList.tableFinished = false
|
||||
tableList.tableData = []
|
||||
tableList._rawTableData = []
|
||||
tableList.localPageForm.pageNumber = 1
|
||||
tableList.$emit('update:page_form', Object.assign({}, tableList.localPageForm))
|
||||
return this.loadFoldedMinePageData(tableList)
|
||||
}
|
||||
},
|
||||
loadFoldedMinePageData(tableList) {
|
||||
tableList.tableLoading = true
|
||||
const loading = createListLoading()
|
||||
return this.$axios.post(tableList.api, tableList.json ? { pageForm: JSON.stringify(tableList.localPageForm) } : tableList.localPageForm).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const list = res.data && Array.isArray(res.data.list) ? res.data.list : []
|
||||
tableList._rawTableData = (tableList._rawTableData || []).concat(list)
|
||||
tableList.tableData = this.buildFoldedTableData(tableList._rawTableData)
|
||||
tableList.localPageForm.totalCount = res.data ? res.data.totalCount : 0
|
||||
if (tableList._rawTableData.length >= tableList.localPageForm.totalCount) {
|
||||
tableList.tableFinished = true
|
||||
}
|
||||
tableList.$emit('update:page_form', Object.assign({}, tableList.localPageForm))
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
tableList.tableLoading = false
|
||||
tableList.tableRefreshing = false
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
@@ -83,7 +246,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: row.yearlyBatch
|
||||
? ('该记录属于“预约本年”批量预约,确认后将一并删除同批次的 ' + (row.batchDeleteCount || 0) + ' 条预约记录,是否继续?')
|
||||
? ('该记录属于“预约本月”批量预约,确认后将一并删除同批次的 ' + (row.batchDeleteCount || row._batchCount || 0) + ' 条预约记录,是否继续?')
|
||||
: '您确定要取消该预约吗?',
|
||||
}).then(() => {
|
||||
this.$axios.post('/platform/siteCug/mine/delete', { id: row.id }).then((res) => {
|
||||
@@ -134,6 +297,7 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.expandedBatchKeys = {}
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
@@ -145,4 +309,4 @@ layout("/layouts/platform_h5.html"){
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
#-->
|
||||
|
||||
+141
-5
@@ -52,6 +52,30 @@ layout("/layouts/platform_h5.html"){
|
||||
background: #fff3e5;
|
||||
color: #d97706;
|
||||
}
|
||||
.site-cug-tag.info {
|
||||
background: #eef2ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
.site-cug-tag.muted {
|
||||
background: #f8fafc;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.site-cug-batch-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: #e0f2fe;
|
||||
color: #0369a1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.site-cug-batch-child {
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid #dbeafe;
|
||||
}
|
||||
.action-btn.disabled {
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
@@ -94,10 +118,21 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="site-cug-audit-list-scroll">
|
||||
<table-list api="/platform/siteCug/schoolUnionAudit/pageData" :page_form.sync="pageForm" ref="tableListRef" title="applyUserName" @ready="onReady">
|
||||
<template v-slot="{index,row}">
|
||||
<div :class="row._isBatchChild ? 'site-cug-batch-child' : ''">
|
||||
<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>
|
||||
<span v-if="row.yearlyBatch" class="site-cug-tag warn">预约本月</span>
|
||||
<span v-if="row._isBatchChild" class="site-cug-tag muted">明细</span>
|
||||
<span v-if="row._batchCount > 1 && !row._isBatchChild" class="site-cug-tag info">共 {{ row._batchCount }} 条</span>
|
||||
<button
|
||||
v-if="row._hasFoldChildren && !row._isBatchChild"
|
||||
type="button"
|
||||
class="site-cug-batch-toggle"
|
||||
@click.stop="toggleBatchGroup(row)">
|
||||
<i :class="row._expanded ? 'fa fa-angle-up' : 'fa fa-angle-down'"></i>
|
||||
<span>{{ row._expanded ? '收起' : '展开' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<table-column label="场地名称">{{row.siteName}}</table-column>
|
||||
<table-column label="预约主体">{{row.reserveType === 'club' ? (row.clubName || '-') : (row.applyUnionName || '-')}}</table-column>
|
||||
@@ -105,17 +140,18 @@ layout("/layouts/platform_h5.html"){
|
||||
<table-column label="开始时间">{{row.reserveStartTime}}</table-column>
|
||||
<table-column label="结束时间">{{row.reserveEndTime}}</table-column>
|
||||
<table-column label="当前节点">{{row.curTaskName || '-'}}</table-column>
|
||||
</div>
|
||||
</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)">
|
||||
<div class="action-btn" v-if="!row._isBatchChild && 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)">
|
||||
<div class="action-btn delete" v-if="!row._isBatchChild && 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>
|
||||
@@ -184,11 +220,13 @@ layout("/layouts/platform_h5.html"){
|
||||
showApprovalForm: false,
|
||||
auditLoading: false,
|
||||
revokeLoading: false,
|
||||
expandedBatchKeys: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
historyBack,
|
||||
async onReady() {
|
||||
this.installTableListFoldHook()
|
||||
await this.querySiteType()
|
||||
await this.querySites()
|
||||
this.doSearch()
|
||||
@@ -203,6 +241,103 @@ layout("/layouts/platform_h5.html"){
|
||||
reserveTypeText(row) {
|
||||
return row && row.reserveType === 'club' ? '协会预约' : '分工会预约'
|
||||
},
|
||||
normalizeBatchFlag(row) {
|
||||
return row && (row.yearlyBatch === 1 || row.yearlyBatch === '1' || row.yearlyBatch === true)
|
||||
},
|
||||
getBatchGroupKey(row) {
|
||||
if (!this.normalizeBatchFlag(row)) {
|
||||
return 'single_' + row.id
|
||||
}
|
||||
return 'batch_' + (row.backOption || row.id) + '_' + (row.createdBy || '')
|
||||
},
|
||||
buildFoldedTableData(rows) {
|
||||
const groups = {}
|
||||
;(rows || []).forEach((row) => {
|
||||
const key = this.getBatchGroupKey(row)
|
||||
if (!groups[key]) {
|
||||
groups[key] = []
|
||||
}
|
||||
groups[key].push(Object.assign({}, row))
|
||||
})
|
||||
const displayRows = []
|
||||
Object.keys(groups).forEach((key) => {
|
||||
const sortedRows = groups[key].slice().sort((a, b) => {
|
||||
return (a.reserveStartTime || '').localeCompare(b.reserveStartTime || '')
|
||||
})
|
||||
const parent = Object.assign({}, sortedRows[0])
|
||||
const children = sortedRows.slice(1).map((item) => {
|
||||
return Object.assign({}, 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 = parent.batchAuditCount || sortedRows.length
|
||||
parent._foldedRecords = children
|
||||
displayRows.push(parent)
|
||||
if (parent._expanded) {
|
||||
children.forEach((child) => displayRows.push(child))
|
||||
}
|
||||
})
|
||||
return displayRows
|
||||
},
|
||||
refreshFoldedTableData() {
|
||||
const tableList = this.$refs.tableListRef
|
||||
if (!tableList) {
|
||||
return
|
||||
}
|
||||
tableList.tableData = this.buildFoldedTableData(tableList._rawTableData || [])
|
||||
},
|
||||
toggleBatchGroup(row) {
|
||||
if (!row || !row._groupKey || !row._hasFoldChildren) {
|
||||
return
|
||||
}
|
||||
this.$set(this.expandedBatchKeys, row._groupKey, !this.expandedBatchKeys[row._groupKey])
|
||||
this.refreshFoldedTableData()
|
||||
},
|
||||
installTableListFoldHook() {
|
||||
const tableList = this.$refs.tableListRef
|
||||
if (!tableList || tableList._siteCugBatchFoldHooked) {
|
||||
return
|
||||
}
|
||||
tableList._siteCugBatchFoldHooked = true
|
||||
tableList._rawTableData = []
|
||||
tableList.pageData = () => {
|
||||
return this.loadFoldedAuditPageData(tableList)
|
||||
}
|
||||
tableList.doSearch = () => {
|
||||
tableList.tableFinished = false
|
||||
tableList.tableData = []
|
||||
tableList._rawTableData = []
|
||||
tableList.localPageForm.pageNumber = 1
|
||||
tableList.$emit('update:page_form', Object.assign({}, tableList.localPageForm))
|
||||
return this.loadFoldedAuditPageData(tableList)
|
||||
}
|
||||
},
|
||||
loadFoldedAuditPageData(tableList) {
|
||||
tableList.tableLoading = true
|
||||
const loading = createListLoading()
|
||||
return this.$axios.post(tableList.api, tableList.json ? { pageForm: JSON.stringify(tableList.localPageForm) } : tableList.localPageForm).then((res) => {
|
||||
if (res.code === 0) {
|
||||
const list = res.data && Array.isArray(res.data.list) ? res.data.list : []
|
||||
tableList._rawTableData = (tableList._rawTableData || []).concat(list)
|
||||
tableList.tableData = this.buildFoldedTableData(tableList._rawTableData)
|
||||
tableList.localPageForm.totalCount = res.data ? res.data.totalCount : 0
|
||||
if (tableList._rawTableData.length >= tableList.localPageForm.totalCount) {
|
||||
tableList.tableFinished = true
|
||||
}
|
||||
tableList.$emit('update:page_form', Object.assign({}, tableList.localPageForm))
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
tableList.tableLoading = false
|
||||
tableList.tableRefreshing = false
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.showApprovalForm = false
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
@@ -228,7 +363,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: this.formData.yearlyBatch
|
||||
? ('该记录属于“预约本年”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||
? ('该记录属于“预约本月”批量预约,提交后将一并审核同批次的 ' + (this.formData.batchAuditCount || 0) + ' 条预约记录,是否继续?')
|
||||
: '您确定要提交吗?',
|
||||
}).then(() => {
|
||||
this.auditLoading = true
|
||||
@@ -267,7 +402,7 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$dialog.confirm({
|
||||
title: '提示',
|
||||
message: row.yearlyBatch
|
||||
? ('该记录属于“预约本年”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || 0) + ' 条审核任务,是否继续?')
|
||||
? ('该记录属于“预约本月”批量预约,撤回后将一并撤回同批次的 ' + (row.batchAuditCount || 0) + ' 条审核任务,是否继续?')
|
||||
: '您确定要撤回吗?',
|
||||
}).then(() => {
|
||||
this.revokeLoading = true
|
||||
@@ -321,6 +456,7 @@ layout("/layouts/platform_h5.html"){
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(() => {
|
||||
this.expandedBatchKeys = {}
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
|
||||
Reference in New Issue
Block a user