From 66034da0c5ac12eaaced6a2844905ceb5c047db8 Mon Sep 17 00:00:00 2001 From: wuzhen <52326163@qq.com> Date: Tue, 19 Aug 2025 15:50:09 +0800 Subject: [PATCH] wuzhen update --- .../ZsjyEnrollmentInfoController.java | 39 +- .../zsjy/controller/ZsjyQrCodeController.java | 161 +++++++++ .../org/dromara/zsjy/domain/ZsjyQrCode.java | 79 +++++ .../dromara/zsjy/domain/bo/ZsjyQrCodeBo.java | 85 +++++ .../dromara/zsjy/domain/vo/ZsjyQrCodeVo.java | 91 +++++ .../dromara/zsjy/mapper/ZsjyQrCodeMapper.java | 54 +++ .../zsjy/service/IZsjyQrCodeService.java | 100 ++++++ .../service/impl/ZsjyQrCodeServiceImpl.java | 242 +++++++++++++ .../resources/mapper/ZsjyQrCodeMapper.xml | 110 ++++++ mobile/src/common/dict.js | 10 +- mobile/src/common/request.js | 16 +- mobile/src/pages.json | 7 + web/package.json | 2 + web/src/api/zsjy/qrcode.ts | 278 +++++++++++++++ web/src/views/zsjy/enrollment/apply.vue | 98 +++++- web/src/views/zsjy/enrollment/index.vue | 26 +- web/src/views/zsjy/qrcode/index.vue | 332 ++++++++++++++++++ 17 files changed, 1691 insertions(+), 39 deletions(-) create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyQrCodeController.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyQrCode.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyQrCodeBo.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyQrCodeVo.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/ZsjyQrCodeMapper.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IZsjyQrCodeService.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyQrCodeServiceImpl.java create mode 100644 backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyQrCodeMapper.xml create mode 100644 web/src/api/zsjy/qrcode.ts create mode 100644 web/src/views/zsjy/qrcode/index.vue diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyEnrollmentInfoController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyEnrollmentInfoController.java index d62d197d..e50df20d 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyEnrollmentInfoController.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyEnrollmentInfoController.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaIgnore; import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import org.dromara.common.idempotent.annotation.RepeatSubmit; @@ -22,6 +23,8 @@ import org.dromara.zsjy.domain.vo.ZsjyEnrollmentInfoVo; import org.dromara.zsjy.domain.bo.ZsjyEnrollmentInfoBo; import org.dromara.zsjy.service.IZsjyEnrollmentInfoService; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.xg.service.IXgSysDeptService; +import org.dromara.xg.domain.vo.XgSysDeptVo; /** * 招生报名信息Controller @@ -36,6 +39,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; public class ZsjyEnrollmentInfoController extends BaseController { private final IZsjyEnrollmentInfoService enrollmentInfoService; + private final IXgSysDeptService xgSysDeptService; /** * 查询招生报名信息列表 @@ -101,6 +105,7 @@ public class ZsjyEnrollmentInfoController extends BaseController { /** * 根据身份证号和准考证号查询报名信息 */ + @SaIgnore @GetMapping("/query") public R queryByIdCardAndExamNumber( @RequestParam(required = false) String idCard, @@ -112,7 +117,7 @@ public class ZsjyEnrollmentInfoController extends BaseController { /** * 提交报名信息(供学生端使用) */ - @SaCheckPermission("zsjy:mobile:enrollment:apply") + @SaIgnore @Log(title = "学生报名", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping("/submit") @@ -123,7 +128,7 @@ public class ZsjyEnrollmentInfoController extends BaseController { /** * 查询我的报名状态(供学生端使用) */ - @SaCheckPermission("zsjy:mobile:enrollment:status") + @SaIgnore @GetMapping("/myStatus") public R getMyEnrollmentStatus( @RequestParam String idCard, @@ -153,6 +158,36 @@ public class ZsjyEnrollmentInfoController extends BaseController { return R.fail("请提供要更新的报名信息ID"); } } + + /** + * 获取学院列表(供移动端公开访问) + */ + @SaIgnore + @GetMapping("/colleges") + public R> getColleges() { + try { + // 调用学院部门服务获取学院列表 + List colleges = xgSysDeptService.selectCollegeList(); + return R.ok(colleges); + } catch (Exception e) { + return R.fail("获取学院列表异常: " + e.getMessage()); + } + } + + /** + * 根据学院ID获取专业列表(供移动端公开访问) + */ + @SaIgnore + @GetMapping("/majors/{collegeId}") + public R> getMajorsByCollegeId(@PathVariable Long collegeId) { + try { + // 调用学院部门服务获取专业列表 + List majors = xgSysDeptService.selectMajorListByCollegeId(collegeId); + return R.ok(majors); + } catch (Exception e) { + return R.fail("获取专业列表异常: " + e.getMessage()); + } + } } /** diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyQrCodeController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyQrCodeController.java new file mode 100644 index 00000000..228948b4 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyQrCodeController.java @@ -0,0 +1,161 @@ +package org.dromara.zsjy.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.zsjy.domain.bo.ZsjyQrCodeBo; +import org.dromara.zsjy.domain.vo.ZsjyQrCodeVo; +import org.dromara.zsjy.service.IZsjyQrCodeService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; + +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; + +/** + * 二维码管理Controller + * + * @author Cursor AI + * @date 2025-01-27 + */ +@Slf4j +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/zsjy/qrcode") +@Tag(name = "二维码管理", description = "招生二维码管理功能") +public class ZsjyQrCodeController extends BaseController { + + private final IZsjyQrCodeService qrCodeService; + + /** + * 查询二维码信息列表 + */ + @Operation(summary = "查询二维码列表", description = "分页查询二维码信息列表") + @SaCheckPermission("zsjy:qrcode:list") + @GetMapping("/list") + public TableDataInfo list(@Validated ZsjyQrCodeBo bo, PageQuery pageQuery) { + return qrCodeService.queryPageList(bo, pageQuery); + } + + /** + * 导出二维码信息列表 + */ + @Operation(summary = "导出二维码列表", description = "导出二维码信息到Excel") + @SaCheckPermission("zsjy:qrcode:export") + @Log(title = "二维码管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(@Validated ZsjyQrCodeBo bo, HttpServletResponse response) { + List list = qrCodeService.queryList(bo); + ExcelUtil.exportExcel(list, "二维码信息", ZsjyQrCodeVo.class, response); + } + + /** + * 获取二维码信息详细信息 + */ + @Operation(summary = "获取二维码详情", description = "根据ID获取二维码详细信息") + @SaCheckPermission("zsjy:qrcode:query") + @GetMapping("/{id}") + public R getInfo( + @Parameter(description = "二维码ID", required = true) + @PathVariable @NotNull(message = "主键不能为空") Long id) { + return R.ok(qrCodeService.queryById(id)); + } + + /** + * 新增二维码信息 + */ + @Operation(summary = "新增二维码", description = "创建新的二维码") + @SaCheckPermission("zsjy:qrcode:add") + @Log(title = "二维码管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody ZsjyQrCodeBo bo) { + return toAjax(qrCodeService.insertByBo(bo)); + } + + /** + * 修改二维码信息 + */ + @Operation(summary = "修改二维码", description = "修改二维码信息") + @SaCheckPermission("zsjy:qrcode:edit") + @Log(title = "二维码管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody ZsjyQrCodeBo bo) { + return toAjax(qrCodeService.updateByBo(bo)); + } + + /** + * 删除二维码信息 + */ + @Operation(summary = "删除二维码", description = "批量删除二维码信息") + @SaCheckPermission("zsjy:qrcode:remove") + @Log(title = "二维码管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove( + @Parameter(description = "二维码ID数组", required = true) + @PathVariable @NotEmpty(message = "主键不能为空") Long[] ids) { + return toAjax(qrCodeService.deleteWithValidByIds(Arrays.asList(ids), true)); + } + + /** + * 验证二维码Token有效性 + */ + @Operation(summary = "验证Token", description = "验证二维码访问令牌是否有效") + @GetMapping("/validate/{token}") + public R validateToken( + @Parameter(description = "访问令牌", required = true) + @PathVariable String token) { + return R.ok(qrCodeService.validateToken(token)); + } + + /** + * 根据Token获取二维码信息 + */ + @Operation(summary = "根据Token获取二维码", description = "通过访问令牌获取二维码信息") + @GetMapping("/token/{token}") + public R getByToken( + @Parameter(description = "访问令牌", required = true) + @PathVariable String token) { + return R.ok(qrCodeService.queryByAccessToken(token)); + } + + /** + * 增加二维码使用次数 + */ + @Operation(summary = "增加使用次数", description = "增加二维码使用次数") + @PostMapping("/increment/{id}") + public R incrementUsage( + @Parameter(description = "二维码ID", required = true) + @PathVariable @NotNull(message = "主键不能为空") Long id) { + return toAjax(qrCodeService.incrementUsage(id)); + } + + /** + * 生成新的访问令牌 + */ + @Operation(summary = "生成Token", description = "生成新的访问令牌") + @SaCheckPermission("zsjy:qrcode:token") + @PostMapping("/generate-token") + public R generateToken() { + return R.ok(qrCodeService.generateAccessToken()); + } + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyQrCode.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyQrCode.java new file mode 100644 index 00000000..f11f75c9 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyQrCode.java @@ -0,0 +1,79 @@ +package org.dromara.zsjy.domain; + +import org.dromara.common.tenant.core.TenantEntity; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.util.Date; + +/** + * 二维码管理对象 zsjy_qr_code + * + * @author Cursor AI + * @date 2025-01-27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("zsjy_qr_code") +public class ZsjyQrCode extends TenantEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId(value = "id") + private Long id; + + /** + * 二维码名称 + */ + private String codeName; + + /** + * 二维码类型(1-招生报名) + */ + private Integer codeType; + + /** + * 二维码内容(URL) + */ + private String qrContent; + + /** + * 访问令牌 + */ + private String accessToken; + + /** + * 过期时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date expireTime; + + /** + * 最大使用次数(0-无限制) + */ + private Integer maxUsage; + + /** + * 当前使用次数 + */ + private Integer currentUsage; + + /** + * 状态(0-禁用 1-启用) + */ + private Integer status; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic + private Integer deleted; + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyQrCodeBo.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyQrCodeBo.java new file mode 100644 index 00000000..ef5e0436 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyQrCodeBo.java @@ -0,0 +1,85 @@ +package org.dromara.zsjy.domain.bo; + +import org.dromara.zsjy.domain.ZsjyQrCode; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import jakarta.validation.constraints.*; +import java.util.Date; + +/** + * 二维码管理业务对象 zsjy_qr_code + * + * @author Cursor AI + * @date 2025-01-27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = ZsjyQrCode.class, reverseConvertGenerate = false) +public class ZsjyQrCodeBo extends BaseEntity { + + /** + * 主键ID + */ + private Long id; + + /** + * 二维码名称 + */ + @NotBlank(message = "二维码名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(max = 100, message = "二维码名称长度不能超过100个字符", groups = { AddGroup.class, EditGroup.class }) + private String codeName; + + /** + * 二维码类型(1-招生报名) + */ + @NotNull(message = "二维码类型不能为空", groups = { AddGroup.class, EditGroup.class }) + private Integer codeType; + + /** + * 二维码内容(URL) + */ + @NotBlank(message = "二维码内容不能为空", groups = { AddGroup.class, EditGroup.class }) + private String qrContent; + + /** + * 访问令牌 + */ + @NotBlank(message = "访问令牌不能为空", groups = { AddGroup.class, EditGroup.class }) + @Size(max = 255, message = "访问令牌长度不能超过255个字符", groups = { AddGroup.class, EditGroup.class }) + private String accessToken; + + /** + * 过期时间 + */ + private Date expireTime; + + /** + * 最大使用次数(0-无限制) + */ + @NotNull(message = "最大使用次数不能为空", groups = { AddGroup.class, EditGroup.class }) + @Min(value = 0, message = "最大使用次数不能小于0", groups = { AddGroup.class, EditGroup.class }) + private Integer maxUsage; + + /** + * 当前使用次数 + */ + private Integer currentUsage; + + /** + * 状态(0-禁用 1-启用) + */ + @NotNull(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class }) + private Integer status; + + // VO类基础字段(强制性规范) + private Long createBy; + private Date createTime; + private Long updateBy; + private Date updateTime; + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyQrCodeVo.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyQrCodeVo.java new file mode 100644 index 00000000..702fc6c5 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/vo/ZsjyQrCodeVo.java @@ -0,0 +1,91 @@ +package org.dromara.zsjy.domain.vo; + +import org.dromara.zsjy.domain.ZsjyQrCode; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 二维码管理视图对象 zsjy_qr_code + * + * @author Cursor AI + * @date 2025-01-27 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = ZsjyQrCode.class) +public class ZsjyQrCodeVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ExcelProperty(value = "主键ID") + private Long id; + + /** + * 二维码名称 + */ + @ExcelProperty(value = "二维码名称") + private String codeName; + + /** + * 二维码类型(1-招生报名) + */ + @ExcelProperty(value = "二维码类型") + private Integer codeType; + + /** + * 二维码内容(URL) + */ + @ExcelProperty(value = "二维码内容") + private String qrContent; + + /** + * 访问令牌 + */ + @ExcelProperty(value = "访问令牌") + private String accessToken; + + /** + * 过期时间 + */ + @ExcelProperty(value = "过期时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date expireTime; + + /** + * 最大使用次数(0-无限制) + */ + @ExcelProperty(value = "最大使用次数") + private Integer maxUsage; + + /** + * 当前使用次数 + */ + @ExcelProperty(value = "当前使用次数") + private Integer currentUsage; + + /** + * 状态(0-禁用 1-启用) + */ + @ExcelProperty(value = "状态") + private Integer status; + + // VO类基础字段(强制性规范) + private Long createBy; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + private Long updateBy; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/ZsjyQrCodeMapper.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/ZsjyQrCodeMapper.java new file mode 100644 index 00000000..ea02f65e --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/ZsjyQrCodeMapper.java @@ -0,0 +1,54 @@ +package org.dromara.zsjy.mapper; + +import org.dromara.zsjy.domain.ZsjyQrCode; +import org.dromara.zsjy.domain.vo.ZsjyQrCodeVo; +import org.dromara.zsjy.domain.bo.ZsjyQrCodeBo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 二维码管理 Mapper 接口 + * + * @author Cursor AI + * @date 2025-01-27 + */ +public interface ZsjyQrCodeMapper extends BaseMapperPlus { + + /** + * 分页查询二维码列表 + * + * @param page 分页参数 + * @param bo 查询条件 + * @return 二维码列表 + */ + IPage selectQrCodePageList(@Param("page") Page page, @Param("bo") ZsjyQrCodeBo bo); + + /** + * 查询二维码列表(非分页) + * + * @param bo 查询条件 + * @return 二维码列表 + */ + List selectQrCodeVoList(ZsjyQrCodeBo bo); + + /** + * 根据访问令牌查询二维码信息 + * + * @param accessToken 访问令牌 + * @return 二维码信息 + */ + ZsjyQrCodeVo selectByAccessToken(String accessToken); + + /** + * 更新二维码使用次数 + * + * @param id 二维码ID + * @return 更新结果 + */ + int updateUsageCount(@Param("id") Long id); + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IZsjyQrCodeService.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IZsjyQrCodeService.java new file mode 100644 index 00000000..8f820ab5 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IZsjyQrCodeService.java @@ -0,0 +1,100 @@ +package org.dromara.zsjy.service; + +import org.dromara.zsjy.domain.bo.ZsjyQrCodeBo; +import org.dromara.zsjy.domain.vo.ZsjyQrCodeVo; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +import java.util.Collection; +import java.util.List; + +/** + * 二维码管理Service接口 + * + * @author Cursor AI + * @date 2025-01-27 + */ +public interface IZsjyQrCodeService { + + /** + * 查询二维码信息 + * + * @param id 二维码信息主键 + * @return 二维码信息 + */ + ZsjyQrCodeVo queryById(Long id); + + /** + * 查询二维码信息列表 + * + * @param bo 二维码信息 + * @param pageQuery 分页参数 + * @return 二维码信息集合 + */ + TableDataInfo queryPageList(ZsjyQrCodeBo bo, PageQuery pageQuery); + + /** + * 查询二维码信息列表 + * + * @param bo 二维码信息 + * @return 二维码信息集合 + */ + List queryList(ZsjyQrCodeBo bo); + + /** + * 新增二维码信息 + * + * @param bo 二维码信息 + * @return 结果 + */ + Boolean insertByBo(ZsjyQrCodeBo bo); + + /** + * 修改二维码信息 + * + * @param bo 二维码信息 + * @return 结果 + */ + Boolean updateByBo(ZsjyQrCodeBo bo); + + /** + * 校验并批量删除二维码信息 + * + * @param ids 需要删除的二维码信息主键集合 + * @param isValid 是否校验,true-删除前校验,false-不校验 + * @return 结果 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 根据访问令牌查询二维码信息 + * + * @param accessToken 访问令牌 + * @return 二维码信息 + */ + ZsjyQrCodeVo queryByAccessToken(String accessToken); + + /** + * 验证二维码Token有效性 + * + * @param accessToken 访问令牌 + * @return 是否有效 + */ + Boolean validateToken(String accessToken); + + /** + * 增加二维码使用次数 + * + * @param id 二维码ID + * @return 结果 + */ + Boolean incrementUsage(Long id); + + /** + * 生成唯一的访问令牌 + * + * @return 访问令牌 + */ + String generateAccessToken(); + +} diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyQrCodeServiceImpl.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyQrCodeServiceImpl.java new file mode 100644 index 00000000..458df0cf --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyQrCodeServiceImpl.java @@ -0,0 +1,242 @@ +package org.dromara.zsjy.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.zsjy.domain.ZsjyQrCode; +import org.dromara.zsjy.domain.bo.ZsjyQrCodeBo; +import org.dromara.zsjy.domain.vo.ZsjyQrCodeVo; +import org.dromara.zsjy.mapper.ZsjyQrCodeMapper; +import org.dromara.zsjy.service.IZsjyQrCodeService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.Date; +import java.util.List; + +/** + * 二维码管理Service业务层处理 + * + * @author Cursor AI + * @date 2025-01-27 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class ZsjyQrCodeServiceImpl implements IZsjyQrCodeService { + + private final ZsjyQrCodeMapper baseMapper; + + /** + * 查询二维码信息 + */ + @Override + public ZsjyQrCodeVo queryById(Long id) { + return baseMapper.selectVoById(id); + } + + /** + * 分页查询二维码信息列表 + */ + @Override + public TableDataInfo queryPageList(ZsjyQrCodeBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询二维码信息列表 + */ + @Override + public List queryList(ZsjyQrCodeBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(ZsjyQrCodeBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.like(StringUtils.isNotBlank(bo.getCodeName()), ZsjyQrCode::getCodeName, bo.getCodeName()); + lqw.eq(ObjectUtil.isNotNull(bo.getCodeType()), ZsjyQrCode::getCodeType, bo.getCodeType()); + lqw.like(StringUtils.isNotBlank(bo.getQrContent()), ZsjyQrCode::getQrContent, bo.getQrContent()); + lqw.eq(StringUtils.isNotBlank(bo.getAccessToken()), ZsjyQrCode::getAccessToken, bo.getAccessToken()); + lqw.eq(ObjectUtil.isNotNull(bo.getExpireTime()), ZsjyQrCode::getExpireTime, bo.getExpireTime()); + lqw.eq(ObjectUtil.isNotNull(bo.getMaxUsage()), ZsjyQrCode::getMaxUsage, bo.getMaxUsage()); + lqw.eq(ObjectUtil.isNotNull(bo.getCurrentUsage()), ZsjyQrCode::getCurrentUsage, bo.getCurrentUsage()); + lqw.eq(ObjectUtil.isNotNull(bo.getStatus()), ZsjyQrCode::getStatus, bo.getStatus()); + return lqw; + } + + /** + * 新增二维码信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(ZsjyQrCodeBo bo) { + ZsjyQrCode add = BeanUtil.toBean(bo, ZsjyQrCode.class); + validEntityBeforeSave(add); + + // 如果没有提供访问令牌,则自动生成 + if (StrUtil.isBlank(add.getAccessToken())) { + add.setAccessToken(generateAccessToken()); + } + + // 初始化当前使用次数 + if (add.getCurrentUsage() == null) { + add.setCurrentUsage(0); + } + + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改二维码信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(ZsjyQrCodeBo bo) { + ZsjyQrCode update = BeanUtil.toBean(bo, ZsjyQrCode.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(ZsjyQrCode entity) { + // 校验二维码名称唯一性 + if (StringUtils.isNotBlank(entity.getCodeName())) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(ZsjyQrCode::getCodeName, entity.getCodeName()); + if (entity.getId() != null) { + lqw.ne(ZsjyQrCode::getId, entity.getId()); + } + boolean exists = baseMapper.exists(lqw); + if (exists) { + throw new RuntimeException("二维码名称已存在"); + } + } + + // 校验访问令牌唯一性 + if (StringUtils.isNotBlank(entity.getAccessToken())) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(ZsjyQrCode::getAccessToken, entity.getAccessToken()); + if (entity.getId() != null) { + lqw.ne(ZsjyQrCode::getId, entity.getId()); + } + boolean exists = baseMapper.exists(lqw); + if (exists) { + throw new RuntimeException("访问令牌已存在"); + } + } + } + + /** + * 批量删除二维码信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + // 删除前校验逻辑(如果需要的话) + } + return baseMapper.deleteBatchIds(ids) > 0; + } + + /** + * 根据访问令牌查询二维码信息 + */ + @Override + public ZsjyQrCodeVo queryByAccessToken(String accessToken) { + if (StrUtil.isBlank(accessToken)) { + return null; + } + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(ZsjyQrCode::getAccessToken, accessToken); + return baseMapper.selectVoOne(lqw); + } + + /** + * 验证二维码Token有效性 + */ + @Override + public Boolean validateToken(String accessToken) { + ZsjyQrCodeVo qrCode = queryByAccessToken(accessToken); + if (qrCode == null) { + return false; + } + + // 检查状态 + if (qrCode.getStatus() == null || qrCode.getStatus() != 1) { + return false; + } + + // 检查过期时间 + if (qrCode.getExpireTime() != null && qrCode.getExpireTime().before(new Date())) { + return false; + } + + // 检查使用次数限制 + if (qrCode.getMaxUsage() != null && qrCode.getMaxUsage() > 0) { + if (qrCode.getCurrentUsage() != null && qrCode.getCurrentUsage() >= qrCode.getMaxUsage()) { + return false; + } + } + + return true; + } + + /** + * 增加二维码使用次数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean incrementUsage(Long id) { + return baseMapper.updateUsageCount(id) > 0; + } + + /** + * 生成唯一的访问令牌 + */ + @Override + public String generateAccessToken() { + String token; + int maxAttempts = 10; + int attempts = 0; + + do { + token = "qr_" + IdUtil.fastSimpleUUID(); + attempts++; + + // 检查令牌是否已存在 + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(ZsjyQrCode::getAccessToken, token); + boolean exists = baseMapper.exists(lqw); + + if (!exists) { + return token; + } + + } while (attempts < maxAttempts); + + throw new RuntimeException("生成访问令牌失败,请重试"); + } + +} + \ No newline at end of file diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyQrCodeMapper.xml b/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyQrCodeMapper.xml new file mode 100644 index 00000000..5a1135a0 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyQrCodeMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + select id, code_name, code_type, qr_content, access_token, expire_time, + max_usage, current_usage, status, create_by, create_time, + update_by, update_time + from zsjy_qr_code + + + + + + + + + + + + + + UPDATE zsjy_qr_code + SET current_usage = IFNULL(current_usage, 0) + 1, + update_time = NOW() + WHERE id = #{id} AND deleted = 0 + + + diff --git a/mobile/src/common/dict.js b/mobile/src/common/dict.js index 27822eb8..47db8253 100644 --- a/mobile/src/common/dict.js +++ b/mobile/src/common/dict.js @@ -1,5 +1,5 @@ // 移动端字典数据获取公共方法 - 适配Vue 2.6.14 + uni-app 2.x -import { get } from './request.js'; +import { request } from './request.js'; /** * 字典数据缓存管理 @@ -76,8 +76,12 @@ const dictCache = { * @returns {Promise} 字典数据Promise */ export const getDicts = (dictType) => { - return get(`/system/dict/data/type/${dictType}`, null, { - isToken: false, // 字典数据不需要token认证 + return request({ + url: `/system/dict/data/type/${dictType}`, + method: 'GET', + header: { + isToken: false // 字典数据不需要token认证 + } }); }; diff --git a/mobile/src/common/request.js b/mobile/src/common/request.js index bf2fe5c5..d5da71be 100644 --- a/mobile/src/common/request.js +++ b/mobile/src/common/request.js @@ -34,6 +34,17 @@ function getToken() { function handleUnauthorized(message = '登录已失效,请重新登录') { console.log('🔒 处理401未授权响应:', message); + // 获取当前页面路径 + const pages = getCurrentPages(); + const currentPage = pages[pages.length - 1]; + const currentPath = '/' + currentPage.route; + + // 如果是新生报名页面,不跳转到登录页,只是静默处理 + if (currentPath === '/pages/enrollment/index') { + console.log('📋 新生报名页面401错误,使用兜底数据,不跳转登录页'); + return; + } + // 清除登录信息 try { uni.removeStorageSync('access_token'); @@ -53,11 +64,6 @@ function handleUnauthorized(message = '登录已失效,请重新登录') { // 延迟跳转,确保Toast显示 setTimeout(() => { - // 获取当前页面路径 - const pages = getCurrentPages(); - const currentPage = pages[pages.length - 1]; - const currentPath = '/' + currentPage.route; - // 如果当前不是登录页,则跳转到登录页 if (currentPath !== '/pages/login/index') { console.log('🔄 从', currentPath, '跳转到登录页'); diff --git a/mobile/src/pages.json b/mobile/src/pages.json index 326201a8..731fcf5e 100644 --- a/mobile/src/pages.json +++ b/mobile/src/pages.json @@ -215,6 +215,13 @@ "navigationBarBackgroundColor": "#0051d9", "navigationBarTextStyle": "white" } + }, + { + "path": "pages/enrollment/index", + "style": { + "navigationBarTitleText": "新生报名登记", + "navigationStyle": "custom" + } } ], "globalStyle": { diff --git a/web/package.json b/web/package.json index fb07e9aa..68f51ada 100644 --- a/web/package.json +++ b/web/package.json @@ -27,6 +27,7 @@ "@fullcalendar/timegrid": "^6.1.18", "@fullcalendar/vue3": "^6.1.18", "@highlightjs/vue-plugin": "2.1.0", + "@types/qrcode": "^1.5.5", "@vueup/vue-quill": "1.2.0", "@vueuse/core": "13.1.0", "animate.css": "4.1.1", @@ -45,6 +46,7 @@ "jspdf-font": "^1.0.7", "nprogress": "0.2.0", "pinia": "3.0.2", + "qrcode": "^1.5.4", "screenfull": "6.0.2", "vue": "3.5.13", "vue-cropper": "1.1.1", diff --git a/web/src/api/zsjy/qrcode.ts b/web/src/api/zsjy/qrcode.ts new file mode 100644 index 00000000..9ebe9113 --- /dev/null +++ b/web/src/api/zsjy/qrcode.ts @@ -0,0 +1,278 @@ +import request from '@/utils/request' + +/** + * 二维码管理 VO + */ +export interface QrCodeVO { + /** + * 主键ID + */ + id?: string | number; + + /** + * 二维码名称 + */ + codeName?: string; + + /** + * 二维码类型(1-招生报名) + */ + codeType?: number; + + /** + * 二维码内容(URL) + */ + qrContent?: string; + + /** + * 访问令牌 + */ + accessToken?: string; + + /** + * 过期时间 + */ + expireTime?: string; + + /** + * 最大使用次数(0-无限制) + */ + maxUsage?: number; + + /** + * 当前使用次数 + */ + currentUsage?: number; + + /** + * 状态(0-禁用 1-启用) + */ + status?: number; + + /** + * 创建人 + */ + createBy?: string | number; + + /** + * 创建时间 + */ + createTime?: string; + + /** + * 更新人 + */ + updateBy?: string | number; + + /** + * 更新时间 + */ + updateTime?: string; +} + +/** + * 二维码管理 BO + */ +export interface QrCodeBO { + /** + * 主键ID + */ + id?: string | number; + + /** + * 二维码名称 + */ + codeName?: string; + + /** + * 二维码类型(1-招生报名) + */ + codeType?: number; + + /** + * 二维码内容(URL) + */ + qrContent?: string; + + /** + * 访问令牌 + */ + accessToken?: string; + + /** + * 过期时间 + */ + expireTime?: string; + + /** + * 最大使用次数(0-无限制) + */ + maxUsage?: number; + + /** + * 当前使用次数 + */ + currentUsage?: number; + + /** + * 状态(0-禁用 1-启用) + */ + status?: number; +} + +/** + * 二维码查询参数 + */ +export interface QrCodeQuery { + /** + * 二维码名称 + */ + codeName?: string; + + /** + * 二维码类型 + */ + codeType?: number; + + /** + * 状态 + */ + status?: number; + + /** + * 创建时间范围 + */ + params?: { + beginTime?: string; + endTime?: string; + }; +} + +/** + * 查询二维码列表 + */ +export function listQrCode(query?: QrCodeQuery) { + return request({ + url: '/zsjy/qrcode/list', + method: 'get', + params: query + }) +} + +/** + * 查询二维码详细 + */ +export function getQrCode(id: string | number) { + return request({ + url: '/zsjy/qrcode/' + id, + method: 'get' + }) +} + +/** + * 新增二维码 + */ +export function addQrCode(data: QrCodeBO) { + return request({ + url: '/zsjy/qrcode', + method: 'post', + data: data + }) +} + +/** + * 修改二维码 + */ +export function updateQrCode(data: QrCodeBO) { + return request({ + url: '/zsjy/qrcode', + method: 'put', + data: data + }) +} + +/** + * 删除二维码 + */ +export function delQrCode(ids: string | number | Array) { + return request({ + url: '/zsjy/qrcode/' + ids, + method: 'delete' + }) +} + +/** + * 导出二维码 + */ +export function exportQrCode(query?: QrCodeQuery) { + return request({ + url: '/zsjy/qrcode/export', + method: 'post', + data: query, + responseType: 'blob' + }) +} + +/** + * 验证二维码Token有效性 + */ +export function validateToken(token: string) { + return request({ + url: '/zsjy/qrcode/validate/' + token, + method: 'get' + }) +} + +/** + * 根据Token获取二维码信息 + */ +export function getQrCodeByToken(token: string) { + return request({ + url: '/zsjy/qrcode/token/' + token, + method: 'get' + }) +} + +/** + * 增加二维码使用次数 + */ +export function incrementUsage(id: string | number) { + return request({ + url: '/zsjy/qrcode/increment/' + id, + method: 'post' + }) +} + +/** + * 生成新的访问令牌 + */ +export function generateToken() { + return request({ + url: '/zsjy/qrcode/generate-token', + method: 'post' + }) +} + +/** + * 二维码类型选项 + */ +export const qrCodeTypeOptions = [ + { + label: '招生报名', + value: 1 + } +] + +/** + * 状态选项 + */ +export const statusOptions = [ + { + label: '禁用', + value: 0 + }, + { + label: '启用', + value: 1 + } +] diff --git a/web/src/views/zsjy/enrollment/apply.vue b/web/src/views/zsjy/enrollment/apply.vue index a6f5890b..b1925348 100644 --- a/web/src/views/zsjy/enrollment/apply.vue +++ b/web/src/views/zsjy/enrollment/apply.vue @@ -159,6 +159,20 @@ 报考信息 + + + + + + + + + + + + + + @@ -271,17 +285,20 @@ import { reactive, ref, toRefs, getCurrentInstance, ComponentInternalInstance, onMounted, nextTick } from 'vue'; import { ElForm } from 'element-plus'; import { submitEnrollmentApplication, queryMyEnrollmentStatus } from '@/api/zsjy/enrollment'; -import { EnrollmentInfoForm } from '@/api/zsjy/enrollment/types'; +import type { EnrollmentInfoForm } from '@/api/zsjy/enrollment/types'; +import { listColleges, listMajorsByCollegeId } from '@/api/xg/xsjcxx/classMsg/college'; import { User, School, Star, Document, Check, Refresh } from '@element-plus/icons-vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { zsjy_gender, sys_yes_no, zsjy_major, zsjy_uniform_size } = toRefs( - proxy?.useDict('zsjy_gender', 'sys_yes_no', 'zsjy_major', 'zsjy_uniform_size') + (proxy as any)?.useDict('zsjy_gender', 'sys_yes_no', 'zsjy_major', 'zsjy_uniform_size') ); const applyFormRef = ref>(); const submitLoading = ref(false); const queryLoading = ref(false); +const collegeOptions = ref>([]); +const collegeSelectValue = ref(undefined); const majorOptions = ref>([]); const statusDialog = reactive({ @@ -311,6 +328,8 @@ const applyForm = reactive({ scienceScore: undefined, socialScore: undefined, peScore: undefined, + collegeName: undefined, + collegeId: undefined, appliedMajor: undefined, majorCode: undefined, uniformSize: undefined, @@ -340,6 +359,7 @@ const rules = { { pattern: /^1[3-9]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' } ], phone2: [{ pattern: /^1[3-9]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' }], + collegeName: [{ required: true, message: '所属学院不能为空', trigger: 'change' }], appliedMajor: [{ required: true, message: '报考专业不能为空', trigger: 'change' }], totalScoreFull: [{ type: 'number', min: 100, max: 1000, message: '中考满分应在100-1000之间', trigger: 'blur' }], totalScore: [{ type: 'number', min: 0, message: '中考成绩不能小于0', trigger: 'blur' }], @@ -383,6 +403,55 @@ const onIdCardChange = () => { } }; +/** 学院选择变化处理 */ +const onCollegeChange = async (selectedCollegeId: number) => { + if (selectedCollegeId) { + // 根据选择的学院ID找到学院对象 + const college = collegeOptions.value.find((item) => item.deptId === selectedCollegeId); + if (college) { + // 设置学院信息 + applyForm.collegeId = college.deptCategory || college.deptId.toString(); + applyForm.collegeName = college.deptName; + + // 根据学院加载专业选项 + await loadMajorsByCollegeId(selectedCollegeId); + + // 清空专业选择 + applyForm.appliedMajor = undefined; + applyForm.majorCode = undefined; + + console.log('学院选择变化:', { + collegeId: applyForm.collegeId, + collegeName: applyForm.collegeName + }); + } + } else { + // 清空学院和专业相关字段 + applyForm.collegeName = undefined; + applyForm.collegeId = undefined; + applyForm.appliedMajor = undefined; + applyForm.majorCode = undefined; + majorOptions.value = []; + } +}; + +/** 根据学院ID加载专业 */ +const loadMajorsByCollegeId = async (collegeId: number) => { + try { + const response = await listMajorsByCollegeId(collegeId); + if (response.data) { + majorOptions.value = response.data.map((major: any) => ({ + value: major.deptId.toString(), + label: major.deptName, + majorCode: major.deptCategory || major.deptId.toString() + })); + } + } catch (error) { + console.error('加载专业数据失败:', error); + majorOptions.value = []; + } +}; + /** 专业选择变化处理 */ const onMajorChange = (selectedMajor: string) => { const major = majorOptions.value.find((item) => item.label === selectedMajor); @@ -448,10 +517,10 @@ const submitApplication = () => { } await submitEnrollmentApplication(applyForm); - proxy?.$modal.msgSuccess('报名申请提交成功!'); + (proxy as any)?.$modal.msgSuccess('报名申请提交成功!'); resetForm(); } catch (error) { - proxy?.$modal.msgError('提交失败,请稍后重试'); + (proxy as any)?.$modal.msgError('提交失败,请稍后重试'); } finally { submitLoading.value = false; } @@ -470,7 +539,7 @@ const resetForm = () => { /** 查询报名状态 */ const queryStatus = async () => { if (!queryForm.idCard && !queryForm.examNumber) { - proxy?.$modal.msgWarning('请输入身份证号或准考证号'); + (proxy as any)?.$modal.msgWarning('请输入身份证号或准考证号'); return; } @@ -485,16 +554,31 @@ const queryStatus = async () => { statusInfo.value = response.data; statusDialog.visible = true; } else { - proxy?.$modal.msgWarning('未找到相关报名信息'); + (proxy as any)?.$modal.msgWarning('未找到相关报名信息'); } } catch (error) { - proxy?.$modal.msgError('查询失败,请稍后重试'); + (proxy as any)?.$modal.msgError('查询失败,请稍后重试'); } finally { queryLoading.value = false; } }; +/** 获取学院选项 */ +const getCollegeOptions = async () => { + try { + const response = await listColleges(); + if (response.data) { + collegeOptions.value = response.data; + console.log('学院数据加载成功:', collegeOptions.value); + } + } catch (error) { + console.error('学院数据加载失败:', error); + collegeOptions.value = []; + } +}; + onMounted(() => { + getCollegeOptions(); getMajorOptions(); }); diff --git a/web/src/views/zsjy/enrollment/index.vue b/web/src/views/zsjy/enrollment/index.vue index b16d8f4a..7c9f18f1 100644 --- a/web/src/views/zsjy/enrollment/index.vue +++ b/web/src/views/zsjy/enrollment/index.vue @@ -365,15 +365,7 @@ - - - - - - - - - + @@ -1214,18 +1206,7 @@ const onSearchCollegeChange = (selectedCollegeId: string) => { // 专业选项由学院选择后动态生成 -// 校服尺码数据,全局常量 -const UNIFORM_SIZES = [ - { value: '150/84A', label: '150/84A(身高150cm)', height: '150cm' }, - { value: '155/86A', label: '155/86A(身高155cm)', height: '155cm' }, - { value: '160/88A', label: '160/88A(身高160cm)', height: '160cm' }, - { value: '165/90A', label: '165/90A(身高165cm)', height: '165cm' }, - { value: '170/92A', label: '170/92A(身高170cm)', height: '170cm' }, - { value: '175/94A', label: '175/94A(身高175cm)', height: '175cm' }, - { value: '180/96A', label: '180/96A(身高180cm)', height: '180cm' }, - { value: '185/98A', label: '185/98A(身高185cm)', height: '185cm' }, - { value: '190/100A', label: '190/100A(身高190cm)', height: '190cm' } -]; +// 校服尺码数据使用字典 zsjy_uniform_size /** 根据学院代码查找学院名称 */ const getCollegeName = (code: string | undefined) => { @@ -1281,7 +1262,8 @@ const getCollegeNameEnhanced = (student: any) => { /** 获取校服尺码显示名称 */ const getUniformSizeLabel = (value: string | undefined) => { if (!value) return '-'; - const size = UNIFORM_SIZES.find((item) => item.value === value); + // 使用字典数据查找校服尺码 + const size = zsjy_uniform_size.value?.find((item: any) => item.value === value); return size ? size.label : value; }; diff --git a/web/src/views/zsjy/qrcode/index.vue b/web/src/views/zsjy/qrcode/index.vue new file mode 100644 index 00000000..5e47fca0 --- /dev/null +++ b/web/src/views/zsjy/qrcode/index.vue @@ -0,0 +1,332 @@ + + + + +