疗休养优化
This commit is contained in:
@@ -5,7 +5,6 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.useragent.UserAgent;
|
||||
import cn.hutool.http.useragent.UserAgentUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
@@ -287,76 +286,67 @@ public class SysHomeController {
|
||||
// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true)
|
||||
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
|
||||
public Result getNews() {
|
||||
// 定义要爬取的URL
|
||||
String domain = "https://cdgh.ncu.edu.cn/";
|
||||
try {
|
||||
// 使用Jsoup连接到URL并获取页面内容
|
||||
Document doc = Jsoup.connect(domain).get();
|
||||
|
||||
JSONObject root = new JSONObject();
|
||||
|
||||
// 1. 新闻快讯(来自 .list1)
|
||||
List<JSONObject> newsArray = new ArrayList<>();
|
||||
Elements newsItems = doc.select(".group1 .list1 li");
|
||||
for (Element item : newsItems) {
|
||||
String date = item.select(".date").text().trim();
|
||||
Element link = item.select("a.text").first();
|
||||
String title = link.select(".title").text().trim();
|
||||
String url = link.attr("href").trim();
|
||||
|
||||
JSONObject node = new JSONObject();
|
||||
node.set("title", title);
|
||||
node.set("date", date);
|
||||
node.set("url", domain + url);
|
||||
newsArray.add(node);
|
||||
}
|
||||
root.set("news", newsArray);
|
||||
|
||||
// 2. 通知公告(来自 .list2)
|
||||
List<JSONObject> noticesArray = new ArrayList<>();
|
||||
Elements noticeItems = doc.select(".group2 .list2 li");
|
||||
for (Element item : noticeItems) {
|
||||
String date = item.select(".date").text().trim();
|
||||
Element link = item.select("a.title").first();
|
||||
String title = link.text().trim();
|
||||
String url = link.attr("href").trim();
|
||||
JSONObject node = new JSONObject();
|
||||
node.set("title", title);
|
||||
node.set("date", date);
|
||||
node.set("url", domain + url);
|
||||
noticesArray.add(node);
|
||||
}
|
||||
root.set("notices", noticesArray);
|
||||
|
||||
// 3. 基层风采(来自 .pic-list1)
|
||||
List<JSONObject> grassrootsArray = new ArrayList<>();
|
||||
Elements grassrootsItems = doc.select(".group3 .pic-list1 li");
|
||||
for (Element item : grassrootsItems) {
|
||||
Element link = item.select("a.img-scale").first();
|
||||
String date = link.select(".date").text().trim();
|
||||
String title = link.select(".title").text().trim();
|
||||
String url = link.attr("href").trim();
|
||||
String summary = link.select(".info").text().trim();
|
||||
|
||||
String imageUrl = "";
|
||||
Element img = link.select("img").first();
|
||||
if (img != null) {
|
||||
imageUrl = img.attr("src").trim();
|
||||
}
|
||||
|
||||
JSONObject node = new JSONObject();
|
||||
node.set("title", title);
|
||||
node.set("date", date);
|
||||
node.set("url", domain + url);
|
||||
node.set("summary", summary);
|
||||
node.set("image", domain + imageUrl);
|
||||
grassrootsArray.add(node);
|
||||
}
|
||||
root.set("grassroots", grassrootsArray);
|
||||
return Result.success(root);
|
||||
List<NutMap> news = new ArrayList<>();
|
||||
news.add(NutMap.NEW().setv("label", "新闻快讯")
|
||||
.setv("value", parseHomeNewsItems(domain, doc.select(".group1 .list1 li"), "a.text", ".title")));
|
||||
news.add(NutMap.NEW().setv("label", "通知公告")
|
||||
.setv("value", parseHomeNewsItems(domain, doc.select(".group2 .list2 li"), "a.title", "")));
|
||||
news.add(NutMap.NEW().setv("label", "基层风采")
|
||||
.setv("value", parseHomeNewsItems(domain, doc.select(".group3 .pic-list1 li"), "a.img-scale", ".title")));
|
||||
return Result.success(news);
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
return Result.success();
|
||||
return Result.success(Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the NCU union website list nodes to the PC v4 home carousel structure.
|
||||
* The migrated jcdt component renders label/value and item href/time/text fields.
|
||||
*
|
||||
* @param domain base website domain used to complete relative links
|
||||
* @param items news list nodes parsed from the source page
|
||||
* @param linkSelector selector for the clickable element inside each list node
|
||||
* @param titleSelector selector for the title inside the clickable element, blank means using link text
|
||||
* @return normalized news items for the PC v4 home page
|
||||
*/
|
||||
private List<NutMap> parseHomeNewsItems(String domain, Elements items, String linkSelector, String titleSelector) {
|
||||
List<NutMap> rows = new ArrayList<>();
|
||||
for (Element item : items) {
|
||||
Element link = item.select(linkSelector).first();
|
||||
if (link == null) {
|
||||
continue;
|
||||
}
|
||||
String title = StrUtil.isBlank(titleSelector) ? link.text().trim() : link.select(titleSelector).text().trim();
|
||||
String href = link.attr("href").trim();
|
||||
String time = item.select(".date").text().trim();
|
||||
rows.add(NutMap.NEW()
|
||||
.setv("href", completeNewsUrl(domain, href))
|
||||
.setv("time", time)
|
||||
.setv("text", title));
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes relative news links while preserving absolute website links.
|
||||
*
|
||||
* @param domain base website domain
|
||||
* @param href original href from the source page
|
||||
* @return absolute link for opening the news detail page
|
||||
*/
|
||||
private String completeNewsUrl(String domain, String href) {
|
||||
if (StrUtil.isBlank(href) || StrUtil.startWithIgnoreCase(href, "http://")
|
||||
|| StrUtil.startWithIgnoreCase(href, "https://")) {
|
||||
return href;
|
||||
}
|
||||
if (href.startsWith("/")) {
|
||||
return domain + href.substring(1);
|
||||
}
|
||||
return domain + href;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-34
@@ -193,14 +193,15 @@ public class TourGroupController {
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
'' AS mobile,
|
||||
t.idCard,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS idCard,
|
||||
t.unionId,
|
||||
t.unionName,
|
||||
t.signupTime
|
||||
FROM tour_ledger t
|
||||
INNER JOIN tour_matter m ON m.id = t.matterId
|
||||
INNER JOIN tour_line l ON l.id = m.lineId
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
$condition
|
||||
ORDER BY $orderColumn $orderBy, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
@@ -212,7 +213,6 @@ public class TourGroupController {
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
fillSignupMobile(list);
|
||||
fillSignupFamilies(list);
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
@@ -300,8 +300,8 @@ public class TourGroupController {
|
||||
t.id AS ledgerId,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
vu.mobile,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS idCard,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
t.unionName,
|
||||
l.lineName,
|
||||
CASE
|
||||
@@ -526,35 +526,6 @@ public class TourGroupController {
|
||||
}
|
||||
}
|
||||
|
||||
private void fillSignupMobile(List<NutMap> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<String> jobNos = new ArrayList<>();
|
||||
for (NutMap item : list) {
|
||||
String jobNo = item.getString("jobNo", "");
|
||||
if (StrUtil.isNotBlank(jobNo) && !jobNos.contains(jobNo)) {
|
||||
jobNos.add(jobNo);
|
||||
}
|
||||
}
|
||||
if (jobNos.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sql sql = Sqls.create("SELECT loginname, mobile FROM vw_user WHERE loginname IN (@jobNos)");
|
||||
sql.setParam("jobNos", jobNos.toArray(new String[0]));
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
|
||||
Map<String, String> mobileMap = new HashMap<>();
|
||||
for (NutMap user : sql.getList(NutMap.class)) {
|
||||
mobileMap.put(user.getString("loginname", ""), user.getString("mobile", ""));
|
||||
}
|
||||
for (NutMap item : list) {
|
||||
item.put("mobile", mobileMap.getOrDefault(item.getString("jobNo", ""), ""));
|
||||
}
|
||||
}
|
||||
|
||||
private Cnd buildQueryCnd(Integer year, String lineName, String lineType, String unionId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("m.delFlag", "=", false);
|
||||
|
||||
+25
-6
@@ -133,8 +133,8 @@ public class TourLedgerController {
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName) AS currentLineName,
|
||||
COALESCE(NULLIF(vu.sex, ''), t.gender, '') AS currentGender,
|
||||
vu.age AS age,
|
||||
COALESCE(NULLIF(vu.idCard, ''), t.idCard, '') AS currentIdCard,
|
||||
COALESCE(NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS currentIdCard,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS currentMobile,
|
||||
IFNULL(f.familyCount, 0) AS familyCount,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
@@ -188,6 +188,7 @@ public class TourLedgerController {
|
||||
item.put("lineName", item.getString("currentLineName"));
|
||||
item.put("gender", item.getString("currentGender"));
|
||||
item.put("idCard", item.getString("currentIdCard"));
|
||||
item.put("mobile", item.getString("currentMobile"));
|
||||
});
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
@@ -206,6 +207,7 @@ public class TourLedgerController {
|
||||
if (!canAccessLedgerUnion(ledger.getUnionId())) {
|
||||
return Result.error("无权查看该台账记录");
|
||||
}
|
||||
fillLedgerContactFallback(ledger);
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.NEW();
|
||||
familyCnd.and(TourLedgerFamily::getLedgerId, "=", id);
|
||||
@@ -392,8 +394,8 @@ public class TourLedgerController {
|
||||
t.userName,
|
||||
COALESCE(NULLIF(vu.sex, ''), t.gender, '') AS gender,
|
||||
vu.age AS age,
|
||||
COALESCE(NULLIF(vu.idCard, ''), t.idCard, '') AS idCard,
|
||||
COALESCE(NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS idCard,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
t.unitName,
|
||||
t.boardingPlace,
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName, '') AS lineName,
|
||||
@@ -491,11 +493,11 @@ public class TourLedgerController {
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS idCard,
|
||||
t.unionId,
|
||||
COALESCE(NULLIF(t.unionName, ''), su.name, vu.unionName, '') AS unionName,
|
||||
COALESCE(NULLIF(su.unionCode, ''), vu.unionCode, '') AS unionCode,
|
||||
COALESCE(NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
COALESCE(NULLIF(l.lineName, ''), t.lineName, '') AS lineName,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
@@ -948,6 +950,23 @@ public class TourLedgerController {
|
||||
return StrUtil.isNotBlank(currentUnionId) && StrUtil.equals(currentUnionId, unionId);
|
||||
}
|
||||
|
||||
private void fillLedgerContactFallback(TourLedger ledger) {
|
||||
if (ledger == null || (StrUtil.isNotBlank(ledger.getIdCard()) && StrUtil.isNotBlank(ledger.getMobile()))) {
|
||||
return;
|
||||
}
|
||||
// Detail views prefer ledger contact data; blank ledger fields fall back to the user profile snapshot for display only.
|
||||
View_user user = tourLedgerService.dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", ledger.getJobNo()));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
ledger.setIdCard(user.getIdCard());
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
ledger.setMobile(user.getMobile());
|
||||
}
|
||||
}
|
||||
|
||||
private void appendApprovedWorkflowFilter(Cnd cnd) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.or("ins.id", "IS", null);
|
||||
|
||||
+111
-2
@@ -27,6 +27,7 @@ import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourMatter;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSetting;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourUserAssignment;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
@@ -147,8 +148,13 @@ public class TourMySignupController {
|
||||
(SELECT MAX(id) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'startTask' AND taskState IN (10, 20)) AS startTaskId,
|
||||
IF(IFNULL(l.directFamilyUnitLine, 0) = 1 OR dr.id IS NOT NULL, 1, 0) AS directFamilyUnitLine,
|
||||
dr.id AS directRelativeId,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS currentIdCard,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS currentMobile,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT task.displayName), IF(ins.id IS NULL, '', '结束')) AS curTaskName,
|
||||
IFNULL(f.familyCount, 0) AS familyCount,
|
||||
a.id AS assignmentId,
|
||||
IFNULL(a.cancelled, 0) AS assignmentCancelled,
|
||||
m.travelStartTime AS actionTravelStartTime,
|
||||
COALESCE(m.travelEndTime, tp.travelEndTime) AS travelEndTime,
|
||||
CASE
|
||||
WHEN IFNULL(m.travelStartTime, '') <> '' AND IFNULL(m.travelEndTime, '') <> ''
|
||||
@@ -160,6 +166,7 @@ public class TourMySignupController {
|
||||
LEFT JOIN wf_process_task task ON task.processInstanceId = ins.id AND task.taskState = 10
|
||||
LEFT JOIN tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
LEFT JOIN (
|
||||
SELECT ledgerId, COUNT(1) AS familyCount
|
||||
FROM tour_ledger_family
|
||||
@@ -167,6 +174,10 @@ public class TourMySignupController {
|
||||
GROUP BY ledgerId
|
||||
) f ON f.ledgerId = t.id
|
||||
LEFT JOIN tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN tour_user_assignment a ON a.matterId = t.matterId
|
||||
AND a.userId = @currentUserId
|
||||
AND a.loginName = t.jobNo
|
||||
AND a.delFlag = 0
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
@@ -192,13 +203,20 @@ public class TourMySignupController {
|
||||
ORDER BY $orderColumn $orderBy, t.`year` DESC, t.signupTime DESC, t.createdAt DESC
|
||||
""");
|
||||
listSql.setCondition(cnd);
|
||||
listSql.setParam("currentUserId", SecurityUtil.getUserId());
|
||||
listSql.setVar("orderColumn", getOrderColumn(pageForm.getPageOrderName()));
|
||||
listSql.setVar("orderBy", "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
|
||||
listSql.setPager(tourLedgerService.dao().createPager(pageForm.getPageNumber(), pageForm.getPageSize()));
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, listSql.getList(NutMap.class));
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
list.forEach(item -> {
|
||||
item.put("idCard", item.getString("currentIdCard"));
|
||||
item.put("mobile", item.getString("currentMobile"));
|
||||
});
|
||||
appendMySignupActionFlags(list);
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@@ -209,6 +227,7 @@ public class TourMySignupController {
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在");
|
||||
}
|
||||
fillLedgerContactFallback(ledger);
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getDelFlag, "=", false)
|
||||
.and(TourLedgerFamily::getLedgerId, "=", ledger.getId());
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
@@ -279,6 +298,7 @@ public class TourMySignupController {
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在");
|
||||
}
|
||||
fillLedgerContactFallback(ledger);
|
||||
if (StrUtil.isBlank(ledger.getMatterId())) {
|
||||
return Result.error("历史报名记录缺少事项信息,不能修改");
|
||||
}
|
||||
@@ -536,6 +556,29 @@ public class TourMySignupController {
|
||||
return Result.success().addMsg("取消报名成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动端我的疗休养退出报名入口。
|
||||
* 仅允许当前登录人操作自己的人员分配记录,具体退出截止天数和台账清理逻辑复用 service 层。
|
||||
*
|
||||
* @param assignmentId 人员分配记录ID
|
||||
* @return 退出结果
|
||||
*/
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"tour.mysignup", "h5.tour.mysignup"}, mode = SaMode.OR)
|
||||
public Result doLeaveTour(String assignmentId) {
|
||||
TourUserAssignment assignment = fetchOwnAssignment(assignmentId);
|
||||
if (assignment == null) {
|
||||
return Result.error("人员分配记录不存在或无权操作");
|
||||
}
|
||||
try {
|
||||
tourUserAssignmentService.cancelAssignment(assignment.getId());
|
||||
return Result.success().addMsg("退出疗休养报名成功");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"tour.mysignup", "h5.tour.mysignup"}, mode = SaMode.OR)
|
||||
@@ -605,6 +648,55 @@ public class TourMySignupController {
|
||||
.and(TourLedger::getJobNo, "=", currentJobNo()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前登录人的人员分配记录,避免移动端传入他人分配ID进行退出。
|
||||
*/
|
||||
private TourUserAssignment fetchOwnAssignment(String assignmentId) {
|
||||
if (StrUtil.isBlank(assignmentId)) {
|
||||
return null;
|
||||
}
|
||||
return tourUserAssignmentService.fetch(Cnd.where(TourUserAssignment::getId, "=", assignmentId)
|
||||
.and(TourUserAssignment::getUserId, "=", SecurityUtil.getUserId())
|
||||
.and(TourUserAssignment::getLoginName, "=", currentJobNo())
|
||||
.and(TourUserAssignment::getDelFlag, "=", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 给移动端我的疗休养列表追加操作按钮显示标识,退出截止时间与 service 层最终校验保持一致。
|
||||
*/
|
||||
private void appendMySignupActionFlags(List<NutMap> list) {
|
||||
if (Lang.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
int cancelDeadlineDays = tourUserAssignmentService.getCancelDeadlineDays();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
for (NutMap item : list) {
|
||||
boolean assignmentCancelled = item.getBoolean("assignmentCancelled", false);
|
||||
String assignmentId = item.getString("assignmentId", "");
|
||||
item.put("cancelDeadlineDays", cancelDeadlineDays);
|
||||
item.put("canLeaveTour", StrUtil.isNotBlank(assignmentId)
|
||||
&& !assignmentCancelled
|
||||
&& isWithinLeaveTimeRange(item.getString("actionTravelStartTime", ""), cancelDeadlineDays, now));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前时间是否处于“出行开始前N天”到“出行开始前”的可退出范围内。
|
||||
*/
|
||||
private boolean isWithinLeaveTimeRange(String travelStartTime, int cancelDeadlineDays, LocalDateTime now) {
|
||||
try {
|
||||
String normalized = normalizeDateTime(travelStartTime, false);
|
||||
if (StrUtil.isBlank(normalized)) {
|
||||
return false;
|
||||
}
|
||||
LocalDateTime startTime = LocalDateTime.parse(normalized, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
LocalDateTime deadline = startTime.minusDays(cancelDeadlineDays);
|
||||
return !now.isBefore(deadline) && now.isBefore(startTime);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Result checkSignup(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return Result.error("参数错误");
|
||||
@@ -1037,13 +1129,30 @@ public class TourMySignupController {
|
||||
ledger.setJobNo(user == null ? SecurityUtil.getUserLoginname() : defaultIfBlank(user.getLoginname(), SecurityUtil.getUserLoginname()));
|
||||
ledger.setUserName(user == null ? SecurityUtil.getUserUsername() : defaultIfBlank(user.getUsername(), SecurityUtil.getUserUsername()));
|
||||
ledger.setGender(user == null ? ledger.getGender() : defaultIfBlank(user.getSex(), ledger.getGender()));
|
||||
ledger.setIdCard(user == null ? ledger.getIdCard() : defaultIfBlank(user.getIdCard(), ledger.getIdCard()));
|
||||
ledger.setIdCard(user == null ? ledger.getIdCard() : defaultIfBlank(ledger.getIdCard(), user.getIdCard()));
|
||||
ledger.setUnitId(user == null ? SecurityUtil.getUnitId() : defaultIfBlank(user.getUnitId(), SecurityUtil.getUnitId()));
|
||||
ledger.setUnitName(user == null ? ledger.getUnitName() : defaultIfBlank(user.getUnitName(), ledger.getUnitName()));
|
||||
ledger.setUnionId(user == null ? SecurityUtil.getUnionId() : defaultIfBlank(user.getUnionId(), ledger.getUnionId()));
|
||||
ledger.setUnionName(user == null ? ledger.getUnionName() : defaultIfBlank(user.getUnionName(), ledger.getUnionName()));
|
||||
}
|
||||
|
||||
private void fillLedgerContactFallback(TourLedger ledger) {
|
||||
if (ledger == null || (StrUtil.isNotBlank(ledger.getIdCard()) && StrUtil.isNotBlank(ledger.getMobile()))) {
|
||||
return;
|
||||
}
|
||||
// My signup detail keeps ledger contact data first; blank contact fields use the user profile snapshot for display only.
|
||||
View_user user = tourLedgerService.dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", ledger.getJobNo()));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
ledger.setIdCard(user.getIdCard());
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
ledger.setMobile(user.getMobile());
|
||||
}
|
||||
}
|
||||
|
||||
private void clearBedInfo(TourLedger ledger, List<TourLedgerFamily> familyList) {
|
||||
if (ledger != null) {
|
||||
ledger.setBedType("");
|
||||
|
||||
+19
@@ -7,6 +7,7 @@ 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.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
@@ -171,6 +172,7 @@ public class TourSchoolUnionApprovalController {
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在或无权查看");
|
||||
}
|
||||
fillLedgerContactFallback(ledger);
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
@@ -465,6 +467,23 @@ public class TourSchoolUnionApprovalController {
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
}
|
||||
|
||||
private void fillLedgerContactFallback(TourLedger ledger) {
|
||||
if (ledger == null || (StrUtil.isNotBlank(ledger.getIdCard()) && StrUtil.isNotBlank(ledger.getMobile()))) {
|
||||
return;
|
||||
}
|
||||
// Approval detail keeps ledger contact data first; blank contact fields use the user profile snapshot for display only.
|
||||
View_user user = tourLedgerService.dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", ledger.getJobNo()));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
ledger.setIdCard(user.getIdCard());
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
ledger.setMobile(user.getMobile());
|
||||
}
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
|
||||
+145
-17
@@ -26,6 +26,7 @@ import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLine;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourMatter;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourSetting;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourUserAssignment;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
@@ -167,6 +168,8 @@ public class TourSignupController {
|
||||
m.`year`,
|
||||
m.unionId,
|
||||
COALESCE(u.name, '校工会') AS unionName,
|
||||
m.signupStartTime,
|
||||
m.signupEndTime,
|
||||
m.lineId,
|
||||
l.lineName,
|
||||
l.lineType,
|
||||
@@ -185,6 +188,8 @@ public class TourSignupController {
|
||||
my.instanceState,
|
||||
my.taskKey,
|
||||
my.startTaskId,
|
||||
my.assignmentId,
|
||||
IFNULL(my.assignmentCancelled, 0) AS assignmentCancelled,
|
||||
IFNULL(my.canRevoke, 0) AS canRevoke,
|
||||
CASE WHEN my.ledgerId IS NULL THEN 0 ELSE 1 END AS signed
|
||||
FROM tour_matter m
|
||||
@@ -217,9 +222,12 @@ public class TourSignupController {
|
||||
MAX(ins.id) AS instanceId,
|
||||
MAX(ins.state) AS instanceState,
|
||||
MAX(task.taskName) AS taskKey,
|
||||
MAX(ua.id) AS assignmentId,
|
||||
MAX(IFNULL(ua.cancelled, 0)) AS assignmentCancelled,
|
||||
MAX((SELECT MAX(st.id) FROM wf_process_task st WHERE st.processInstanceId = ins.id AND st.taskName = 'startTask' AND st.taskState IN (10, 20))) AS startTaskId,
|
||||
MAX(IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = task.taskParentId) = 'startTask', 1, 0)) AS canRevoke
|
||||
FROM tour_ledger t
|
||||
LEFT JOIN tour_user_assignment ua ON ua.matterId = t.matterId AND ua.loginName = t.jobNo AND ua.delFlag = 0
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id AND ins.state <> @abandonState
|
||||
LEFT JOIN wf_process_task task ON task.processInstanceId = ins.id AND task.taskState = 10
|
||||
WHERE t.delFlag = 0
|
||||
@@ -240,17 +248,73 @@ public class TourSignupController {
|
||||
listSql.setCallback(Sqls.callback.maps());
|
||||
tourMatterService.dao().execute(listSql);
|
||||
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, listSql.getList(NutMap.class));
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
appendH5LineActionFlags(list);
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动端退出疗休养入口,复用人员分配退出逻辑并限定只能操作当前登录人的分配记录。
|
||||
*
|
||||
* @param assignmentId 人员分配记录ID
|
||||
* @return 退出结果
|
||||
*/
|
||||
@At("/h5/doLeaveTour")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("h5.tour.signup")
|
||||
public Result h5DoLeaveTour(String assignmentId) {
|
||||
TourUserAssignment assignment = fetchCurrentUserAssignment(assignmentId);
|
||||
if (assignment == null) {
|
||||
return Result.error("人员分配记录不存在或无权操作");
|
||||
}
|
||||
try {
|
||||
tourUserAssignmentService.cancelAssignment(assignment.getId());
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动端取消当前线路,删除本人的报名台账并清空人员分配中的线路快照。
|
||||
*
|
||||
* @param ledgerId 报名台账ID
|
||||
* @return 取消结果
|
||||
*/
|
||||
@At("/h5/doCancelLine")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("h5.tour.signup")
|
||||
public Result h5DoCancelLine(String ledgerId) {
|
||||
if (StrUtil.isBlank(ledgerId)) {
|
||||
return Result.error("报名台账参数错误");
|
||||
}
|
||||
TourLedger ledger = tourLedgerService.fetch(Cnd.where(TourLedger::getId, "=", ledgerId)
|
||||
.and(TourLedger::getJobNo, "=", currentJobNo())
|
||||
.and(TourLedger::getDelFlag, "=", false));
|
||||
if (ledger == null) {
|
||||
return Result.error("报名台账不存在或无权操作");
|
||||
}
|
||||
TourMatter matter = tourMatterService.fetch(ledger.getMatterId());
|
||||
Result signupTimeResult = checkSignupTime(matter);
|
||||
if (signupTimeResult != null) {
|
||||
return signupTimeResult;
|
||||
}
|
||||
tourLedgerFamilyService.clear(Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId()));
|
||||
tourLedgerDirectRelativeService.clear(Cnd.where(TourLedgerDirectRelative::getLedgerId, "=", ledger.getId()));
|
||||
tourLedgerService.delete(ledger.getId());
|
||||
tourUserAssignmentService.clearExistingAssignmentMatterAfterLedgerDelete(ledger.getMatterId(), ledger.getJobNo());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission(value = {"tour.signup", "h5.tour.signup"}, mode = SaMode.OR)
|
||||
public Result pageData(PageForm pageForm, Integer year, String lineName, String lineType, String unionId) {
|
||||
public Result pageData(PageForm pageForm, Integer year, String lineName, String lineType, String unionId, String travelPeriod) {
|
||||
if (StrUtil.isBlank(pageForm.getPageOrderName())) {
|
||||
pageForm.defaultSortAsc("lineName");
|
||||
}
|
||||
Cnd cnd = buildQueryCnd(year, lineName, lineType, unionId);
|
||||
appendTravelPeriodCnd(cnd, travelPeriod);
|
||||
String currentJobNo = currentJobNo();
|
||||
|
||||
Sql countSql = Sqls.create("""
|
||||
@@ -375,9 +439,10 @@ public class TourSignupController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询移动端选择路线页的出行时间筛选项,按 yyyyMMdd-yyyyMMdd 格式拼接事项出行起止时间并去重。
|
||||
* Queries distinct travel periods for PC signup and H5 line selection.
|
||||
* The value uses yyyyMMdd-yyyyMMdd so the frontend can pass it back as a stable filter key.
|
||||
*/
|
||||
@At("/h5/travelPeriodOptions")
|
||||
@At({"/h5/travelPeriodOptions", "/travelPeriodOptions"})
|
||||
@SaCheckPermission(value = {"tour.signup", "h5.tour.signup"}, mode = SaMode.OR)
|
||||
public Result h5TravelPeriodOptions(Integer year, String lineType, Boolean directFamilyUnitLine) {
|
||||
Cnd cnd = buildQueryCnd(year, null, null, null);
|
||||
@@ -490,20 +555,11 @@ public class TourSignupController {
|
||||
.and(TourLedger::getJobNo, "=", staff.getString("jobNo"));
|
||||
ledgerCnd.desc(TourLedger::getCreatedAt);
|
||||
TourLedger ledger = tourLedgerService.fetch(ledgerCnd);
|
||||
TourMatter matterEntity = tourMatterService.fetch(matter.getString("matterId"));
|
||||
TourLedger ruleLedger = new TourLedger();
|
||||
ruleLedger.setId(ledger == null ? null : ledger.getId());
|
||||
ruleLedger.setYear(matterEntity == null ? matter.getInt("year") : matterEntity.getYear());
|
||||
ruleLedger.setMatterId(matter.getString("matterId"));
|
||||
ruleLedger.setLineId(matter.getString("lineId"));
|
||||
ruleLedger.setLineName(matter.getString("lineName"));
|
||||
Result ruleResult = checkSignupRule(ruleLedger, matterEntity, ledger);
|
||||
if (ruleResult != null) {
|
||||
return ruleResult;
|
||||
}
|
||||
// Viewing a line should only load detail data; signup rules are enforced when the user starts or submits signup.
|
||||
List<TourLedgerFamily> families = Collections.emptyList();
|
||||
TourLedgerDirectRelative directRelative = null;
|
||||
if (ledger != null) {
|
||||
fillLedgerContactFallback(ledger, staff);
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getDelFlag, "=", false)
|
||||
.and(TourLedgerFamily::getLedgerId, "=", ledger.getId());
|
||||
familyCnd.asc(TourLedgerFamily::getCreatedAt);
|
||||
@@ -793,7 +849,7 @@ public class TourSignupController {
|
||||
return workflowResult;
|
||||
}
|
||||
}
|
||||
return Result.success().addMsg(approvalRequired ? (update ? "修改已提交,等待审核" : "申请已提交,等待审核") : (update ? "修改成功" : "报名成功"));
|
||||
return Result.success().addMsg(approvalRequired ? (update ? "修改已提交,等待审核" : "申请已提交,等待审核") : (update ? "修改成功" : "恭喜您已报名成功"));
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -1199,6 +1255,65 @@ public class TourSignupController {
|
||||
return setting != null && "ASSIGNED_USER".equals(setting.getSignupEligibilityMode());
|
||||
}
|
||||
|
||||
private void appendH5LineActionFlags(List<NutMap> list) {
|
||||
if (Lang.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
int cancelDeadlineDays = tourUserAssignmentService.getCancelDeadlineDays();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
for (NutMap item : list) {
|
||||
boolean signed = item.getBoolean("signed", false);
|
||||
boolean assignmentCancelled = item.getBoolean("assignmentCancelled", false);
|
||||
String assignmentId = item.getString("assignmentId", "");
|
||||
String ledgerId = item.getString("ledgerId", "");
|
||||
// Button visibility is calculated on the server so H5 follows the same time rules as backend submit actions.
|
||||
item.put("cancelDeadlineDays", cancelDeadlineDays);
|
||||
item.put("canLeaveTour", signed && StrUtil.isNotBlank(assignmentId) && !assignmentCancelled
|
||||
&& isWithinLeaveTimeRange(item.getString("travelStartTime", ""), cancelDeadlineDays, now));
|
||||
item.put("canCancelLine", signed && StrUtil.isNotBlank(ledgerId)
|
||||
&& isWithinSignupRange(item.getString("signupStartTime", ""), item.getString("signupEndTime", ""), now));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isWithinLeaveTimeRange(String travelStartTime, int cancelDeadlineDays, LocalDateTime now) {
|
||||
LocalDateTime startTime = parseDateTimeValue(travelStartTime, false);
|
||||
if (startTime == null) {
|
||||
return false;
|
||||
}
|
||||
LocalDateTime deadline = startTime.minusDays(cancelDeadlineDays);
|
||||
return !now.isBefore(deadline) && now.isBefore(startTime);
|
||||
}
|
||||
|
||||
private boolean isWithinSignupRange(String signupStartTime, String signupEndTime, LocalDateTime now) {
|
||||
LocalDateTime startTime = parseDateTimeValue(signupStartTime, false);
|
||||
LocalDateTime endTime = parseDateTimeValue(signupEndTime, true);
|
||||
if (startTime == null || endTime == null) {
|
||||
return false;
|
||||
}
|
||||
return !now.isBefore(startTime) && !now.isAfter(endTime);
|
||||
}
|
||||
|
||||
private LocalDateTime parseDateTimeValue(String value, boolean endOfDay) {
|
||||
String normalized = normalizeDateTime(value, endOfDay);
|
||||
if (StrUtil.isBlank(normalized)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return LocalDateTime.parse(normalized.substring(0, 19), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private TourUserAssignment fetchCurrentUserAssignment(String assignmentId) {
|
||||
if (StrUtil.isBlank(assignmentId)) {
|
||||
return null;
|
||||
}
|
||||
return tourLedgerService.dao().fetch(TourUserAssignment.class, Cnd.where(TourUserAssignment::getId, "=", assignmentId)
|
||||
.and(TourUserAssignment::getUserId, "=", SecurityUtil.getUserId())
|
||||
.and(TourUserAssignment::getDelFlag, "=", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一校验疗休养事项报名时间,确保资格名单校验在时间校验通过后再执行。
|
||||
*/
|
||||
@@ -1497,13 +1612,26 @@ public class TourSignupController {
|
||||
ledger.setJobNo(user == null ? SecurityUtil.getUserLoginname() : defaultIfBlank(user.getLoginname(), SecurityUtil.getUserLoginname()));
|
||||
ledger.setUserName(user == null ? SecurityUtil.getUserUsername() : defaultIfBlank(user.getUsername(), SecurityUtil.getUserUsername()));
|
||||
ledger.setGender(user == null ? ledger.getGender() : defaultIfBlank(user.getSex(), ledger.getGender()));
|
||||
ledger.setIdCard(user == null ? ledger.getIdCard() : defaultIfBlank(user.getIdCard(), ledger.getIdCard()));
|
||||
ledger.setIdCard(user == null ? ledger.getIdCard() : defaultIfBlank(ledger.getIdCard(), user.getIdCard()));
|
||||
ledger.setUnitId(user == null ? SecurityUtil.getUnitId() : defaultIfBlank(user.getUnitId(), SecurityUtil.getUnitId()));
|
||||
ledger.setUnitName(user == null ? ledger.getUnitName() : defaultIfBlank(user.getUnitName(), ledger.getUnitName()));
|
||||
ledger.setUnionId(user == null ? SecurityUtil.getUnionId() : defaultIfBlank(user.getUnionId(), SecurityUtil.getUnionId()));
|
||||
ledger.setUnionName(user == null ? ledger.getUnionName() : defaultIfBlank(user.getUnionName(), ledger.getUnionName()));
|
||||
}
|
||||
|
||||
private void fillLedgerContactFallback(TourLedger ledger, NutMap staff) {
|
||||
if (ledger == null || staff == null) {
|
||||
return;
|
||||
}
|
||||
// Signup detail keeps saved ledger contact data first; blank contact fields use the user profile snapshot for display only.
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
ledger.setIdCard(staff.getString("idCard", ""));
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
ledger.setMobile(staff.getString("mobile", ""));
|
||||
}
|
||||
}
|
||||
|
||||
private List<TourLedgerFamily> parseFamilies(String families) {
|
||||
if (StrUtil.isBlank(families)) {
|
||||
return Collections.emptyList();
|
||||
|
||||
+19
@@ -7,6 +7,7 @@ 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.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerDirectRelative;
|
||||
@@ -171,6 +172,7 @@ public class TourUnionApprovalController {
|
||||
if (ledger == null) {
|
||||
return Result.error("报名记录不存在或无权查看");
|
||||
}
|
||||
fillLedgerContactFallback(ledger);
|
||||
ledger.setLineName(getCurrentLineName(ledger));
|
||||
Cnd familyCnd = Cnd.where(TourLedgerFamily::getLedgerId, "=", ledger.getId())
|
||||
.and(TourLedgerFamily::getDelFlag, "=", false);
|
||||
@@ -465,6 +467,23 @@ public class TourUnionApprovalController {
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
}
|
||||
|
||||
private void fillLedgerContactFallback(TourLedger ledger) {
|
||||
if (ledger == null || (StrUtil.isNotBlank(ledger.getIdCard()) && StrUtil.isNotBlank(ledger.getMobile()))) {
|
||||
return;
|
||||
}
|
||||
// Approval detail keeps ledger contact data first; blank contact fields use the user profile snapshot for display only.
|
||||
View_user user = tourLedgerService.dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", ledger.getJobNo()));
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
ledger.setIdCard(user.getIdCard());
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
ledger.setMobile(user.getMobile());
|
||||
}
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
if (ledger == null) {
|
||||
return "";
|
||||
|
||||
+2
-2
@@ -416,9 +416,9 @@ public class TourUnionLedgerController {
|
||||
SELECT
|
||||
t.id,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
COALESCE(NULLIF(t.idCard, ''), NULLIF(vu.idCard, ''), '') AS idCard,
|
||||
t.unionName,
|
||||
vu.mobile,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
m.travelStartTime,
|
||||
m.travelEndTime,
|
||||
m.estimatedCost,
|
||||
|
||||
@@ -51,6 +51,11 @@ public class TourLedger extends BaseModel implements Serializable {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String idCard;
|
||||
|
||||
@Column
|
||||
@Comment("手机号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 30)
|
||||
private String mobile;
|
||||
|
||||
@Column
|
||||
@Comment("所在单位ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
|
||||
+7
@@ -272,6 +272,13 @@ public interface TourUserAssignmentService extends BaseService<TourUserAssignmen
|
||||
*/
|
||||
void cancelAssignment(String id);
|
||||
|
||||
/**
|
||||
* 查询疗休养退出取消的出行开始前限制天数,供移动端按钮展示和实际退出校验保持一致。
|
||||
*
|
||||
* @return 出行开始前允许退出的天数
|
||||
*/
|
||||
int getCancelDeadlineDays();
|
||||
|
||||
/**
|
||||
* 将人员分配记录从已退出恢复为未退出。
|
||||
* 只恢复人员分配表状态,不自动恢复已删除的报名台账。
|
||||
|
||||
+6
-3
@@ -886,12 +886,15 @@ public class TourUserAssignmentServiceImpl extends BaseServiceImpl<TourUserAssig
|
||||
LocalDateTime travelStartTime = parseTravelStartTime(matter.getTravelStartTime());
|
||||
int days = getCancelDeadlineDays();
|
||||
LocalDateTime deadline = travelStartTime.minusDays(days);
|
||||
if (LocalDateTime.now().isAfter(deadline)) {
|
||||
throw new IllegalArgumentException("当前路线已超过取消时间,需在出行开始前" + days + "天取消");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 退出报名仅允许在“出行开始前N天”到“出行开始前”之间办理,出行开始时刻不能再退出。
|
||||
if (now.isBefore(deadline) || !now.isBefore(travelStartTime)) {
|
||||
throw new IllegalArgumentException("当前不在退出时间范围内,需在出行开始前" + days + "天至出行开始前办理");
|
||||
}
|
||||
}
|
||||
|
||||
private int getCancelDeadlineDays() {
|
||||
@Override
|
||||
public int getCancelDeadlineDays() {
|
||||
try {
|
||||
Sys_config config = sysConfigService == null ? null : sysConfigService.getValueByKey(TOUR_CANCEL_DEADLINE_DAYS_KEY);
|
||||
String value = config == null ? "" : config.getConfigValue();
|
||||
|
||||
Reference in New Issue
Block a user