From 9a16535359e51a1cd9777a8420d4a7c8c2c75c10 Mon Sep 17 00:00:00 2001 From: wuzhen <52326163@qq.com> Date: Thu, 14 Aug 2025 10:52:22 +0800 Subject: [PATCH] wuzhen update --- .../controller/InternshipInfoController.java | 32 ++++ .../ZsjyInternshipDailyController.java | 3 +- .../zsjy/domain/ZsjyInternshipDaily.java | 121 ++++++++++-- .../domain/bo/ZsjyInternshipDailyAddBo.java | 178 +++++++++++++++--- .../impl/ZsjyInternshipDailyServiceImpl.java | 74 ++++++-- mobile/src/pages.json | 8 + mobile/src/pages/index/index.vue | 24 ++- mobile/src/utils/permission.js | 26 +++ web/src/views/zsjy/internship/daily/index.vue | 6 +- 9 files changed, 408 insertions(+), 64 deletions(-) diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java index 48580eef..f1678340 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/InternshipInfoController.java @@ -5,6 +5,7 @@ import org.dromara.common.core.domain.R; 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.common.satoken.utils.LoginHelper; import org.dromara.zsjy.domain.vo.InternshipInfoVO; import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO; import org.dromara.zsjy.domain.bo.InternshipInfoAddBO; @@ -101,6 +102,37 @@ public class InternshipInfoController extends BaseController { return R.ok(internshipInfoService.getInternshipStatistics(queryBO)); } + /** + * 学生获取自己的实习信息(移动端专用) + */ + @Operation(summary = "学生获取实习信息", description = "学生查看自己的实习信息(移动端)") + @GetMapping("/student/info") + public R getStudentInfo() { + log.info("=== 学生获取实习信息 ==="); + log.info("当前用户ID: {}", LoginHelper.getUserId()); + + try { + Long currentUserId = LoginHelper.getUserId(); + if (currentUserId == null) { + log.error("用户ID为空,无法获取实习信息"); + return R.fail("用户未登录"); + } + + InternshipInfoVO result = internshipInfoService.queryById(currentUserId); + + if (result != null) { + log.info("成功获取学生实习信息,学生ID: {}", currentUserId); + return R.ok(result); + } else { + log.info("学生暂无实习信息,学生ID: {}", currentUserId); + return R.fail("暂无实习信息"); + } + } catch (Exception e) { + log.error("获取学生实习信息异常,用户ID: {},错误信息: {}", LoginHelper.getUserId(), e.getMessage(), e); + return R.fail("获取实习信息失败:" + e.getMessage()); + } + } + /** * 新增实习信息 */ diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java index 2c11b2fe..2c46276b 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java @@ -6,6 +6,7 @@ import org.dromara.common.core.validate.AddGroup; 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.CheckInGroup; import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyAddBo; import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyQueryBo; import org.dromara.zsjy.domain.vo.ZsjyInternshipDailyVo; @@ -58,7 +59,7 @@ public class ZsjyInternshipDailyController extends BaseController { @Operation(summary = "学生签到打卡", description = "学生进行实习日常签到打卡") @SaCheckPermission("zsjy:internshipdaily:checkin") @PostMapping("/checkin") - public R checkIn(@Validated(AddGroup.class) @RequestBody ZsjyInternshipDailyAddBo addBo) { + public R checkIn(@Validated(CheckInGroup.class) @RequestBody ZsjyInternshipDailyAddBo addBo) { log.info("=== Controller层调试 ==="); log.info("接口被调用: /zsjy/internship/daily/checkin"); log.info("签到参数: {}", addBo); diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java index 38a5c471..16e0229b 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyInternshipDaily.java @@ -1,5 +1,7 @@ package org.dromara.zsjy.domain; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -9,6 +11,8 @@ import org.dromara.common.mybatis.core.domain.BaseEntity; import java.io.Serial; import java.math.BigDecimal; import java.sql.Time; +import java.time.LocalDate; +import java.time.LocalTime; import java.util.Date; /** @@ -26,74 +30,161 @@ public class ZsjyInternshipDaily extends BaseEntity { private static final long serialVersionUID = 1L; /** - * 日常记录ID + * 日常记录ID (对应数据库daily_id字段) */ - @TableId(value = "daily_id") - private Long dailyId; + @TableId(value = "daily_id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 租户ID + */ + @TableField("tenant_id") + private String tenantId; /** * 实习ID */ + @TableField("internship_id") private Long internshipId; /** * 学生ID */ + @TableField("student_id") private Long studentId; /** - * 打卡日期 + * 签到日期 */ - private Date checkDate; + @TableField("check_date") + private LocalDate checkDate; /** * 签到时间 */ - private Time checkInTime; + @TableField("check_in_time") + private LocalTime checkInTime; /** - * 签到位置 + * 签到地点 (对应数据库check_in_location字段) */ - private String checkInLocation; + @TableField("check_in_location") + private String checkOutLocation; /** - * 纬度 + * 签到经度 (对应数据库longitude字段) */ - private BigDecimal latitude; + @TableField("longitude") + private BigDecimal checkOutLongitude; /** - * 经度 + * 签到纬度 (对应数据库latitude字段) */ - private BigDecimal longitude; + @TableField("latitude") + private BigDecimal checkOutLatitude; /** - * 日总结 + * 工作内容/日总结 */ - private String dailySummary; + @TableField("daily_summary") + private String workContent; /** * 图片附件(JSON格式) */ + @TableField("images") private String images; /** * 是否异常(0正常 1异常) */ + @TableField("is_exception") private String isException; /** * 异常原因 */ + @TableField("exception_reason") private String exceptionReason; /** * 异常处理状态(0待处理 1已处理) */ + @TableField("exception_status") private String exceptionStatus; /** - * 状态(0正常 1停用) + * 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工) */ + @TableField("status") private String status; + /** + * 备注 + */ + @TableField("remark") + private String remark; + + // ==================== 扩展字段(数据库中不存在,通过关联查询获取) ==================== + + /** + * 学生姓名 (通过student_id关联查询获取) + */ + @TableField(exist = false) + private String studentName; + + /** + * 学号 (通过student_id关联查询获取) + */ + @TableField(exist = false) + private String studentNumber; + + /** + * 班级名称 (通过student_id关联查询获取) + */ + @TableField(exist = false) + private String className; + + /** + * 实习单位名称 (通过internship_id关联查询获取) + */ + @TableField(exist = false) + private String companyName; + + /** + * 实习岗位 (通过internship_id关联查询获取) + */ + @TableField(exist = false) + private String position; + + /** + * 签到地点 (业务扩展字段,当前只有签退地点) + */ + @TableField(exist = false) + private String checkInLocation; + + /** + * 签到经度 (业务扩展字段,当前只有签退经度) + */ + @TableField(exist = false) + private BigDecimal checkInLongitude; + + /** + * 签到纬度 (业务扩展字段,当前只有签退纬度) + */ + @TableField(exist = false) + private BigDecimal checkInLatitude; + + /** + * 签退时间 (业务扩展字段,当前只有签到时间) + */ + @TableField(exist = false) + private LocalTime checkOutTime; + + /** + * 工作时长(小时) (业务计算字段) + */ + @TableField(exist = false) + private BigDecimal workDuration; + } diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyInternshipDailyAddBo.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyInternshipDailyAddBo.java index 49e037d7..5d344d2a 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyInternshipDailyAddBo.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyInternshipDailyAddBo.java @@ -10,7 +10,8 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import java.io.Serial; import java.math.BigDecimal; -import java.sql.Time; +import java.time.LocalDate; +import java.time.LocalTime; import java.util.Date; /** @@ -31,53 +32,87 @@ public class ZsjyInternshipDailyAddBo extends BaseEntity { * 实习ID */ @Schema(description = "实习ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "实习ID不能为空", groups = {AddGroup.class}) + @NotNull(message = "实习ID不能为空", groups = {AddGroup.class, CheckInGroup.class}) private Long internshipId; /** * 学生ID */ @Schema(description = "学生ID", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "学生ID不能为空", groups = {AddGroup.class}) + @NotNull(message = "学生ID不能为空", groups = {AddGroup.class, CheckInGroup.class}) private Long studentId; /** - * 打卡日期 + * 签到日期 */ - @Schema(description = "打卡日期", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "打卡日期不能为空", groups = {AddGroup.class}) - private Date checkDate; + @Schema(description = "签到日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签到日期不能为空", groups = {AddGroup.class, CheckInGroup.class}) + private LocalDate checkDate; /** * 签到时间 */ - @Schema(description = "签到时间") - private Time checkInTime; + @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签到时间不能为空", groups = {AddGroup.class, CheckInGroup.class}) + private LocalTime checkInTime; /** - * 签到位置 + * 签退时间 */ - @Schema(description = "签到位置") - @Size(max = 200, message = "签到位置长度不能超过200个字符") + @Schema(description = "签退时间") + private LocalTime checkOutTime; + + /** + * 签到地点 (前端传递字段,映射到数据库check_in_location字段) + */ + @Schema(description = "签到地点", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签到地点不能为空", groups = {CheckInGroup.class}) + @Size(max = 500, message = "签到地点长度不能超过500个字符") private String checkInLocation; /** - * 纬度 + * 签到纬度 (前端传递字段,映射到数据库latitude字段) */ - @Schema(description = "纬度") + @Schema(description = "签到纬度", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签到纬度不能为空", groups = {CheckInGroup.class}) private BigDecimal latitude; /** - * 经度 + * 签到经度 (前端传递字段,映射到数据库longitude字段) */ - @Schema(description = "经度") + @Schema(description = "签到经度", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签到经度不能为空", groups = {CheckInGroup.class}) private BigDecimal longitude; /** - * 日总结 + * 签退地点 (对应数据库check_in_location字段,实际存储签退地点) */ - @Schema(description = "日总结") - private String dailySummary; + @Schema(description = "签退地点", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签退地点不能为空", groups = {AddGroup.class}) + @Size(max = 500, message = "签退地点长度不能超过500个字符") + private String checkOutLocation; + + /** + * 签退纬度 (对应数据库latitude字段) + */ + @Schema(description = "签退纬度", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签退纬度不能为空", groups = {AddGroup.class}) + private BigDecimal checkOutLatitude; + + /** + * 签退经度 (对应数据库longitude字段) + */ + @Schema(description = "签退经度", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "签退经度不能为空", groups = {AddGroup.class}) + private BigDecimal checkOutLongitude; + + /** + * 工作内容 (对应数据库daily_summary字段) + */ + @Schema(description = "工作内容", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "工作内容不能为空", groups = {AddGroup.class}) + @Size(max = 1000, message = "工作内容长度不能超过1000个字符") + private String workContent; /** * 图片附件(JSON格式) @@ -95,25 +130,112 @@ public class ZsjyInternshipDailyAddBo extends BaseEntity { * 异常原因 */ @Schema(description = "异常原因") - @Size(max = 500, message = "异常原因长度不能超过500个字符") private String exceptionReason; /** - * 异常处理状态(0待处理 1已处理) + * 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工) */ - @Schema(description = "异常处理状态") - private String exceptionStatus; - - /** - * 状态(0正常 1停用) - */ - @Schema(description = "状态") + @Schema(description = "考勤状态") private String status; /** * 备注 */ @Schema(description = "备注") + @Size(max = 500, message = "备注长度不能超过500个字符") private String remark; + // ==================== 扩展字段(用于显示,不存储到数据库) ==================== + + /** + * 学生姓名(扩展字段,用于显示) + */ + @Schema(description = "学生姓名", hidden = true) + private String studentName; + + /** + * 学生学号(扩展字段,用于显示) + */ + @Schema(description = "学生学号", hidden = true) + private String studentNumber; + + /** + * 班级名称(扩展字段,用于显示) + */ + @Schema(description = "班级名称", hidden = true) + private String className; + + /** + * 企业名称(扩展字段,用于显示) + */ + @Schema(description = "企业名称", hidden = true) + private String companyName; + + /** + * 实习岗位(扩展字段,用于显示) + */ + @Schema(description = "实习岗位", hidden = true) + private String position; + + // ==================== 兼容移动端字段(前端可能使用的别名) ==================== + + /** + * 日总结(兼容移动端,实际映射为workContent) + */ + @Schema(description = "日总结", hidden = true) + private String dailySummary; + + // ==================== 数据转换方法(处理前端字段映射) ==================== + + /** + * 处理移动端兼容字段映射 + * 将移动端使用的字段名映射到实际的字段 + */ + public void processCompatibleFields() { + // 处理经纬度映射(签到时映射到签退字段存储) + if (this.latitude != null && this.checkOutLatitude == null) { + this.checkOutLatitude = this.latitude; + } + if (this.longitude != null && this.checkOutLongitude == null) { + this.checkOutLongitude = this.longitude; + } + + // 处理工作内容映射 + if (this.dailySummary != null && this.workContent == null) { + this.workContent = this.dailySummary; + } + + // 处理签到位置映射(签到时映射到签退字段存储) + if (this.checkInLocation != null && this.checkOutLocation == null) { + this.checkOutLocation = this.checkInLocation; + } + } + + /** + * 获取实际的签退地点(优先使用checkOutLocation,否则使用checkInLocation) + */ + public String getActualCheckOutLocation() { + return this.checkOutLocation != null ? this.checkOutLocation : this.checkInLocation; + } + + /** + * 获取实际的签退经度(优先使用checkOutLongitude,否则使用longitude) + */ + public BigDecimal getActualCheckOutLongitude() { + return this.checkOutLongitude != null ? this.checkOutLongitude : this.longitude; + } + + /** + * 获取实际的签退纬度(优先使用checkOutLatitude,否则使用latitude) + */ + public BigDecimal getActualCheckOutLatitude() { + return this.checkOutLatitude != null ? this.checkOutLatitude : this.latitude; + } + + /** + * 获取实际的工作内容(优先使用workContent,否则使用dailySummary) + */ + public String getActualWorkContent() { + return this.workContent != null ? this.workContent : this.dailySummary; + } } diff --git a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java index 20ba3a91..9f5c97db 100644 --- a/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java +++ b/backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.R; import org.dromara.common.core.exception.ServiceException; 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.common.satoken.utils.LoginHelper; @@ -22,8 +23,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.sql.Time; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.YearMonth; +import java.time.ZoneId; import java.util.*; /** @@ -64,32 +68,70 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi @Transactional(rollbackFor = Exception.class) public R checkIn(ZsjyInternshipDailyAddBo addBo) { try { - // 1. 验证学生当日是否已签到 - boolean exists = baseMapper.existsByStudentAndDate(addBo.getStudentId(), addBo.getCheckDate()); + // 1. 验证学生当日是否已签到 - 将LocalDate转换为Date + Date checkDateAsDate = Date.from(addBo.getCheckDate().atStartOfDay(ZoneId.systemDefault()).toInstant()); + boolean exists = baseMapper.existsByStudentAndDate(addBo.getStudentId(), checkDateAsDate); if (exists) { return R.fail("今日已签到,请勿重复签到"); } - // 2. 构建实体对象 - ZsjyInternshipDaily entity = MapstructUtils.convert(addBo, ZsjyInternshipDaily.class); + // 2. 处理兼容字段映射(移动端可能使用的别名映射到正确的字段) + if (addBo.getLatitude() != null && addBo.getCheckOutLatitude() == null) { + addBo.setCheckOutLatitude(addBo.getLatitude()); + } + if (addBo.getLongitude() != null && addBo.getCheckOutLongitude() == null) { + addBo.setCheckOutLongitude(addBo.getLongitude()); + } + if (addBo.getDailySummary() != null && addBo.getWorkContent() == null) { + addBo.setWorkContent(addBo.getDailySummary()); + } + if (addBo.getCheckInLocation() != null && addBo.getCheckOutLocation() == null) { + addBo.setCheckOutLocation(addBo.getCheckInLocation()); + } - // 3. 设置签到时间为当前时间 + // 3. 构建实体对象 - 手动创建避免MapStruct转换器错误 + ZsjyInternshipDaily entity = new ZsjyInternshipDaily(); + + // 核心必填字段(对应数据库字段) + entity.setInternshipId(addBo.getInternshipId()); + entity.setStudentId(addBo.getStudentId()); + entity.setCheckDate(addBo.getCheckDate()); + entity.setCheckInTime(addBo.getCheckInTime()); + entity.setCheckOutLocation(addBo.getCheckOutLocation()); // 对应数据库check_in_location字段 + entity.setCheckOutLatitude(addBo.getCheckOutLatitude()); // 对应数据库latitude字段 + entity.setCheckOutLongitude(addBo.getCheckOutLongitude()); // 对应数据库longitude字段 + entity.setWorkContent(addBo.getWorkContent()); // 对应数据库daily_summary字段 + entity.setImages(addBo.getImages()); + entity.setIsException(addBo.getIsException()); + entity.setExceptionReason(addBo.getExceptionReason()); + entity.setStatus(addBo.getStatus()); + entity.setRemark(addBo.getRemark()); + + // 扩展字段(不存储到数据库,仅用于显示) + entity.setStudentName(addBo.getStudentName()); + entity.setStudentNumber(addBo.getStudentNumber()); + entity.setClassName(addBo.getClassName()); + entity.setCompanyName(addBo.getCompanyName()); + entity.setPosition(addBo.getPosition()); + + // 继承BaseEntity的字段会自动填充(create_time, create_by等) + + // 4. 设置签到时间为当前时间(如果没有传入) if (ObjectUtil.isNull(entity.getCheckInTime())) { - entity.setCheckInTime(Time.valueOf(DateUtil.format(new Date(), "HH:mm:ss"))); + entity.setCheckInTime(LocalTime.now()); } - // 4. 设置默认值 - if (ObjectUtil.isNull(entity.getIsException())) { - entity.setIsException("0"); // 默认正常 - } - if (ObjectUtil.isNull(entity.getExceptionStatus())) { - entity.setExceptionStatus("0"); // 默认待处理 - } + // 5. 设置默认状态 if (ObjectUtil.isNull(entity.getStatus())) { - entity.setStatus("0"); // 默认正常 + entity.setStatus("1"); // 正常状态 } - // 5. 保存签到记录 + // 6. 设置默认异常状态 + if (ObjectUtil.isNull(entity.getIsException())) { + entity.setIsException("0"); // 正常 + } + + // 7. 保存签到记录 boolean result = baseMapper.insert(entity) > 0; if (!result) { return R.fail("签到失败,请稍后重试"); @@ -100,7 +142,7 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi } catch (Exception e) { log.error("学生签到失败: {}", e.getMessage(), e); - throw new ServiceException("签到失败: " + e.getMessage()); + return R.fail("签到失败: " + e.getMessage()); } } diff --git a/mobile/src/pages.json b/mobile/src/pages.json index b2d90571..4a01ca34 100644 --- a/mobile/src/pages.json +++ b/mobile/src/pages.json @@ -119,6 +119,14 @@ "navigationBarTitleText": "微信JS-SDK测试", "navigationStyle": "custom" } + }, + { + "path": "pages/internship/index", + "style": { + "navigationBarTitleText": "实习打卡", + "navigationBarBackgroundColor": "#0051d9", + "navigationBarTextStyle": "white" + } } ], "globalStyle": { diff --git a/mobile/src/pages/index/index.vue b/mobile/src/pages/index/index.vue index 291c979f..db77be33 100644 --- a/mobile/src/pages/index/index.vue +++ b/mobile/src/pages/index/index.vue @@ -154,6 +154,20 @@ /> + + + + @@ -575,7 +589,8 @@ export default { this.hasPermi(['student:psychology:list']) || this.hasPermi(['student:club:list']) || this.hasPermi(['student:counsel:list']) || - this.hasPermi(['student:info:edit']) + this.hasPermi(['student:info:edit']) || + this.hasPermi(['student:internship:list']) ); }, @@ -776,6 +791,13 @@ export default { }); }, + // 跳转到实习管理页面 + gotoInternshipManage() { + uni.navigateTo({ + url: '/pages/internship/index', + }); + }, + // 图片加载成功处理 handleImageLoad(event) { console.log('✅ 轮播图片加载成功:', event.detail); diff --git a/mobile/src/utils/permission.js b/mobile/src/utils/permission.js index fcf3c4e0..11cf33bb 100644 --- a/mobile/src/utils/permission.js +++ b/mobile/src/utils/permission.js @@ -14,6 +14,10 @@ export const checkPermi = (value) => { if (value && value instanceof Array && value.length > 0) { const userInfo = userStorage.getUserInfo(); if (!userInfo || !userInfo.permissions) { + console.warn('🚫 权限检查失败: 用户信息或权限列表不存在', { + hasUserInfo: !!userInfo, + hasPermissions: !!(userInfo && userInfo.permissions) + }); return false; } @@ -21,11 +25,33 @@ export const checkPermi = (value) => { const permissionDatas = value; const all_permission = '*:*:*'; + // 调试日志:输出当前用户权限和检查的权限 + console.log('🔐 权限检查调试信息:', { + 检查权限: permissionDatas, + 用户权限数量: permissions.length, + 是否包含超级权限: permissions.includes(all_permission), + 权限匹配结果: permissionDatas.some(perm => permissions.includes(perm)) + }); + + // 特别检查实习相关权限 + if (permissionDatas.some(perm => perm.includes('internship'))) { + console.log('📚 实习权限检查详情:', { + 检查的实习权限: permissionDatas.filter(perm => perm.includes('internship')), + 用户拥有的实习权限: permissions.filter(perm => perm.includes('internship')), + 所有权限前10条: permissions.slice(0, 10) + }); + } + const hasPermission = permissions.some((permission) => { return all_permission === permission || permissionDatas.includes(permission); }); if (!hasPermission) { + console.warn('🚫 权限验证失败:', { + 需要权限: permissionDatas, + 用户ID: userInfo.user?.userId, + 用户名: userInfo.user?.userName + }); return false; } return true; diff --git a/web/src/views/zsjy/internship/daily/index.vue b/web/src/views/zsjy/internship/daily/index.vue index 5a132e2b..dbac2d0d 100644 --- a/web/src/views/zsjy/internship/daily/index.vue +++ b/web/src/views/zsjy/internship/daily/index.vue @@ -125,9 +125,9 @@
实习日常管理
- 新增签到 + 新增签到 搜索 - 导出 + 导出
@@ -578,7 +578,7 @@ const submitAdd = () => { proxy.$refs.addFormRef.validate(valid => { if (valid) { addLoading.value = true; - + addInternshipDaily(addForm.value).then(response => { proxy.$modal.msgSuccess("新增签到记录成功"); addDialogVisible.value = false;