移动端疗休养模块UI优化
This commit is contained in:
+13
-37
@@ -1,5 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
@@ -12,7 +14,7 @@ import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourMatterService;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
@@ -193,7 +195,7 @@ public class TourGroupController {
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
'' AS mobile,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
t.idCard,
|
||||
t.unionId,
|
||||
t.unionName,
|
||||
@@ -201,6 +203,7 @@ public class TourGroupController {
|
||||
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 +215,6 @@ public class TourGroupController {
|
||||
tourLedgerService.dao().execute(listSql);
|
||||
|
||||
List<NutMap> list = listSql.getList(NutMap.class);
|
||||
fillSignupMobile(list);
|
||||
Pagination<NutMap> pagination = new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), count, list);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
@@ -231,7 +233,7 @@ public class TourGroupController {
|
||||
List<NutMap> list = queryExportParticipants(matterId);
|
||||
Workbook workbook = buildParticipantsWorkbook(matter, list);
|
||||
String lineName = StrUtil.blankToDefault(matter.getString("lineName", ""), "线路");
|
||||
CommonDownloadUtil.download(lineName + "参加人员名单.xls", workbook, response);
|
||||
CommonDownloadUtil.download(lineName + "参加人员名单.xlsx", workbook, response);
|
||||
}
|
||||
|
||||
private Cnd buildSignupQueryCnd(String matterId, String keyword, String unionId) {
|
||||
@@ -300,7 +302,7 @@ public class TourGroupController {
|
||||
t.jobNo,
|
||||
t.userName,
|
||||
t.idCard,
|
||||
vu.mobile,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
t.unionName,
|
||||
l.lineName,
|
||||
CASE
|
||||
@@ -343,7 +345,8 @@ public class TourGroupController {
|
||||
ledgerId,
|
||||
familyName,
|
||||
relationship,
|
||||
idCard
|
||||
idCard,
|
||||
mobile
|
||||
FROM tour_ledger_family
|
||||
WHERE delFlag = 0
|
||||
AND ledgerId IN (@ledgerIds)
|
||||
@@ -363,7 +366,9 @@ public class TourGroupController {
|
||||
}
|
||||
|
||||
private Workbook buildParticipantsWorkbook(NutMap matter, List<NutMap> list) {
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("参加人员名单");
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 10));
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 10));
|
||||
@@ -414,7 +419,7 @@ public class TourGroupController {
|
||||
Row familyRow = sheet.createRow(rowIndex++);
|
||||
familyRow.setHeightInPoints(24);
|
||||
setParticipantRow(familyRow, seq++, "", family.getString("familyName", ""),
|
||||
family.getString("idCard", ""), "", "",
|
||||
family.getString("idCard", ""), family.getString("mobile", ""), "",
|
||||
item.getString("lineName", matter.getString("lineName", "")),
|
||||
item.getString("travelPeriod", matter.getString("travelPeriod", "")),
|
||||
family.getString("relationship", ""), item.getString("userName", ""), bodyStyle);
|
||||
@@ -481,35 +486,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);
|
||||
|
||||
+8
-6
@@ -27,7 +27,7 @@ import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerDirectRelativeSer
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerFamilyService;
|
||||
import com.budwk.app.zhgh.dayofficework.tour.service.TourLedgerService;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
@@ -183,7 +183,7 @@ public class TourLedgerController {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("参数错误");
|
||||
}
|
||||
TourLedger ledger = tourLedgerService.fetch(id);
|
||||
TourLedger ledger = tourLedgerService.fillMobileFallback(tourLedgerService.fetch(id));
|
||||
if (ledger == null) {
|
||||
return Result.error("台账记录不存在");
|
||||
}
|
||||
@@ -328,7 +328,7 @@ public class TourLedgerController {
|
||||
response.setHeader("Content-Disposition", "attachment;filename=" + zipName + ";filename*=UTF-8''" + zipName);
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) {
|
||||
if (unionRows.isEmpty()) {
|
||||
zipOutputStream.putNextEntry(new ZipEntry("无数据报名汇总表.xls"));
|
||||
zipOutputStream.putNextEntry(new ZipEntry("无数据报名汇总表.xlsx"));
|
||||
try (Workbook workbook = buildUnionSignupWorkbook("无数据", Collections.emptyList())) {
|
||||
workbook.write(zipOutputStream);
|
||||
}
|
||||
@@ -336,7 +336,7 @@ public class TourLedgerController {
|
||||
} else {
|
||||
for (Map.Entry<String, List<NutMap>> entry : unionRows.entrySet()) {
|
||||
String unionName = entry.getValue().isEmpty() ? entry.getKey() : entry.getValue().get(0).getString("unionName", entry.getKey());
|
||||
String fileName = safeFileName(unionName + "报名汇总表.xls");
|
||||
String fileName = safeFileName(unionName + "报名汇总表.xlsx");
|
||||
zipOutputStream.putNextEntry(new ZipEntry(fileName));
|
||||
try (Workbook workbook = buildUnionSignupWorkbook(unionName, entry.getValue())) {
|
||||
workbook.write(zipOutputStream);
|
||||
@@ -360,7 +360,7 @@ public class TourLedgerController {
|
||||
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, '') <> ''
|
||||
@@ -415,7 +415,9 @@ public class TourLedgerController {
|
||||
}
|
||||
|
||||
private Workbook buildUnionSignupWorkbook(String unionName, List<NutMap> rows) {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("报名汇总表");
|
||||
sheet.setColumnWidth(0, 8 * 256);
|
||||
sheet.setColumnWidth(1, 14 * 256);
|
||||
|
||||
+27
-8
@@ -407,6 +407,14 @@ public class TourMySignupController {
|
||||
return Result.success(sql.getList(Sys_dict.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改本人疗休养报名。
|
||||
*
|
||||
* @param ledger 报名台账,包含报名人身份证号码和手机号
|
||||
* @param families 亲属信息JSON数组,包含姓名、年龄、性别、关系及联系方式
|
||||
* @param directRelative 直系亲属线路信息JSON,非直系亲属线路可为空
|
||||
* @return Result,成功时返回修改结果,校验失败时返回具体业务提示
|
||||
*/
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.mysignup")
|
||||
@@ -571,9 +579,9 @@ public class TourMySignupController {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return null;
|
||||
}
|
||||
return tourLedgerService.fetch(Cnd.where(TourLedger::getDelFlag, "=", false)
|
||||
return tourLedgerService.fillMobileFallback(tourLedgerService.fetch(Cnd.where(TourLedger::getDelFlag, "=", false)
|
||||
.and(TourLedger::getId, "=", id)
|
||||
.and(TourLedger::getJobNo, "=", currentJobNo()));
|
||||
.and(TourLedger::getJobNo, "=", currentJobNo())));
|
||||
}
|
||||
|
||||
private Result checkSignup(TourLedger ledger) {
|
||||
@@ -592,6 +600,12 @@ public class TourMySignupController {
|
||||
if (StrUtil.isBlank(ledger.getLineName())) {
|
||||
return Result.error("报名线路不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
return Result.error("身份证号码不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
return Result.error("手机号不能为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1005,15 +1019,20 @@ public class TourMySignupController {
|
||||
if (family == null) {
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isBlank(family.getFamilyName()) || StrUtil.isBlank(family.getGender())
|
||||
|| StrUtil.isBlank(family.getIdCard()) || StrUtil.isBlank(family.getRelationship())) {
|
||||
return Result.error("请完善亲属姓名、性别、身份证号码和关系");
|
||||
if (StrUtil.isBlank(family.getFamilyName()) || family.getAge() == null
|
||||
|| StrUtil.isBlank(family.getGender()) || StrUtil.isBlank(family.getRelationship())) {
|
||||
return Result.error("请完善亲属姓名、年龄、性别和与本人关系");
|
||||
}
|
||||
String idCard = family.getIdCard().trim().toUpperCase();
|
||||
if (!isValidIdCard(idCard)) {
|
||||
// 年满16周岁的亲属必须提供身份证号码和手机号;未满16周岁时两项允许为空。
|
||||
if (family.getAge() >= 16 && (StrUtil.isBlank(family.getIdCard()) || StrUtil.isBlank(family.getMobile()))) {
|
||||
return Result.error("年满16周岁的亲属必须填写身份证号码和手机号");
|
||||
}
|
||||
if (StrUtil.isNotBlank(family.getIdCard()) && !isValidIdCard(family.getIdCard().trim().toUpperCase())) {
|
||||
return Result.error("请输入正确的身份证号码");
|
||||
}
|
||||
family.setIdCard(idCard);
|
||||
if (StrUtil.isNotBlank(family.getIdCard())) {
|
||||
family.setIdCard(family.getIdCard().trim().toUpperCase());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -461,7 +461,7 @@ public class TourSchoolUnionApprovalController {
|
||||
sql.setParam("actorId", SecurityUtil.getUserId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
return sql.getInt() > 0 ? tourLedgerService.fillMobileFallback(tourLedgerService.fetch(id)) : null;
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
|
||||
+28
-8
@@ -472,7 +472,7 @@ public class TourSignupController {
|
||||
.and(TourLedger::getMatterId, "=", matter.getString("matterId"))
|
||||
.and(TourLedger::getJobNo, "=", staff.getString("jobNo"));
|
||||
ledgerCnd.desc(TourLedger::getCreatedAt);
|
||||
TourLedger ledger = tourLedgerService.fetch(ledgerCnd);
|
||||
TourLedger ledger = tourLedgerService.fillMobileFallback(tourLedgerService.fetch(ledgerCnd));
|
||||
TourMatter matterEntity = tourMatterService.fetch(matter.getString("matterId"));
|
||||
TourLedger ruleLedger = new TourLedger();
|
||||
ruleLedger.setId(ledger == null ? null : ledger.getId());
|
||||
@@ -661,10 +661,19 @@ public class TourSignupController {
|
||||
return Result.success(sql.getList(Sys_dict.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存疗休养报名。
|
||||
*
|
||||
* @param ledger 报名台账基础信息,包含线路、事项、报名人身份证号码和手机号等内容
|
||||
* @param families 亲属信息JSON数组;每项包含姓名、性别、身份证号码、手机号和关系
|
||||
* @param directRelative 直系亲属线路信息JSON;非直系亲属线路可传空字符串
|
||||
* @return Result,成功时返回报名及流程结果,校验失败时返回具体缺失字段提示
|
||||
*/
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("tour.signup")
|
||||
public Result doSignup(TourLedger ledger, @Param("families") String families, @Param("directRelative") String directRelative) {
|
||||
public Result doSignup(TourLedger ledger, @Param("families") String families,
|
||||
@Param("directRelative") String directRelative) {
|
||||
Result checkResult = checkSignup(ledger);
|
||||
if (checkResult != null) {
|
||||
return checkResult;
|
||||
@@ -826,6 +835,12 @@ public class TourSignupController {
|
||||
if (StrUtil.isBlank(ledger.getLineName())) {
|
||||
return Result.error("报名线路不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getIdCard())) {
|
||||
return Result.error("身份证号码不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(ledger.getMobile())) {
|
||||
return Result.error("手机号不能为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -874,15 +889,20 @@ public class TourSignupController {
|
||||
if (family == null) {
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isBlank(family.getFamilyName()) || StrUtil.isBlank(family.getGender())
|
||||
|| StrUtil.isBlank(family.getIdCard()) || StrUtil.isBlank(family.getRelationship())) {
|
||||
return Result.error("请完善亲属姓名、性别、身份证号码和关系");
|
||||
if (StrUtil.isBlank(family.getFamilyName()) || family.getAge() == null
|
||||
|| StrUtil.isBlank(family.getGender()) || StrUtil.isBlank(family.getRelationship())) {
|
||||
return Result.error("请完善亲属姓名、年龄、性别和与本人关系");
|
||||
}
|
||||
String idCard = family.getIdCard().trim().toUpperCase();
|
||||
if (!isValidIdCard(idCard)) {
|
||||
// 年满16周岁的亲属必须提供身份证号码和手机号;未满16周岁时两项允许为空。
|
||||
if (family.getAge() >= 16 && (StrUtil.isBlank(family.getIdCard()) || StrUtil.isBlank(family.getMobile()))) {
|
||||
return Result.error("年满16周岁的亲属必须填写身份证号码和手机号");
|
||||
}
|
||||
if (StrUtil.isNotBlank(family.getIdCard()) && !isValidIdCard(family.getIdCard().trim().toUpperCase())) {
|
||||
return Result.error("请输入正确的身份证号码");
|
||||
}
|
||||
family.setIdCard(idCard);
|
||||
if (StrUtil.isNotBlank(family.getIdCard())) {
|
||||
family.setIdCard(family.getIdCard().trim().toUpperCase());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -461,7 +461,7 @@ public class TourUnionApprovalController {
|
||||
sql.setParam("actorId", SecurityUtil.getUserId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
return sql.getInt() > 0 ? tourLedgerService.fillMobileFallback(tourLedgerService.fetch(id)) : null;
|
||||
}
|
||||
|
||||
private String getCurrentLineName(TourLedger ledger) {
|
||||
|
||||
+9
-5
@@ -1,5 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.tour.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
@@ -15,7 +17,7 @@ import com.budwk.app.zhgh.dayofficework.tour.models.TourLedgerFamily;
|
||||
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;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
@@ -171,7 +173,7 @@ public class TourUnionLedgerController {
|
||||
Cnd cnd = buildQueryCnd(currentUnionId, startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, scopeType, true);
|
||||
List<NutMap> list = queryOverCostSummaryList(cnd, pageForm);
|
||||
Workbook workbook = buildOverCostSummaryWorkbook(currentUnionName(), list);
|
||||
CommonDownloadUtil.download("5天外超出部分疗休养费用由单位承担申请人员汇总表.xls", workbook, response);
|
||||
CommonDownloadUtil.download("5天外超出部分疗休养费用由单位承担申请人员汇总表.xlsx", workbook, response);
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -411,7 +413,7 @@ public class TourUnionLedgerController {
|
||||
t.userName,
|
||||
t.idCard,
|
||||
t.unionName,
|
||||
vu.mobile,
|
||||
COALESCE(NULLIF(t.mobile, ''), NULLIF(vu.mobile, ''), '') AS mobile,
|
||||
m.travelStartTime,
|
||||
m.travelEndTime,
|
||||
m.estimatedCost,
|
||||
@@ -474,7 +476,9 @@ public class TourUnionLedgerController {
|
||||
}
|
||||
|
||||
private Workbook buildOverCostSummaryWorkbook(String unionName, List<NutMap> list) {
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("汇总表");
|
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
|
||||
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 9));
|
||||
@@ -675,7 +679,7 @@ public class TourUnionLedgerController {
|
||||
sql.setParam("unionId", currentUnionId());
|
||||
sql.setCallback(Sqls.callback.integer());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getInt() > 0 ? tourLedgerService.fetch(id) : null;
|
||||
return sql.getInt() > 0 ? tourLedgerService.fillMobileFallback(tourLedgerService.fetch(id)) : null;
|
||||
}
|
||||
|
||||
private String getTravelPeriod(TourLedger ledger) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -56,6 +56,11 @@ public class TourLedgerFamily 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("年龄")
|
||||
@ColDefine(type = ColType.INT, width = 3)
|
||||
|
||||
@@ -8,6 +8,14 @@ import com.budwk.app.zhgh.dayofficework.tour.models.TourLedger;
|
||||
*/
|
||||
public interface TourLedgerService extends BaseService<TourLedger> {
|
||||
|
||||
/**
|
||||
* 补充报名台账手机号。台账已保存手机号时保持原值,仅在台账手机号为空时按工号读取用户视图手机号。
|
||||
*
|
||||
* @param ledger 待补充手机号的报名台账,允许为空
|
||||
* @return 原报名台账对象;参数为空时返回空
|
||||
*/
|
||||
TourLedger fillMobileFallback(TourLedger ledger);
|
||||
|
||||
/**
|
||||
* 校验当前人员在省内间隔周期内是否已经实际参加过省内线路。
|
||||
*
|
||||
|
||||
+12
@@ -26,6 +26,18 @@ public class TourLedgerServiceImpl extends BaseServiceImpl<TourLedger> implement
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TourLedger fillMobileFallback(TourLedger ledger) {
|
||||
if (ledger == null || StrUtil.isNotBlank(ledger.getMobile()) || StrUtil.isBlank(ledger.getJobNo())) {
|
||||
return ledger;
|
||||
}
|
||||
View_user user = dao().fetch(View_user.class, Cnd.where(View_user::getLoginname, "=", ledger.getJobNo()));
|
||||
if (user != null) {
|
||||
ledger.setMobile(user.getMobile());
|
||||
}
|
||||
return ledger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String checkInProvinceParticipation(String jobNo,
|
||||
Integer inProvinceYears,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- 疗休养报名手机号仅由业务代码控制必填,数据库字段保持可空以兼容历史数据。
|
||||
ALTER TABLE `tour_ledger`
|
||||
ADD COLUMN `mobile` varchar(30) NULL COMMENT '手机号' AFTER `idCard`;
|
||||
|
||||
ALTER TABLE `tour_ledger_family`
|
||||
ADD COLUMN `mobile` varchar(30) NULL COMMENT '手机号' AFTER `idCard`;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@@ -254,6 +254,7 @@
|
||||
})
|
||||
$(document).on("pjax:send", function () {
|
||||
window.h5HistoryLayerManager.reset()
|
||||
showH5PageSkeleton()
|
||||
NProgress.start()
|
||||
window.customStyleList = document.querySelectorAll('style[id^="style-"]')
|
||||
})
|
||||
@@ -268,6 +269,7 @@
|
||||
window.customStyleList = null
|
||||
}
|
||||
NProgress.done()
|
||||
hideH5PageSkeleton()
|
||||
toggleShowBar()
|
||||
})
|
||||
|
||||
@@ -292,6 +294,13 @@
|
||||
})()
|
||||
|
||||
function pjaxReplace(url, data = null) {
|
||||
showH5PageSkeleton(url)
|
||||
// 疗休养报名页面使用独立 H5 布局,其中包含图片懒加载等专用初始化逻辑。
|
||||
// 禁止通过公共 PJAX 只替换页面片段,否则专用布局脚本不会执行,首次进入会出现图片懒加载指令未注册。
|
||||
if (url && url.indexOf("/platform/tour/signup/h5") === 0) {
|
||||
window.location.href = url
|
||||
return
|
||||
}
|
||||
return $.pjax({
|
||||
url: url,
|
||||
container: "#container",
|
||||
@@ -304,6 +313,24 @@
|
||||
})
|
||||
}
|
||||
|
||||
// 仅在疗休养 H5 页面切换期间显示骨架,避免影响共用布局下的其他业务模块。
|
||||
const showH5PageSkeleton = (targetUrl) => {
|
||||
const pageUrl = targetUrl || window.location.pathname
|
||||
if (pageUrl.indexOf("/platform/tour/") !== 0) return
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.add("is-visible")
|
||||
}
|
||||
|
||||
const hideH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.remove("is-visible")
|
||||
}
|
||||
|
||||
// 从疗休养完整页面返回公共 H5 页面时可能命中 BFCache,需要清除离开前保留的骨架状态。
|
||||
window.addEventListener("pageshow", () => {
|
||||
hideH5PageSkeleton()
|
||||
})
|
||||
|
||||
let h5GlobalLoading = null
|
||||
let h5PendingRequestCount = 0
|
||||
|
||||
@@ -373,6 +400,7 @@
|
||||
}
|
||||
|
||||
function historyBack(func) {
|
||||
showH5PageSkeleton()
|
||||
if (window.history.length > 1) {
|
||||
window.history.back()
|
||||
} else {
|
||||
@@ -618,6 +646,8 @@
|
||||
Vue.prototype.$axios = commonUtil.axiosService()
|
||||
Vue.prototype.$downLoad = commonUtil.downLoadService.bind(commonUtil)
|
||||
Vue.prototype.$pjaxReplace = pjaxReplace
|
||||
Vue.prototype.$showH5PageSkeleton = showH5PageSkeleton
|
||||
Vue.prototype.$hideH5PageSkeleton = hideH5PageSkeleton
|
||||
</script>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
@@ -663,9 +693,41 @@
|
||||
.h5-voice-menu .voice-menu-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-page-transition-skeleton {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 30000;
|
||||
display: none;
|
||||
padding: 58px 12px 20px;
|
||||
background: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tour-page-transition-skeleton.is-visible { display: block; }
|
||||
.tour-page-transition-skeleton__nav,
|
||||
.tour-page-transition-skeleton__hero,
|
||||
.tour-page-transition-skeleton__line,
|
||||
.tour-page-transition-skeleton__card {
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-page-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
.tour-page-transition-skeleton__nav { position: absolute; top: 0; left: 0; right: 0; height: 46px; background-color: #fff; }
|
||||
.tour-page-transition-skeleton__hero { height: 154px; border-radius: 14px; }
|
||||
.tour-page-transition-skeleton__line { width: 42%; height: 18px; margin: 18px 2px 12px; border-radius: 9px; }
|
||||
.tour-page-transition-skeleton__card { height: 126px; margin-top: 12px; border-radius: 14px; }
|
||||
@keyframes tour-page-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tour-page-transition-skeleton" class="tour-page-transition-skeleton" aria-hidden="true">
|
||||
<div class="tour-page-transition-skeleton__nav"></div>
|
||||
<div class="tour-page-transition-skeleton__hero"></div>
|
||||
<div class="tour-page-transition-skeleton__line"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
</div>
|
||||
<div class="main-page page-showtabbar">
|
||||
<div class="page-wrapper">
|
||||
<div id="container">${layoutContent}</div>
|
||||
|
||||
@@ -11,11 +11,38 @@
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css?v=20260524"/>
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/h5.css?v=20260524"/>
|
||||
|
||||
<style>
|
||||
.tour-page-transition-skeleton {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 30000;
|
||||
display: none;
|
||||
padding: 58px 12px 20px;
|
||||
background: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tour-page-transition-skeleton.is-visible { display: block; }
|
||||
.tour-page-transition-skeleton__nav,
|
||||
.tour-page-transition-skeleton__hero,
|
||||
.tour-page-transition-skeleton__line,
|
||||
.tour-page-transition-skeleton__card {
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-page-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
.tour-page-transition-skeleton__nav { position: absolute; top: 0; left: 0; right: 0; height: 46px; background-color: #fff; }
|
||||
.tour-page-transition-skeleton__hero { height: 154px; border-radius: 14px; }
|
||||
.tour-page-transition-skeleton__line { width: 42%; height: 18px; margin: 18px 2px 12px; border-radius: 9px; }
|
||||
.tour-page-transition-skeleton__card { height: 126px; margin-top: 12px; border-radius: 14px; }
|
||||
@keyframes tour-page-skeleton-loading { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
|
||||
</style>
|
||||
|
||||
<script src="${base!}/assets/platform/plugins/vue/vue.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/vant/index.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/axios/axios.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/plugins/jquery/jquery.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/js/util/commonUtil.js?v=20260524"></script>
|
||||
<script src="${base!}/assets/platform/js/util/h5PopupHistory.js?v=20260830"></script>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
Vue.config.devtools = true
|
||||
@@ -123,6 +150,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 疗休养页面跳转前统一展示结构化骨架,避免旧页面或未完成样式短暂闪现。
|
||||
const showH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.add("is-visible")
|
||||
}
|
||||
|
||||
const hideH5PageSkeleton = () => {
|
||||
const skeleton = document.getElementById("tour-page-transition-skeleton")
|
||||
if (skeleton) skeleton.classList.remove("is-visible")
|
||||
}
|
||||
|
||||
// 浏览器返回或前进时可能直接恢复 BFCache 页面,需要主动关闭离开页面前显示的骨架层。
|
||||
// 此处只恢复页面展示,不刷新数据,从而保留线路列表的筛选条件、分页和滚动位置。
|
||||
window.addEventListener("pageshow", () => {
|
||||
hideH5PageSkeleton()
|
||||
})
|
||||
|
||||
const pjaxReplace = (url) => {
|
||||
showH5PageSkeleton()
|
||||
window.location.href = url
|
||||
}
|
||||
|
||||
function historyBack(fallbackUrl, func) {
|
||||
if (typeof fallbackUrl === "function") {
|
||||
func = fallbackUrl
|
||||
@@ -130,6 +179,7 @@
|
||||
} else if (typeof fallbackUrl !== "string" || !fallbackUrl) {
|
||||
fallbackUrl = "/platform/h5/home"
|
||||
}
|
||||
showH5PageSkeleton()
|
||||
if (window.history.length > 1) {
|
||||
window.history.back()
|
||||
} else {
|
||||
@@ -158,9 +208,20 @@
|
||||
Vue.prototype.$auth = commonUtil.authService()
|
||||
Vue.prototype.$axios = commonUtil.axiosService()
|
||||
Vue.prototype.$downLoad = commonUtil.downLoadService.bind(commonUtil)
|
||||
Vue.prototype.$pjaxReplace = pjaxReplace
|
||||
Vue.prototype.$showH5PageSkeleton = showH5PageSkeleton
|
||||
Vue.prototype.$hideH5PageSkeleton = hideH5PageSkeleton
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tour-page-transition-skeleton" class="tour-page-transition-skeleton" aria-hidden="true">
|
||||
<div class="tour-page-transition-skeleton__nav"></div>
|
||||
<div class="tour-page-transition-skeleton__hero"></div>
|
||||
<div class="tour-page-transition-skeleton__line"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
<div class="tour-page-transition-skeleton__card"></div>
|
||||
</div>
|
||||
<div class="main-page">
|
||||
<div class="page-wrapper">
|
||||
<div id="container">${layoutContent}</div>
|
||||
|
||||
@@ -159,6 +159,7 @@ layout("/layouts/platform.html"){
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ detail.mobile || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -205,6 +206,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile" min-width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
|
||||
@@ -99,6 +99,7 @@ layout("/layouts/platform.html"){
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ detail.mobile || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -145,6 +146,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile" min-width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="detailFillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
@@ -229,6 +231,13 @@ layout("/layouts/platform.html"){
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="手机号" required>
|
||||
<el-input v-model="signupForm.mobile" maxlength="30" placeholder="请输入手机号"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="tour-title tour-section">报名信息</div>
|
||||
<el-row :gutter="20">
|
||||
@@ -387,7 +396,12 @@ layout("/layouts/platform.html"){
|
||||
</el-table-column>
|
||||
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.idCard" maxlength="18" placeholder="请输入" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
||||
@@ -1181,6 +1195,7 @@ layout("/layouts/platform.html"){
|
||||
familyName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
age: null,
|
||||
bedType: "",
|
||||
bedInfo: "",
|
||||
@@ -1222,18 +1237,27 @@ layout("/layouts/platform.html"){
|
||||
this.$message.warning("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
this.$message.warning("请完善亲属姓名、性别、身份证号码和关系")
|
||||
const invalidBase = this.familyData.some(item => !item.familyName || item.age === null || item.age === undefined
|
||||
|| !item.gender || !item.relationship)
|
||||
if (invalidBase) {
|
||||
this.$message.warning("请完善亲属姓名、年龄、性别和与本人关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item) && (!item.idCard || !item.mobile))
|
||||
if (invalidContact) {
|
||||
this.$message.warning("年满16周岁的亲属必须填写身份证号码和手机号")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => item.idCard && !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
this.$message.warning("请输入正确的身份证号码")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
familyContactRequired(family) {
|
||||
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
row.idCard = String(row.idCard).trim().toUpperCase()
|
||||
@@ -1272,6 +1296,10 @@ layout("/layouts/platform.html"){
|
||||
return true
|
||||
},
|
||||
submitSignup() {
|
||||
if (!this.signupForm.idCard || !this.signupForm.mobile) {
|
||||
this.$message.warning("请完善报名人身份证号码和手机号")
|
||||
return
|
||||
}
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
@@ -1281,7 +1309,6 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
this.signupLoading = true
|
||||
this.$axios.post(loc() + "/doSignup", form).then((res) => {
|
||||
this.signupLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg || "修改成功")
|
||||
this.signupVisible = false
|
||||
@@ -1291,6 +1318,7 @@ layout("/layouts/platform.html"){
|
||||
this.$message.warning(res.msg || "修改失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.signupLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
+2
@@ -184,6 +184,7 @@ layout("/layouts/platform.html"){
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ detail.mobile || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
@@ -220,6 +221,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile" min-width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
|
||||
@@ -128,6 +128,13 @@ layout("/layouts/platform.html"){
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="手机号" required>
|
||||
<el-input v-model="signupForm.mobile" maxlength="30" placeholder="请输入手机号"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="tour-signup-title tour-signup-section">报名信息</div>
|
||||
<el-row :gutter="20">
|
||||
@@ -286,7 +293,12 @@ layout("/layouts/platform.html"){
|
||||
</el-table-column>
|
||||
<el-table-column label="身份证号码" min-width="180" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.idCard" maxlength="18" placeholder="请输入" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||
<el-input v-model="row.idCard" maxlength="18" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'" @blur="normalizeFamilyIdCard(row)"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号" min-width="150" align="center" header-align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-input v-model="row.mobile" maxlength="30" :placeholder="familyContactRequired(row) ? '16岁及以上必填' : '选填'"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="年龄" width="110" align="center" header-align="center">
|
||||
@@ -799,6 +811,7 @@ layout("/layouts/platform.html"){
|
||||
familyName: "",
|
||||
gender: "",
|
||||
idCard: "",
|
||||
mobile: "",
|
||||
age: null,
|
||||
bedType: "",
|
||||
bedInfo: "",
|
||||
@@ -840,18 +853,27 @@ layout("/layouts/platform.html"){
|
||||
this.$message.warning("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
this.$message.warning("请完善亲属姓名、性别、身份证号码和关系")
|
||||
const invalidBase = this.familyData.some(item => !item.familyName || item.age === null || item.age === undefined
|
||||
|| !item.gender || !item.relationship)
|
||||
if (invalidBase) {
|
||||
this.$message.warning("请完善亲属姓名、年龄、性别和与本人关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item) && (!item.idCard || !item.mobile))
|
||||
if (invalidContact) {
|
||||
this.$message.warning("年满16周岁的亲属必须填写身份证号码和手机号")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => item.idCard && !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
this.$message.warning("请输入正确的身份证号码")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
familyContactRequired(family) {
|
||||
return family && family.age !== null && family.age !== undefined && Number(family.age) >= 16
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
row.idCard = String(row.idCard).trim().toUpperCase()
|
||||
@@ -890,6 +912,10 @@ layout("/layouts/platform.html"){
|
||||
return true
|
||||
},
|
||||
submitSignup() {
|
||||
if (!this.signupForm.idCard || !this.signupForm.mobile) {
|
||||
this.$message.warning("请完善报名人身份证号码和手机号")
|
||||
return
|
||||
}
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
@@ -899,7 +925,6 @@ layout("/layouts/platform.html"){
|
||||
})
|
||||
this.signupLoading = true
|
||||
this.$axios.post(loc() + "/doSignup", form).then((res) => {
|
||||
this.signupLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg || "报名成功")
|
||||
this.signupVisible = false
|
||||
@@ -908,6 +933,7 @@ layout("/layouts/platform.html"){
|
||||
this.$message.warning(res.msg || "报名失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.signupLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -184,6 +184,7 @@ layout("/layouts/platform.html"){
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ detail.mobile || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报名时间">{{ detail.signupTime || '' }}</el-descriptions-item>
|
||||
@@ -220,6 +221,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile" min-width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
|
||||
@@ -149,6 +149,7 @@ layout("/layouts/platform.html"){
|
||||
<el-descriptions-item label="姓名">{{ detail.userName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="性别">{{ detail.gender || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.idCard || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ detail.mobile || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在单位">{{ detail.unitName || '' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所在工会">{{ detail.unionName || '' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -195,6 +196,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column label="家属姓名" prop="familyName" min-width="120" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="性别" prop="gender" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="身份证号码" prop="idCard" min-width="180" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile" min-width="140" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="90" align="center" header-align="center"></el-table-column>
|
||||
<el-table-column label="关系" prop="relationship" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column v-if="fillBedInfo" label="床型" prop="bedType" width="110" align="center" header-align="center" show-overflow-tooltip></el-table-column>
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/* 疗休养移动端统一视觉主题:仅使用 tour-h5-theme 下的业务类,避免影响其他 H5 模块。 */
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-h5-theme {
|
||||
min-height: 100vh;
|
||||
color: #263548;
|
||||
background-color: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 页面接口首次加载时使用结构化骨架,避免先显示空字段或旧列表。 */
|
||||
.tour-content-skeleton {
|
||||
padding: 12px;
|
||||
background: #f3f7fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-content-skeleton__cover,
|
||||
.tour-content-skeleton__title,
|
||||
.tour-content-skeleton__row,
|
||||
.tour-content-skeleton__card {
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-content-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
|
||||
.tour-content-skeleton__cover { height: 168px; border-radius: 14px; }
|
||||
.tour-content-skeleton__title { width: 46%; height: 18px; margin: 16px 2px 10px; border-radius: 9px; }
|
||||
.tour-content-skeleton__row { width: 76%; height: 13px; margin: 10px 2px; border-radius: 7px; }
|
||||
.tour-content-skeleton__card { height: 126px; margin-top: 12px; border-radius: 14px; }
|
||||
|
||||
@keyframes tour-content-skeleton-loading {
|
||||
0% { background-position: 100% 50%; }
|
||||
100% { background-position: 0 50%; }
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-nav-bar .van-icon,
|
||||
.tour-h5-theme .van-nav-bar__text {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-nav-bar::after,
|
||||
.tour-h5-theme .van-hairline--bottom::after {
|
||||
border-bottom-color: #edf2f8;
|
||||
}
|
||||
|
||||
.tour-h5-card {
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-h5-section-title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-height: 46px;
|
||||
padding: 0 14px 0 20px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-h5-section-title::before {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
bottom: 15px;
|
||||
left: 10px;
|
||||
width: 3px;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.tour-h5-tag {
|
||||
display: inline-flex;
|
||||
min-height: 22px;
|
||||
padding: 2px 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 11px;
|
||||
color: #1989fa;
|
||||
background-color: #eaf4ff;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-h5-tag.is-success {
|
||||
color: #20a765;
|
||||
background-color: #e9f8f0;
|
||||
}
|
||||
|
||||
.tour-h5-tag.is-warning {
|
||||
color: #e98018;
|
||||
background-color: #fff3e4;
|
||||
}
|
||||
|
||||
.tour-h5-tag.is-muted {
|
||||
color: #7c899b;
|
||||
background-color: #f0f2f5;
|
||||
}
|
||||
|
||||
.tour-h5-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-h5-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-h5-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-h5-search .van-field__control::placeholder {
|
||||
color: #a7b0bf;
|
||||
}
|
||||
|
||||
.tour-h5-filter {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
}
|
||||
|
||||
.tour-h5-filter .van-dropdown-menu__bar,
|
||||
.tour-h5-filter .van-dropdown-menu__item,
|
||||
.tour-h5-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.tour-h5-filter .van-dropdown-menu__bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-h5-filter .van-dropdown-menu__title {
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-h5-filter .van-dropdown-menu__title--active,
|
||||
.tour-h5-filter .van-dropdown-item__option--active,
|
||||
.tour-h5-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-h5-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.tour-h5-empty {
|
||||
display: flex;
|
||||
min-height: 290px;
|
||||
padding: 40px 18px 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-h5-empty img {
|
||||
display: block;
|
||||
width: 60%;
|
||||
max-width: 190px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tour-h5-empty__title {
|
||||
margin-top: 8px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-h5-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-h5-fixed-bar {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 30;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
background-color: rgba(255, 255, 255, .98);
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-h5-fixed-bar .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-cell {
|
||||
min-height: 48px;
|
||||
padding: 13px 14px;
|
||||
color: #35445a;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-cell__title {
|
||||
color: #65748a;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-cell__value {
|
||||
color: #263548;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-field__label {
|
||||
color: #65748a;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-field__control {
|
||||
color: #263548;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-button--info,
|
||||
.tour-h5-theme .van-button--primary {
|
||||
border-color: #0f7bf3;
|
||||
background-color: #0f7bf3;
|
||||
}
|
||||
|
||||
.tour-h5-theme .van-button--plain.van-button--info {
|
||||
color: #0f7bf3;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.tour-h5-fixed-bar {
|
||||
gap: 7px;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+410
-43
@@ -2,34 +2,36 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
padding: 8px 12px 10px;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
padding: 2px 12px 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
@@ -39,12 +41,36 @@ layout("/layouts/platform_h5.html"){
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
overflow: hidden;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
margin-left: 7px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
@@ -60,17 +86,24 @@ layout("/layouts/platform_h5.html"){
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-detail {
|
||||
height: 100%;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
height: calc(100% - 46px);
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
padding: 2px 0 calc(86px + env(safe-area-inset-bottom));
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
@@ -78,7 +111,7 @@ layout("/layouts/platform_h5.html"){
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
@@ -92,7 +125,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
@@ -106,9 +139,303 @@ layout("/layouts/platform_h5.html"){
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-approval-sticky /deep/ .van-dropdown-menu__bar,
|
||||
.tour-approval-sticky .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .table-list-card,
|
||||
.tour-approval-list-scroll /deep/ .list-card {
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .action-btn {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
/* 审核列表与提案校工会预审核采用同一信息层级和卡片规范。 */
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-approval-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.tour-approval-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar,
|
||||
.tour-approval-filter .van-dropdown-menu__item,
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
padding: 2px 12px 24px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-approval-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-approval-empty img {
|
||||
display: block;
|
||||
width: 60%;
|
||||
max-width: 190px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tour-approval-empty__title {
|
||||
margin-top: 10px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
margin: 0 0 7px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tour-card-heading-main {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
display: block;
|
||||
margin: 1px 0 0;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-status {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-approval-detail,
|
||||
.tour-approval-sheet {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
padding: 18px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 0 0 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 12px 14px 8px 21px;
|
||||
border-bottom: 0;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__title {
|
||||
flex: 0 0 92px;
|
||||
width: 92px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__value {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.tour-section .tour-approval-opinion {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background-color: #f7f9fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
gap: 10px;
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.tour-approval-actions .van-button {
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.tour-approval-sticky,
|
||||
.tour-approval-list-scroll {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<div id="app" class="tour-approval-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="校工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
@@ -116,27 +443,39 @@ layout("/layouts/platform_h5.html"){
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
<van-dropdown-menu class="tour-approval-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="unionOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.unionId"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<div v-if="pageSkeletonLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'school-approval-skeleton-' + index"></div>
|
||||
</div>
|
||||
<div v-if="!pageSkeletonLoading && pageForm.totalCount === 0" class="tour-approval-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无审核记录插画">
|
||||
<div class="tour-approval-empty__title">暂无审核记录</div>
|
||||
<div class="tour-approval-empty__hint">当前筛选条件下暂时没有疗休养报名</div>
|
||||
</div>
|
||||
<table-list v-show="!pageSkeletonLoading" api="/platform/tour/schoolUnionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" :show_loading_overlay="false" @ready="onReady" @loading-change="onTableLoading">
|
||||
<template #header="{index,row}">
|
||||
<div class="tour-card-heading">
|
||||
<div class="tour-card-heading-main">
|
||||
<div class="tour-card-person">{{ row.userName || '--' }}</div>
|
||||
<div class="tour-card-job-no">工号:{{ row.jobNo || '--' }}</div>
|
||||
</div>
|
||||
<span class="tour-h5-tag tour-card-status" :class="row.taskState === 10 ? 'is-warning' : 'is-success'">{{ row.curTaskName || (row.taskState === 10 ? '待审核' : '已处理') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
@@ -156,11 +495,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -172,6 +511,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
class="tour-approval-opinion"
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
@@ -197,8 +537,10 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="报名详情">
|
||||
<div class="tour-approval-sheet">
|
||||
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%' }" :close-on-click-overlay="false">
|
||||
<div class="tour-approval-detail">
|
||||
<van-nav-bar title="报名详情" left-text="返回" left-arrow @click-left="onClose"></van-nav-bar>
|
||||
<div class="tour-approval-sheet">
|
||||
<div class="tour-section">
|
||||
<div class="tour-section-title">教职工信息</div>
|
||||
<van-cell title="工号" :value="detail.jobNo || ''"></van-cell>
|
||||
@@ -261,9 +603,10 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
@@ -276,13 +619,15 @@ layout("/layouts/platform_h5.html"){
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
doneTasks: [],
|
||||
popupHistoryToken: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.$set(this, "visible", true)
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "detail")
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
@@ -294,7 +639,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, "detail")) {
|
||||
this.$set(this, "visible", false)
|
||||
}
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/schoolUnionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
@@ -337,6 +684,15 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "popupHistoryToken", window.h5PopupHistory.register(() => {
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("closed")
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +726,9 @@ layout("/layouts/platform_h5.html"){
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
pageSkeletonLoading: true,
|
||||
filterOpened: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -378,12 +736,24 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
onTableLoading(state) {
|
||||
if (state && state.initial) {
|
||||
this.$set(this, "pageSkeletonLoading", !!state.loading)
|
||||
}
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()])
|
||||
this.$nextTick(() => {
|
||||
Promise.all([this.loadUnionOptions(), this.loadLineTypeOptions()]).then(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadUnionOptions() {
|
||||
@@ -435,16 +805,12 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
@@ -467,6 +833,7 @@ layout("/layouts/platform_h5.html"){
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,28 +40,132 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
|
||||
.tour-card-title-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-card-actions {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tour-family-tab {
|
||||
margin: 10px 12px 0;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
background: #1684d2;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 30px;
|
||||
.tour-family-tabs {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.tour-family-tabs-shell {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
z-index: 2;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
border: 1px solid #d7e7fb;
|
||||
border-radius: 50%;
|
||||
color: #1989fa;
|
||||
background-color: rgba(255, 255, 255, .94);
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(43, 73, 112, .1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow.is-left {
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow.is-right {
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.tour-family-tab-arrow:disabled {
|
||||
border-color: #edf1f6;
|
||||
color: #c5ceda;
|
||||
background-color: #f8fafc;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-family-tabs.is-single {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* 只有一位亲属时直接展示表单,不显示没有切换意义的页签标题栏。 */
|
||||
.tour-family-tabs.is-single .van-tabs__wrap {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__wrap {
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__nav {
|
||||
background-color: #f6f9fd;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 页签标题栏使用原生惯性滚动,复杂亲属表单不再参与手势拖动。 */
|
||||
.tour-family-tabs .van-tabs__wrap--scrollable .van-tabs__nav {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
scroll-behavior: smooth;
|
||||
overscroll-behavior-x: contain;
|
||||
touch-action: pan-x;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__wrap--scrollable .van-tab {
|
||||
-webkit-box-flex: 0 !important;
|
||||
-webkit-flex: 0 0 auto !important;
|
||||
flex: 0 0 auto !important;
|
||||
min-width: 88px;
|
||||
padding: 0 14px;
|
||||
color: #718198;
|
||||
font-size: 13px;
|
||||
transition: color .2s ease, background-color .2s ease;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tab--active {
|
||||
color: #1989fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__line {
|
||||
width: 26px;
|
||||
height: 3px;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
transition-timing-function: cubic-bezier(.22, .61, .36, 1);
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tabs__track {
|
||||
transition-timing-function: cubic-bezier(.22, .61, .36, 1) !important;
|
||||
}
|
||||
|
||||
.tour-family-tabs .van-tab__text {
|
||||
display: block;
|
||||
max-width: 112px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-family-form {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.tour-field-tip {
|
||||
@@ -96,21 +200,77 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
.tour-apply-page {
|
||||
padding: 12px 12px 82px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-apply-card {
|
||||
margin-bottom: 10px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-apply-title {
|
||||
min-height: 46px;
|
||||
padding: 0 14px 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom-color: #edf1f6;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.tour-apply-title::before {
|
||||
top: 15px;
|
||||
bottom: 15px;
|
||||
left: 10px;
|
||||
width: 3px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-card-actions .van-button {
|
||||
height: 29px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.tour-submit-bar {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top-color: #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-submit-bar .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div id="app" class="tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-apply-page">
|
||||
<van-loading v-if="pageLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<div v-if="pageLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<div class="tour-apply-card">
|
||||
<div class="tour-apply-title">教职工信息</div>
|
||||
<van-field label="姓名" readonly v-model="signupForm.userName"></van-field>
|
||||
<van-field label="工号" readonly v-model="signupForm.jobNo"></van-field>
|
||||
<van-field label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field required label="身份证号码" v-model="signupForm.idCard" maxlength="30" placeholder="请填写身份证号码"></van-field>
|
||||
<van-field required label="手机号" v-model="signupForm.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field label="所属工会" readonly v-model="signupForm.unionName"></van-field>
|
||||
</div>
|
||||
|
||||
@@ -177,41 +337,81 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
当前线路不支持填写亲属
|
||||
</div>
|
||||
<template v-else-if="familyData.length > 0">
|
||||
<div class="tour-family-tab">亲属{{ familyActive + 1 }}</div>
|
||||
<van-field label="姓名" v-model="currentFamily.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field label="年龄" v-model.number="currentFamily.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="currentFamily.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="身份证号码" v-model="currentFamily.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(currentFamily)"></van-field>
|
||||
<van-field label="手机号" v-model="currentFamily.mobile" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="currentFamily.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="currentFamily.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="currentFamily.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="currentFamily.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
<div class="tour-family-tabs-shell" :class="{ 'has-arrows': familyData.length > 4 }">
|
||||
<button
|
||||
v-if="familyData.length > 4"
|
||||
type="button"
|
||||
class="tour-family-tab-arrow is-left"
|
||||
:disabled="familyActive <= 0"
|
||||
aria-label="上一位亲属"
|
||||
@click.stop="moveFamilyTab(-1)">
|
||||
<van-icon name="arrow-left"></van-icon>
|
||||
</button>
|
||||
<van-tabs
|
||||
ref="familyTabs"
|
||||
class="tour-family-tabs"
|
||||
:class="{ 'is-single': familyData.length === 1 }"
|
||||
v-model="familyActive"
|
||||
animated
|
||||
:duration="0.28"
|
||||
:ellipsis="false"
|
||||
:swipe-threshold="3"
|
||||
color="#1989fa"
|
||||
title-active-color="#1989fa"
|
||||
@change="handleFamilyTabChange">
|
||||
<van-tab
|
||||
v-for="(family, familyIndex) in familyData"
|
||||
:key="family.id || 'family-' + familyIndex"
|
||||
:title="familyTabTitle(family, familyIndex)">
|
||||
<div class="tour-family-form">
|
||||
<van-field required label="姓名" v-model="family.familyName" maxlength="100" placeholder="请填写姓名"></van-field>
|
||||
<van-field required label="年龄" v-model.number="family.age" type="digit" placeholder="请填写年龄"></van-field>
|
||||
<van-field required label="性别">
|
||||
<template #input>
|
||||
<van-radio-group v-model="family.gender" direction="horizontal">
|
||||
<van-radio name="男">男</van-radio>
|
||||
<van-radio name="女">女</van-radio>
|
||||
</van-radio-group>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field :required="familyContactRequired(family)" label="身份证号码" v-model="family.idCard" maxlength="18" placeholder="请填写身份证号码" @blur="normalizeFamilyIdCard(family)"></van-field>
|
||||
<van-field :required="familyContactRequired(family)" label="手机号" v-model="family.mobile" type="tel" maxlength="30" placeholder="请填写手机号"></van-field>
|
||||
<van-field
|
||||
required
|
||||
label="与本人关系"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择关系"
|
||||
v-model="family.relationship"
|
||||
@click="openRelationshipPicker">
|
||||
</van-field>
|
||||
<van-field
|
||||
v-if="fillBedInfo"
|
||||
label="床型"
|
||||
readonly
|
||||
clickable
|
||||
is-link
|
||||
placeholder="请选择房型"
|
||||
v-model="family.bedType"
|
||||
@click="openBedPicker('family')">
|
||||
</van-field>
|
||||
<van-field v-if="fillBedInfo" label="床位" v-model="family.bedInfo" maxlength="100" placeholder="请输入床位数量"></van-field>
|
||||
<van-field v-if="fillBedInfo" label="意向拼床人" v-model="family.intendedRoommate" maxlength="100" placeholder="请输入意向拼床人"></van-field>
|
||||
<div v-if="fillBedInfo" class="tour-field-tip">提醒:如果跟报名人员同一房间,无须选择!</div>
|
||||
</div>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
<button
|
||||
v-if="familyData.length > 4"
|
||||
type="button"
|
||||
class="tour-family-tab-arrow is-right"
|
||||
:disabled="familyActive >= familyData.length - 1"
|
||||
aria-label="下一位亲属"
|
||||
@click.stop="moveFamilyTab(1)">
|
||||
<van-icon name="arrow"></van-icon>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="tour-apply-empty">暂无亲属,请按需添加</div>
|
||||
</div>
|
||||
@@ -222,16 +422,16 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<van-button type="info" block round :loading="submitLoading" @click="submitSignup">提交报名</van-button>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="bedPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="bedPickerVisible=false"></van-picker>
|
||||
<van-popup v-model="bedPickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="bedTypeColumns" @confirm="confirmBedType" @cancel="closePicker('bed-picker')"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="relationshipPickerVisible=false"></van-picker>
|
||||
<van-popup v-model="relationshipPickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="relationshipColumns" @confirm="confirmRelationship" @cancel="closePicker('relationship-picker')"></van-picker>
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="directRelativePickerVisible=false"></van-picker>
|
||||
<van-popup v-model="directRelativePickerVisible" position="bottom" :close-on-click-overlay="false">
|
||||
<van-picker show-toolbar :columns="directRelativeColumns" @confirm="confirmDirectRelative" @cancel="closePicker('direct-relative-picker')"></van-picker>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
@@ -255,6 +455,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
bedPickerVisible: false,
|
||||
relationshipPickerVisible: false,
|
||||
directRelativePickerVisible: false,
|
||||
popupHistoryToken: "",
|
||||
bedPickerTarget: "self",
|
||||
matterId: GetQueryString("matterId") || ""
|
||||
}
|
||||
@@ -274,6 +475,52 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 页签优先展示亲属姓名;姓名尚未填写时使用亲属序号,便于区分每份亲属表单。
|
||||
familyTabTitle(family, familyIndex) {
|
||||
const familyName = family && family.familyName ? String(family.familyName).trim() : ""
|
||||
return familyName || "亲属" + (familyIndex + 1)
|
||||
},
|
||||
// 等待页签渲染完成后再滚动定位,确保新增亲属始终展示在可视区域内。
|
||||
focusFamilyTab(familyIndex) {
|
||||
const lastIndex = Math.max(this.familyData.length - 1, 0)
|
||||
const nextIndex = Math.min(Math.max(Number(familyIndex) || 0, 0), lastIndex)
|
||||
this.$set(this, "familyActive", nextIndex)
|
||||
this.$nextTick(() => {
|
||||
const familyTabs = this.$refs.familyTabs
|
||||
if (familyTabs && typeof familyTabs.resize === "function") {
|
||||
familyTabs.resize()
|
||||
}
|
||||
this.scrollFamilyTabIntoView(nextIndex)
|
||||
})
|
||||
},
|
||||
// 将当前亲属页签平滑定位到导航可视区域中间,兼容箭头切换和直接点击页签。
|
||||
scrollFamilyTabIntoView(familyIndex) {
|
||||
const familyTabs = this.$refs.familyTabs
|
||||
const tabRoot = familyTabs && familyTabs.$el
|
||||
if (!tabRoot) return
|
||||
const tabNav = tabRoot.querySelector(".van-tabs__nav")
|
||||
const tabItems = tabRoot.querySelectorAll(".van-tab")
|
||||
const currentTab = tabItems[familyIndex]
|
||||
if (!tabNav || !currentTab) return
|
||||
const maxScrollLeft = Math.max(tabNav.scrollWidth - tabNav.clientWidth, 0)
|
||||
const targetScrollLeft = currentTab.offsetLeft - (tabNav.clientWidth - currentTab.offsetWidth) / 2
|
||||
tabNav.scrollTo({
|
||||
left: Math.min(Math.max(targetScrollLeft, 0), maxScrollLeft),
|
||||
behavior: "smooth"
|
||||
})
|
||||
},
|
||||
// 直接点击页签时,等待 Vant 更新激活状态后再执行横向定位。
|
||||
handleFamilyTabChange(familyIndex) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollFamilyTabIntoView(Number(familyIndex) || 0)
|
||||
})
|
||||
},
|
||||
// 左右箭头按相邻顺序切换亲属,并复用页签组件的平滑定位能力。
|
||||
moveFamilyTab(step) {
|
||||
const nextIndex = Number(this.familyActive) + Number(step)
|
||||
if (nextIndex < 0 || nextIndex >= this.familyData.length) return
|
||||
this.focusFamilyTab(nextIndex)
|
||||
},
|
||||
formatDateTime(date) {
|
||||
const pad = (value) => String(value).padStart(2, "0")
|
||||
return date.getFullYear()
|
||||
@@ -426,13 +673,15 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
addFamily() {
|
||||
if (!this.allowFamily || this.isDirectFamilyLine(this.signupForm)) return
|
||||
this.familyData.push(this.emptyFamily())
|
||||
this.familyActive = this.familyData.length - 1
|
||||
this.focusFamilyTab(this.familyData.length - 1)
|
||||
this.signupForm.hasFamily = true
|
||||
},
|
||||
removeFamily() {
|
||||
if (this.familyData.length === 0) return
|
||||
this.familyData.splice(this.familyActive, 1)
|
||||
this.familyActive = Math.max(0, this.familyActive - 1)
|
||||
const removedIndex = this.familyActive
|
||||
this.familyData.splice(removedIndex, 1)
|
||||
// 删除当前页签后优先停留在同一位置;删除末项时回到新的最后一项。
|
||||
this.focusFamilyTab(this.familyData.length === 0 ? 0 : Math.min(removedIndex, this.familyData.length - 1))
|
||||
this.signupForm.hasFamily = this.familyData.length > 0
|
||||
},
|
||||
openBedPicker(target) {
|
||||
@@ -442,6 +691,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
this.bedPickerTarget = target
|
||||
this.bedPickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "bed-picker")
|
||||
},
|
||||
confirmBedType(value) {
|
||||
if (this.bedPickerTarget === "family") {
|
||||
@@ -449,7 +699,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
} else {
|
||||
this.signupForm.bedType = value
|
||||
}
|
||||
this.bedPickerVisible = false
|
||||
this.closePicker("bed-picker")
|
||||
},
|
||||
openRelationshipPicker() {
|
||||
if (this.relationshipColumns.length === 0) {
|
||||
@@ -457,10 +707,11 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
this.relationshipPickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "relationship-picker")
|
||||
},
|
||||
confirmRelationship(value) {
|
||||
this.currentFamily.relationship = value
|
||||
this.relationshipPickerVisible = false
|
||||
this.closePicker("relationship-picker")
|
||||
},
|
||||
openDirectRelativePicker() {
|
||||
if (this.directRelativeColumns.length === 0) {
|
||||
@@ -468,12 +719,27 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
this.directRelativePickerVisible = true
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "direct-relative-picker")
|
||||
},
|
||||
confirmDirectRelative(value) {
|
||||
const item = value && value.item ? value.item : {}
|
||||
this.directRelativeForm.relationshipCode = item.code || ""
|
||||
this.directRelativeForm.relationshipName = item.name || value.text || ""
|
||||
this.directRelativePickerVisible = false
|
||||
this.closePicker("direct-relative-picker")
|
||||
},
|
||||
closePicker(popupKey) {
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, popupKey)) {
|
||||
this.syncPickerVisible(popupKey, false)
|
||||
}
|
||||
},
|
||||
syncPickerVisible(popupKey, visible) {
|
||||
if (popupKey === "bed-picker") {
|
||||
this.bedPickerVisible = visible
|
||||
} else if (popupKey === "relationship-picker") {
|
||||
this.relationshipPickerVisible = visible
|
||||
} else if (popupKey === "direct-relative-picker") {
|
||||
this.directRelativePickerVisible = visible
|
||||
}
|
||||
},
|
||||
normalizeFamilyIdCard(row) {
|
||||
if (!row || !row.idCard) return
|
||||
@@ -484,18 +750,46 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
const idCard = String(value).trim().toUpperCase()
|
||||
return /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/.test(idCard)
|
||||
},
|
||||
isBlankValue(value) {
|
||||
return value === undefined || value === null || !String(value).trim()
|
||||
},
|
||||
// 年满16周岁的亲属才强制填写身份证号码和手机号。
|
||||
familyContactRequired(family) {
|
||||
return family && !this.isBlankValue(family.age) && Number(family.age) >= 16
|
||||
},
|
||||
// 报名人身份证号码和手机号为提交报名的基础必填信息。
|
||||
validateSignupContact() {
|
||||
if (this.isBlankValue(this.signupForm.idCard)) {
|
||||
vant.Toast("请填写身份证号码")
|
||||
return false
|
||||
}
|
||||
if (this.isBlankValue(this.signupForm.mobile)) {
|
||||
vant.Toast("请填写手机号")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
validateFamilies() {
|
||||
if (!this.allowFamily || !this.signupForm.hasFamily) return true
|
||||
if (this.familyData.length === 0) {
|
||||
vant.Toast("请添加亲属信息")
|
||||
return false
|
||||
}
|
||||
const invalid = this.familyData.some(item => !item.familyName || !item.gender || !item.idCard || !item.relationship)
|
||||
if (invalid) {
|
||||
vant.Toast("请完善亲属姓名、性别、身份证号码和关系")
|
||||
const invalidBase = this.familyData.some(item => this.isBlankValue(item.familyName)
|
||||
|| this.isBlankValue(item.age)
|
||||
|| this.isBlankValue(item.gender)
|
||||
|| this.isBlankValue(item.relationship))
|
||||
if (invalidBase) {
|
||||
vant.Toast("请完善亲属姓名、年龄、性别和与本人关系")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isValidIdCard(item.idCard))
|
||||
const invalidContact = this.familyData.some(item => this.familyContactRequired(item)
|
||||
&& (this.isBlankValue(item.idCard) || this.isBlankValue(item.mobile)))
|
||||
if (invalidContact) {
|
||||
vant.Toast("年满16周岁的亲属必须填写身份证号码和手机号")
|
||||
return false
|
||||
}
|
||||
const invalidIdCard = this.familyData.some(item => !this.isBlankValue(item.idCard) && !this.isValidIdCard(item.idCard))
|
||||
if (invalidIdCard) {
|
||||
vant.Toast("请输入正确的亲属身份证号码")
|
||||
return false
|
||||
@@ -528,6 +822,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
},
|
||||
submitSignup() {
|
||||
if (this.pageLoading || this.submitLoading) return
|
||||
if (!this.validateSignupContact()) return
|
||||
if (!this.validateFamilies()) return
|
||||
if (!this.validateDirectRelative()) return
|
||||
const families = this.allowFamily && this.signupForm.hasFamily ? this.familyData : []
|
||||
@@ -537,13 +832,13 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
this.submitLoading = true
|
||||
this.$axios.post("/platform/tour/signup/doSignup", form).then((res) => {
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
vant.Dialog.alert({
|
||||
title: "提示",
|
||||
message: res.msg || "报名成功",
|
||||
confirmButtonColor: "#1867b0"
|
||||
}).then(() => {
|
||||
this.$showH5PageSkeleton()
|
||||
window.location.replace("/platform/tour/signup/h5/signup")
|
||||
})
|
||||
} else {
|
||||
@@ -554,13 +849,20 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
this.submitLoading = false
|
||||
// 接口失败提示由全局 Axios 拦截器统一展示,避免与名额已满等业务提示重复。
|
||||
}).finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.popupHistoryToken = window.h5PopupHistory.register((popupKey) => {
|
||||
this.syncPickerVisible(popupKey, false)
|
||||
})
|
||||
this.init()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -163,9 +163,122 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
box-sizing: border-box;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
#app.tour-signup-h5 {
|
||||
padding-bottom: 0;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-signup-banner {
|
||||
height: 208px;
|
||||
margin: 12px 12px 0;
|
||||
border-radius: 14px;
|
||||
background-color: #1779d8;
|
||||
box-shadow: 0 8px 22px rgba(30, 112, 207, .2);
|
||||
}
|
||||
|
||||
.tour-signup-swipe img {
|
||||
height: 208px;
|
||||
}
|
||||
|
||||
.tour-signup-banner::after {
|
||||
background: linear-gradient(90deg, rgba(8, 72, 145, .74) 0%, rgba(8, 72, 145, .36) 51%, rgba(8, 72, 145, .04) 100%);
|
||||
}
|
||||
|
||||
.tour-signup-banner__text {
|
||||
left: 18px;
|
||||
bottom: 25px;
|
||||
}
|
||||
|
||||
.tour-signup-title {
|
||||
width: 180px;
|
||||
font-size: 25px;
|
||||
line-height: 1.35;
|
||||
letter-spacing: .5px;
|
||||
}
|
||||
|
||||
.tour-signup-subtitle {
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tour-signup-card {
|
||||
margin: 12px 12px 0;
|
||||
padding: 14px 14px 16px;
|
||||
height: calc(100vh - 352px);
|
||||
height: calc(100vh - 352px - env(safe-area-inset-bottom));
|
||||
min-height: 240px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .09);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-card__header {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* 标题栏保持固定,富文本、PDF、空状态及加载骨架只在卡片剩余区域内滚动。 */
|
||||
.tour-signup-card > .van-skeleton,
|
||||
.tour-signup-card > .tour-signup-notice,
|
||||
.tour-signup-card > .tour-signup-empty {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.tour-signup-card__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-signup-card__title .van-icon {
|
||||
margin-right: 7px;
|
||||
color: #1989fa;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.tour-signup-card__year {
|
||||
min-height: 24px;
|
||||
padding: 2px 9px;
|
||||
border-radius: 12px;
|
||||
background-color: #eaf4ff;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-signup-notice {
|
||||
font-size: 14px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.tour-signup-footer {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-signup-footer-spacer {
|
||||
height: 62px;
|
||||
height: calc(62px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-signup-footer .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-signup-h5">
|
||||
<div id="app" class="tour-signup-h5 tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养报名" left-text="返回" left-arrow @click-left="$pjaxReplace('/platform/h5/home')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-signup-banner">
|
||||
@@ -175,13 +288,14 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
<div class="tour-signup-banner__text">
|
||||
<div class="tour-signup-title">疗休养报名</div>
|
||||
<div class="tour-signup-title">工会疗休养<br>乐享健康时光</div>
|
||||
<div class="tour-signup-subtitle">放松身心 · 收获健康 · 美好同行</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-signup-card">
|
||||
<div class="tour-signup-card__header">
|
||||
<div class="tour-signup-card__title">服务须知</div>
|
||||
<div class="tour-signup-card__title"><van-icon name="notes-o"></van-icon>报名须知</div>
|
||||
<div class="tour-signup-card__year">{{ setting.year || currentYear }}年度</div>
|
||||
</div>
|
||||
|
||||
@@ -227,7 +341,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
store,
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loading: true,
|
||||
currentYear: new Date().getFullYear(),
|
||||
serviceNoticePdfHref: "",
|
||||
pdfDoc: null,
|
||||
@@ -240,8 +354,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
readCountdown: 10,
|
||||
readCountdownTimer: null,
|
||||
bannerList: [
|
||||
"/assets/platform/images/tour/tour-h5-banner-1.jpg",
|
||||
"/assets/platform/images/tour/tour-h5-banner-2.jpg"
|
||||
"/assets/platform/images/tour/tour-h5-hero-v3.png?v=20260830"
|
||||
],
|
||||
setting: {
|
||||
year: "",
|
||||
@@ -419,7 +532,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
loadServiceNotice() {
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/serviceNotice").then((res) => {
|
||||
this.loading = false
|
||||
if (res.code === 0) {
|
||||
this.setting = Object.assign({}, this.setting, res.data || {})
|
||||
this.serviceNoticePdfHref = this.parseContentHref(this.setting.serviceNotice)
|
||||
@@ -430,6 +542,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
vant.Toast(res.msg || "服务须知加载失败")
|
||||
}
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -170,14 +170,111 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
#app {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-detail-page {
|
||||
padding: 12px 12px 76px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-detail-cover {
|
||||
width: 100%;
|
||||
height: 178px;
|
||||
flex: none;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #eaf2fb;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .1);
|
||||
}
|
||||
|
||||
.tour-detail-cover .van-image__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.tour-detail-header {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-detail-title {
|
||||
color: #202938;
|
||||
font-size: 18px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.tour-line-tag {
|
||||
min-height: 22px;
|
||||
height: auto;
|
||||
padding: 2px 8px;
|
||||
border-radius: 11px;
|
||||
color: #1989fa;
|
||||
background-color: #eaf4ff;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-detail-meta {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
color: #35445a;
|
||||
font-size: 13px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.tour-detail-section {
|
||||
margin-top: 10px;
|
||||
padding: 14px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-detail-section-title {
|
||||
margin-bottom: 10px;
|
||||
border-left-color: #1989fa;
|
||||
color: #202938;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-detail-footer {
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
|
||||
border-top-color: #edf1f6;
|
||||
box-shadow: 0 -6px 18px rgba(38, 66, 103, .08);
|
||||
}
|
||||
|
||||
.tour-detail-footer .van-button {
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app">
|
||||
<div id="app" class="tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="线路详情" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5/signup')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-detail-page">
|
||||
<van-loading v-if="detailLoading" size="24px" vertical>加载中...</van-loading>
|
||||
<div v-if="detailLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__cover"></div>
|
||||
<div class="tour-content-skeleton__title"></div>
|
||||
<div class="tour-content-skeleton__row"></div>
|
||||
<div class="tour-content-skeleton__row"></div>
|
||||
<div class="tour-content-skeleton__card"></div>
|
||||
</div>
|
||||
<template v-else>
|
||||
<van-image class="tour-detail-cover" :src="detailCover()" fit="cover">
|
||||
<template #loading><van-loading type="spinner" size="22"></van-loading></template>
|
||||
<template #error><van-icon name="photo-o" size="36" color="#9ba9bc"></van-icon></template>
|
||||
</van-image>
|
||||
<div class="tour-detail-header">
|
||||
<div class="tour-detail-title">{{ lineDetail.lineName || signupDetail.lineName || '线路详情' }}</div>
|
||||
<div class="tour-detail-tags">
|
||||
@@ -257,6 +354,9 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
detailCover() {
|
||||
return this.lineDetail.mobileThumb || "/assets/platform/images/tour/tour-h5-hero-v3.png?v=20260830"
|
||||
},
|
||||
travelPeriod(row) {
|
||||
if (!row) {
|
||||
return ""
|
||||
@@ -493,7 +593,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.$axios.post("/platform/tour/signup/lineDetail", { lineId: this.lineId }),
|
||||
this.$axios.post("/platform/tour/signup/signupDetail", { matterId: this.matterId })
|
||||
]).then(([lineRes, signupRes]) => {
|
||||
this.detailLoading = false
|
||||
if (lineRes.code !== 0) {
|
||||
vant.Toast(lineRes.msg || "线路详情加载失败")
|
||||
} else {
|
||||
@@ -513,8 +612,9 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}, process)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.detailLoading = false
|
||||
vant.Toast("线路详情加载失败")
|
||||
}).finally(() => {
|
||||
this.detailLoading = false
|
||||
})
|
||||
},
|
||||
onApply() {
|
||||
@@ -523,7 +623,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
const goApply = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId)
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(this.matterId))
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: this.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
|
||||
@@ -21,6 +21,10 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-refresh {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 10px 0 8px 16px;
|
||||
background: #f4f6f8;
|
||||
@@ -60,52 +64,51 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
.tour-line-search-button {
|
||||
width: 42px;
|
||||
height: 38px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #1e88e5;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-search-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
width: 48px;
|
||||
min-height: 42px;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
margin-top: 8px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
padding: 0 14px;
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
color: #66758a;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #64748b;
|
||||
font-size: 24px;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tour-line-union-entry__label {
|
||||
display: inline-flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.tour-line-union-entry__text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-line-union-entry--active,
|
||||
.tour-line-union-entry--active .van-icon {
|
||||
color: #0b75bd;
|
||||
@@ -376,25 +379,252 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.tour-line-thumb-loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #edf2f8 25%, #f8fbff 37%, #edf2f8 63%);
|
||||
background-size: 400% 100%;
|
||||
animation: tour-content-skeleton-loading 1.35s ease infinite;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
.tour-line-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-line-toolbar {
|
||||
padding: 12px 12px 10px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search {
|
||||
display: flex;
|
||||
width: 0;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-search__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-line-toolbar .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-line-union-entry {
|
||||
color: #66758a;
|
||||
}
|
||||
|
||||
.tour-line-union-entry .van-icon {
|
||||
color: #8fa0b5;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry {
|
||||
width: 52px;
|
||||
height: 42px;
|
||||
min-height: 42px;
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
border-radius: 0;
|
||||
color: #66758a;
|
||||
background: transparent;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry .van-icon {
|
||||
color: #8fa0b5;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.tour-line-search-row .tour-line-union-entry--active,
|
||||
.tour-line-search-row .tour-line-union-entry--active .van-icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-line-shortcuts {
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut {
|
||||
min-height: 86px;
|
||||
padding: 11px 5px 9px;
|
||||
border-radius: 11px;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .07);
|
||||
}
|
||||
|
||||
.tour-line-shortcut__icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__text {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tour-line-shortcut__hint {
|
||||
color: #9aa7b8;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.tour-line-scroll {
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
|
||||
.tour-line-list {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.tour-line-card {
|
||||
display: block;
|
||||
min-height: 0;
|
||||
margin: 0 0 10px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 7px 20px rgba(55, 85, 126, .08);
|
||||
}
|
||||
|
||||
.tour-line-thumb {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.tour-line-main {
|
||||
position: relative;
|
||||
padding: 12px 38px 14px 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tour-line-title {
|
||||
overflow: hidden;
|
||||
color: #303846;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-line-type-badge,
|
||||
.tour-line-tag {
|
||||
height: auto;
|
||||
padding: 3px 8px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
color: #397de0;
|
||||
background-color: #edf5ff;
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-line-info {
|
||||
margin-top: 4px;
|
||||
padding-top: 0;
|
||||
border-top: 0;
|
||||
color: #98a2b2;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-line-info span {
|
||||
color: #98a2b2;
|
||||
}
|
||||
|
||||
.tour-line-tags {
|
||||
margin-top: 10px;
|
||||
padding-top: 9px;
|
||||
gap: 6px;
|
||||
border-top: 1px solid #edf1f6;
|
||||
}
|
||||
|
||||
.tour-line-card__arrow {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 14px;
|
||||
color: #b4bdca;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tour-line-actions {
|
||||
margin-top: 10px;
|
||||
margin-right: -24px;
|
||||
}
|
||||
|
||||
.tour-line-action {
|
||||
display: inline-flex;
|
||||
min-width: 64px;
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #1989fa;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
color: #1989fa;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-line-action .van-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-line-action--danger {
|
||||
border-color: #ee4d5a;
|
||||
color: #ee4d5a;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-line-action--disabled {
|
||||
border-color: #d8dee8;
|
||||
color: #b8c0cc;
|
||||
background: transparent;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-line-page">
|
||||
<div id="app" class="tour-line-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="疗休养线路" left-text="返回" left-arrow @click-left="historyBack('/platform/tour/signup/h5')" fixed placeholder></van-nav-bar>
|
||||
|
||||
<div class="tour-line-toolbar">
|
||||
<div class="tour-line-search-row">
|
||||
<van-search
|
||||
v-model="pageForm.lineName"
|
||||
show-action
|
||||
clearable
|
||||
placeholder="请输入线路名称搜索"
|
||||
shape="round"
|
||||
placeholder="搜索疗休养线路"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<button type="button" class="tour-line-search-button" @click="doSearch">
|
||||
<van-icon name="search"></van-icon>
|
||||
</button>
|
||||
</template>
|
||||
</van-search>
|
||||
<button
|
||||
type="button"
|
||||
@@ -413,6 +643,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-in-province.png" alt="省内线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省内线路</div>
|
||||
<div class="tour-line-shortcut__hint">发现身边美景</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -422,6 +653,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-out-province.png" alt="省外线路">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>省外线路</div>
|
||||
<div class="tour-line-shortcut__hint">畅游大好河山</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -431,23 +663,29 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<img class="tour-line-shortcut__icon" src="/assets/platform/images/tour/tour-direct-family-icon.png?v=20260524" alt="直系亲属">
|
||||
<div class="tour-line-shortcut__text">
|
||||
<div>直系亲属</div>
|
||||
<div class="tour-line-shortcut__hint">家属同行共享</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tour-line-scroll">
|
||||
<van-pull-refresh class="tour-line-refresh" v-model="refreshing" @refresh="onRefresh">
|
||||
<div v-if="initialLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'line-skeleton-' + index"></div>
|
||||
</div>
|
||||
<van-list
|
||||
v-else
|
||||
v-model="loading"
|
||||
:finished="finished"
|
||||
finished-text="没有更多了"
|
||||
:finished-text="list.length > 0 ? '没有更多了' : ''"
|
||||
@load="loadData">
|
||||
<div class="tour-line-list">
|
||||
<div class="tour-line-card" v-for="row in list" :key="row.matterId" @click="onLine(row)">
|
||||
<div class="tour-line-thumb">
|
||||
<van-image v-if="thumbUrl(row)" :src="thumbUrl(row)" fit="cover" lazy-load>
|
||||
<template #loading>
|
||||
<div class="tour-line-thumb-empty">图片加载中</div>
|
||||
<div class="tour-line-thumb-loading" aria-label="图片加载中"></div>
|
||||
</template>
|
||||
<template #error>
|
||||
<div class="tour-line-thumb-empty">暂无图片</div>
|
||||
@@ -463,10 +701,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<van-icon name="good-job"></van-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<div class="tour-line-info">
|
||||
<div><span>出行开始时间:</span>{{ row.travelStartTime || '暂无' }}</div>
|
||||
<div><span>出行结束时间:</span>{{ row.travelEndTime || '暂无' }}</div>
|
||||
@@ -474,6 +708,11 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
<div><span>服务单位:</span>{{ row.travelAgencyName || '暂无' }}</div>
|
||||
-->
|
||||
</div>
|
||||
<div class="tour-line-tags">
|
||||
<span v-if="row.lotName" class="tour-line-tag">{{ row.lotName }}</span>
|
||||
<span v-if="row.unionName" class="tour-line-tag">{{ row.unionName }}</span>
|
||||
</div>
|
||||
<van-icon class="tour-line-card__arrow" name="arrow"></van-icon>
|
||||
<div class="tour-line-actions">
|
||||
<button
|
||||
v-if="showSignupAction(row)"
|
||||
@@ -485,7 +724,8 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}"
|
||||
:disabled="signupActionDisabled(row)"
|
||||
@click.stop="handleSignupAction(row)">
|
||||
{{ signupActionText(row) }}
|
||||
<van-icon :name="canRevokeSignup(row) ? 'revoke' : 'edit'"></van-icon>
|
||||
<span>{{ signupActionText(row) }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -493,10 +733,15 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
</div>
|
||||
</van-list>
|
||||
|
||||
<van-empty v-if="!loading && list.length === 0" description="暂无线路"></van-empty>
|
||||
<div v-if="!loading && list.length === 0" class="tour-h5-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无线路插画">
|
||||
<div class="tour-h5-empty__title">暂无线路</div>
|
||||
<div class="tour-h5-empty__hint">当前筛选条件下暂未发布疗休养线路</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
</div>
|
||||
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round>
|
||||
<van-popup v-model="showUnionPopup" position="bottom" round :close-on-click-overlay="false" @click-overlay="closeUnionPopup">
|
||||
<div class="tour-line-union-popup">
|
||||
<div class="tour-line-union-popup__title">选择分工会</div>
|
||||
<div class="tour-line-union-popup__list">
|
||||
@@ -525,9 +770,12 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return {
|
||||
list: [],
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
initialLoading: true,
|
||||
finished: false,
|
||||
lineChecking: false,
|
||||
showUnionPopup: false,
|
||||
popupHistoryToken: "",
|
||||
unionList: [
|
||||
{id: "", name: "全部分工会"}
|
||||
],
|
||||
@@ -619,7 +867,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
return
|
||||
}
|
||||
const go = () => {
|
||||
window.location.href = "/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId)
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/apply?matterId=" + encodeURIComponent(row.matterId))
|
||||
}
|
||||
this.$axios.post("/platform/tour/signup/signupEligibilityNotice", { matterId: row.matterId }).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
@@ -672,6 +920,7 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.list = []
|
||||
this.$set(this, "initialLoading", true)
|
||||
this.finished = false
|
||||
this.loadData()
|
||||
},
|
||||
@@ -689,17 +938,26 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
},
|
||||
openUnionPopup() {
|
||||
this.showUnionPopup = true
|
||||
if (this.popupHistoryToken) {
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "union-picker")
|
||||
}
|
||||
if (this.unionList.length <= 1) {
|
||||
this.loadUnionOptions()
|
||||
}
|
||||
},
|
||||
closeUnionPopup() {
|
||||
if (!this.popupHistoryToken || !window.h5PopupHistory.close(this.popupHistoryToken, "union-picker")) {
|
||||
this.showUnionPopup = false
|
||||
}
|
||||
},
|
||||
selectUnion(item) {
|
||||
const unionId = item && item.id ? item.id : ""
|
||||
this.showUnionPopup = false
|
||||
if (this.pageForm.unionId === unionId) {
|
||||
this.closeUnionPopup()
|
||||
return
|
||||
}
|
||||
this.pageForm.unionId = unionId
|
||||
this.closeUnionPopup()
|
||||
this.doSearch()
|
||||
},
|
||||
loadUnionOptions() {
|
||||
@@ -723,7 +981,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.post("/platform/tour/signup/h5/pageData", this.pageForm).then((res) => {
|
||||
this.loading = false
|
||||
if (res.code !== 0) {
|
||||
vant.Toast(res.msg || "线路加载失败")
|
||||
this.finished = true
|
||||
@@ -739,10 +996,27 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
this.pageForm.pageNumber += 1
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.finished = true
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
this.$set(this, "refreshing", false)
|
||||
this.$set(this, "initialLoading", false)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 下拉刷新当前筛选结果:保留线路名称、线路类型和分工会条件,只重置分页数据。
|
||||
*/
|
||||
onRefresh() {
|
||||
if (this.loading) {
|
||||
this.$set(this, "refreshing", false)
|
||||
return
|
||||
}
|
||||
this.$set(this.pageForm, "pageNumber", 1)
|
||||
this.$set(this.pageForm, "totalCount", 0)
|
||||
this.$set(this, "list", [])
|
||||
this.$set(this, "finished", false)
|
||||
this.loadData()
|
||||
},
|
||||
onLine(row) {
|
||||
if (!row || !row.lineId || !row.matterId) {
|
||||
vant.Toast("线路信息不完整")
|
||||
@@ -758,7 +1032,6 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
"x-requested-with": "XMLHttpRequest"
|
||||
}
|
||||
}).then((resp) => {
|
||||
this.lineChecking = false
|
||||
const res = resp.data || {}
|
||||
if (res.code !== 0) {
|
||||
vant.Dialog.alert({
|
||||
@@ -768,23 +1041,32 @@ layout("/layouts/platform_tour_signup_h5.html"){
|
||||
})
|
||||
return
|
||||
}
|
||||
window.location.href = "/platform/tour/signup/h5/lineInfo?matterId="
|
||||
this.$pjaxReplace("/platform/tour/signup/h5/lineInfo?matterId="
|
||||
+ encodeURIComponent(row.matterId)
|
||||
+ "&lineId="
|
||||
+ encodeURIComponent(row.lineId)
|
||||
+ encodeURIComponent(row.lineId))
|
||||
}).catch((err) => {
|
||||
this.lineChecking = false
|
||||
vant.Dialog.alert({
|
||||
title: "温馨提醒",
|
||||
message: err && err.msg ? err.msg : "当前线路暂不能报名",
|
||||
confirmButtonColor: "#1867b0"
|
||||
})
|
||||
}).finally(() => {
|
||||
this.lineChecking = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.popupHistoryToken = window.h5PopupHistory.register((popupKey) => {
|
||||
if (popupKey === "union-picker") {
|
||||
this.showUnionPopup = false
|
||||
}
|
||||
})
|
||||
this.loadUnionOptions()
|
||||
this.loadData()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
+409
-42
@@ -2,34 +2,36 @@
|
||||
layout("/layouts/platform_h5.html"){
|
||||
#-->
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.tour-approval-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f4f6f8;
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
flex-shrink: 0;
|
||||
background: #f4f6f8;
|
||||
padding: 8px 12px 10px;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 18px;
|
||||
padding: 2px 12px 18px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-search /deep/ .van-search__content,
|
||||
.tour-approval-search .van-search__content {
|
||||
border-radius: 8px;
|
||||
border-radius: 18px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
@@ -39,12 +41,36 @@ layout("/layouts/platform_h5.html"){
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
overflow: hidden;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
margin-left: 7px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.tour-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
border-radius: 999px;
|
||||
background: #eef6ff;
|
||||
color: #0b75bd;
|
||||
font-size: 12px;
|
||||
@@ -60,17 +86,24 @@ layout("/layouts/platform_h5.html"){
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.tour-approval-detail {
|
||||
height: 100%;
|
||||
background: #f4f8ff;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
max-height: 86vh;
|
||||
height: calc(100% - 46px);
|
||||
overflow-y: auto;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background: #f4f6f8;
|
||||
padding: 2px 0 calc(86px + env(safe-area-inset-bottom));
|
||||
background: #f4f8ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 10px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
@@ -78,7 +111,7 @@ layout("/layouts/platform_h5.html"){
|
||||
position: relative;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #edf0f4;
|
||||
color: #0b75bd;
|
||||
color: #17233d;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
@@ -92,7 +125,7 @@ layout("/layouts/platform_h5.html"){
|
||||
width: 30px;
|
||||
height: 4px;
|
||||
border-radius: 0 0 3px 3px;
|
||||
background: #0b75bd;
|
||||
background: #1677ff;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
@@ -106,9 +139,303 @@ layout("/layouts/platform_h5.html"){
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.tour-approval-sticky /deep/ .van-dropdown-menu__bar,
|
||||
.tour-approval-sticky .van-dropdown-menu__bar {
|
||||
height: 44px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .table-list-card,
|
||||
.tour-approval-list-scroll /deep/ .list-card {
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 16px rgba(34, 94, 170, 0.06);
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll /deep/ .action-btn {
|
||||
color: #1677ff;
|
||||
}
|
||||
|
||||
<!--#include("../common/theme.css"){}#-->
|
||||
|
||||
/* 审核列表与提案校工会预审核采用同一信息层级和卡片规范。 */
|
||||
body {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-page .van-nav-bar__title {
|
||||
color: #172033;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-sticky {
|
||||
padding: 22px 12px 1px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-search {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .1);
|
||||
}
|
||||
|
||||
.tour-approval-search .van-search__content {
|
||||
height: 42px;
|
||||
padding-left: 12px;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.tour-approval-search .van-field__control {
|
||||
color: #263548;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-filter {
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 5px 16px rgba(43, 73, 112, .08);
|
||||
transition: border-radius .18s ease;
|
||||
}
|
||||
|
||||
.tour-approval-filter.is-open {
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar,
|
||||
.tour-approval-filter .van-dropdown-menu__item,
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__bar {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: #66758a;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-menu__title--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active,
|
||||
.tour-approval-filter .van-dropdown-item__option--active .van-dropdown-item__icon {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__content {
|
||||
width: calc(100% - 24px);
|
||||
margin: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 10px 24px rgba(31, 65, 108, .14);
|
||||
}
|
||||
|
||||
.tour-approval-filter .van-dropdown-item__option {
|
||||
display: flex;
|
||||
min-height: 48px;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
color: #46566c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll {
|
||||
padding: 2px 12px 24px;
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .empty-state {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tour-approval-empty {
|
||||
display: flex;
|
||||
min-height: 280px;
|
||||
padding: 46px 18px 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-approval-empty img {
|
||||
display: block;
|
||||
width: 60%;
|
||||
max-width: 190px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.tour-approval-empty__title {
|
||||
margin-top: 10px;
|
||||
color: #50627a;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-approval-empty__hint {
|
||||
margin-top: 5px;
|
||||
color: #9aa7b8;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-heading {
|
||||
margin: 0 0 7px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tour-card-heading-main {
|
||||
min-width: 0;
|
||||
padding-right: 10px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tour-card-person {
|
||||
color: #253247;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-card-job-no {
|
||||
display: block;
|
||||
margin: 1px 0 0;
|
||||
color: #9ba6b6;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tour-card-status {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.tour-card-tags {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-approval-list-scroll .action-btn .van-icon {
|
||||
margin-right: 6px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tour-approval-detail,
|
||||
.tour-approval-sheet {
|
||||
background-color: #f3f7fd;
|
||||
}
|
||||
|
||||
.tour-approval-sheet {
|
||||
padding: 18px 12px calc(92px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.tour-section {
|
||||
margin: 0 0 11px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e9eff7;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 11px rgba(51, 87, 126, .08);
|
||||
}
|
||||
|
||||
.tour-section-title {
|
||||
position: relative;
|
||||
padding: 12px 14px 8px 21px;
|
||||
border-bottom: 0;
|
||||
color: #354255;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tour-section-title::before {
|
||||
top: 15px;
|
||||
bottom: 11px;
|
||||
left: 12px;
|
||||
width: 2px;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
.tour-section .van-cell {
|
||||
min-height: 44px;
|
||||
padding: 10px 14px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__title {
|
||||
flex: 0 0 92px;
|
||||
width: 92px;
|
||||
color: #596779;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tour-section .van-cell__value {
|
||||
color: #4f5d70;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.tour-section .tour-approval-opinion {
|
||||
width: calc(100% - 28px);
|
||||
margin: 0 14px 14px;
|
||||
padding: 12px;
|
||||
border: 1px solid #c9d5e5;
|
||||
border-radius: 10px;
|
||||
background-color: #f7f9fd;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tour-approval-actions {
|
||||
gap: 10px;
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.tour-approval-actions .van-button {
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.tour-approval-sticky,
|
||||
.tour-approval-list-scroll {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" class="tour-approval-page" v-cloak>
|
||||
<div id="app" class="tour-approval-page tour-h5-theme" v-cloak>
|
||||
<van-nav-bar title="分工会审核" left-text="返回" left-arrow @click-left="historyBack" fixed placeholder></van-nav-bar>
|
||||
|
||||
<van-sticky offset-top="46px" class="tour-approval-sticky">
|
||||
@@ -116,26 +443,38 @@ layout("/layouts/platform_h5.html"){
|
||||
class="tour-approval-search"
|
||||
v-model="pageForm.keyword"
|
||||
placeholder="请输入工号/姓名/线路搜索"
|
||||
show-action
|
||||
clearable
|
||||
input-align="left"
|
||||
@search="doSearch"
|
||||
@clear="doSearch">
|
||||
<template #action>
|
||||
<div @click="doSearch">搜索</div>
|
||||
</template>
|
||||
</van-search>
|
||||
<van-dropdown-menu :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
<van-dropdown-menu class="tour-approval-filter" :class="{'is-open': filterOpened}" active-color="#1989fa" :close-on-click-outside="false" :close-on-click-overlay="false">
|
||||
<van-dropdown-item :options="auditOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.audit"></van-dropdown-item>
|
||||
<van-dropdown-item :options="lineTypeOptions" @change="doSearch" @open="onFilterOpen" @close="onFilterClose" v-model="pageForm.lineType"></van-dropdown-item>
|
||||
</van-dropdown-menu>
|
||||
</van-sticky>
|
||||
|
||||
<div class="tour-approval-list-scroll">
|
||||
<table-list api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" @ready="onReady">
|
||||
<div v-if="pageSkeletonLoading" class="tour-content-skeleton">
|
||||
<div class="tour-content-skeleton__card" v-for="index in 3" :key="'union-approval-skeleton-' + index"></div>
|
||||
</div>
|
||||
<div v-if="!pageSkeletonLoading && pageForm.totalCount === 0" class="tour-approval-empty">
|
||||
<img src="/assets/platform/images/tour/tour-h5-empty-v3.png?v=20260831" alt="暂无审核记录插画">
|
||||
<div class="tour-approval-empty__title">暂无审核记录</div>
|
||||
<div class="tour-approval-empty__hint">当前筛选条件下暂时没有疗休养报名</div>
|
||||
</div>
|
||||
<table-list v-show="!pageSkeletonLoading" api="/platform/tour/unionApproval/pageData" :page_form.sync="pageForm" ref="tableListRef" title="userName" :show_loading_overlay="false" @ready="onReady" @loading-change="onTableLoading">
|
||||
<template #header="{index,row}">
|
||||
<div class="tour-card-heading">
|
||||
<div class="tour-card-heading-main">
|
||||
<div class="tour-card-person">{{ row.userName || '--' }}</div>
|
||||
<div class="tour-card-job-no">工号:{{ row.jobNo || '--' }}</div>
|
||||
</div>
|
||||
<span class="tour-h5-tag tour-card-status" :class="row.taskState === 10 ? 'is-warning' : 'is-success'">{{ row.curTaskName || (row.taskState === 10 ? '待审核' : '已处理') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot="{index,row}">
|
||||
<div class="tour-card-tags">
|
||||
<span v-if="row.jobNo" class="tour-tag">{{ row.jobNo }}</span>
|
||||
<span v-if="row.lineType" class="tour-tag gray">{{ row.lineType }}</span>
|
||||
<span v-if="row.overCostReimbursed" class="tour-tag warn">报销超出费用</span>
|
||||
</div>
|
||||
@@ -155,11 +494,11 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
<template #actions="{index,row}">
|
||||
<div class="action-btn" @click="onView(row)">
|
||||
<i class="fa fa-eye"></i>
|
||||
<van-icon name="eye-o"></van-icon>
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="action-btn" v-if="row.taskState === 10" @click="onApproval(row)">
|
||||
<i class="fa fa-check"></i>
|
||||
<van-icon name="edit"></van-icon>
|
||||
<span>审核</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -171,6 +510,7 @@ layout("/layouts/platform_h5.html"){
|
||||
<div class="tour-section-title">{{ formData.taskName || '审核' }}</div>
|
||||
<van-form ref="formRef">
|
||||
<van-field
|
||||
class="tour-approval-opinion"
|
||||
v-model="formData.tf_opinion"
|
||||
name="tf_opinion"
|
||||
label="审批意见"
|
||||
@@ -195,8 +535,10 @@ layout("/layouts/platform_h5.html"){
|
||||
<script nonce="${cspNonce!}">
|
||||
const TOUR_INFO = {
|
||||
template: /*language=HTML*/ `
|
||||
<van-action-sheet v-model="visible" title="报名详情">
|
||||
<div class="tour-approval-sheet">
|
||||
<van-popup v-model="visible" position="right" :style="{ width: '100%', height: '100%' }" :close-on-click-overlay="false">
|
||||
<div class="tour-approval-detail">
|
||||
<van-nav-bar title="报名详情" left-text="返回" left-arrow @click-left="onClose"></van-nav-bar>
|
||||
<div class="tour-approval-sheet">
|
||||
<div class="tour-section">
|
||||
<div class="tour-section-title">教职工信息</div>
|
||||
<van-cell title="工号" :value="detail.jobNo || ''"></van-cell>
|
||||
@@ -259,9 +601,10 @@ layout("/layouts/platform_h5.html"){
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<slot></slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</van-popup>
|
||||
`,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
data() {
|
||||
@@ -274,13 +617,15 @@ layout("/layouts/platform_h5.html"){
|
||||
allowFamily: false,
|
||||
fillBedInfo: true,
|
||||
directFamilyUnitLine: false,
|
||||
doneTasks: []
|
||||
doneTasks: [],
|
||||
popupHistoryToken: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.visible = true
|
||||
this.$set(this, "visible", true)
|
||||
window.h5PopupHistory.open(this.popupHistoryToken, "detail")
|
||||
this.detail = {}
|
||||
this.familyData = []
|
||||
this.directRelative = {}
|
||||
@@ -292,7 +637,9 @@ layout("/layouts/platform_h5.html"){
|
||||
this.getDoneTasks()
|
||||
},
|
||||
onClose() {
|
||||
this.visible = false
|
||||
if (!window.h5PopupHistory.close(this.popupHistoryToken, "detail")) {
|
||||
this.$set(this, "visible", false)
|
||||
}
|
||||
},
|
||||
info() {
|
||||
this.$axios.post("/platform/tour/unionApproval/detail", { id: this.row.id }).then((res) => {
|
||||
@@ -335,6 +682,15 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
return this.hasFamily() ? "是" : "否"
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$set(this, "popupHistoryToken", window.h5PopupHistory.register(() => {
|
||||
this.$set(this, "visible", false)
|
||||
this.$emit("closed")
|
||||
}))
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.h5PopupHistory.unregister(this.popupHistoryToken)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +720,9 @@ layout("/layouts/platform_h5.html"){
|
||||
{ text: "全部线路类型", value: "" }
|
||||
],
|
||||
formData: {},
|
||||
showApprovalForm: false
|
||||
showApprovalForm: false,
|
||||
pageSkeletonLoading: true,
|
||||
filterOpened: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -372,12 +730,24 @@ layout("/layouts/platform_h5.html"){
|
||||
onReady() {
|
||||
this.doSearch()
|
||||
},
|
||||
onTableLoading(state) {
|
||||
if (state && state.initial) {
|
||||
this.$set(this, "pageSkeletonLoading", !!state.loading)
|
||||
}
|
||||
},
|
||||
onFilterOpen() {
|
||||
this.$set(this, "filterOpened", true)
|
||||
},
|
||||
onFilterClose() {
|
||||
this.$set(this, "filterOpened", false)
|
||||
},
|
||||
doSearch() {
|
||||
this.$nextTick(async () => {
|
||||
await this.loadLineTypeOptions()
|
||||
this.$nextTick(() => {
|
||||
this.loadLineTypeOptions().then(() => {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageForm.totalCount = 0
|
||||
this.$refs.tableListRef.doSearch()
|
||||
})
|
||||
})
|
||||
},
|
||||
loadLineTypeOptions() {
|
||||
@@ -410,16 +780,12 @@ layout("/layouts/platform_h5.html"){
|
||||
}
|
||||
this.$refs.infoRef.onOpen(row)
|
||||
},
|
||||
async handleTaskAction(val) {
|
||||
try {
|
||||
await this.$refs.formRef.validate()
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
this.$dialog.confirm({
|
||||
handleTaskAction(val) {
|
||||
this.$refs.formRef.validate().then(() => {
|
||||
this.$dialog.confirm({
|
||||
title: "提示",
|
||||
message: "您确定要提交吗?"
|
||||
}).then(() => {
|
||||
}).then(() => {
|
||||
const loading = this.$toast.loading({
|
||||
message: "加载中...",
|
||||
forbidClick: true,
|
||||
@@ -442,6 +808,7 @@ layout("/layouts/platform_h5.html"){
|
||||
}).finally(() => {
|
||||
loading.close()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user