wuzhen update

This commit is contained in:
wuzhen committed 2025-08-14 10:52:22 +08:00
1 parent 84016d2f1a
commit 9a16535359
9 files changed
+408 -64

No files matched your search

@@ -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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController; 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.vo.InternshipInfoVO;
import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO; import org.dromara.zsjy.domain.bo.InternshipInfoQueryBO;
import org.dromara.zsjy.domain.bo.InternshipInfoAddBO; import org.dromara.zsjy.domain.bo.InternshipInfoAddBO;
@@ -101,6 +102,37 @@ public class InternshipInfoController extends BaseController {
return R.ok(internshipInfoService.getInternshipStatistics(queryBO)); return R.ok(internshipInfoService.getInternshipStatistics(queryBO));
} }
/**
* 学生获取自己的实习信息(移动端专用)
*/
@Operation(summary = "学生获取实习信息", description = "学生查看自己的实习信息(移动端)")
@GetMapping("/student/info")
public R<InternshipInfoVO> 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());
}
}
/** /**
* 新增实习信息 * 新增实习信息
*/ */
@@ -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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController; 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.ZsjyInternshipDailyAddBo;
import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyQueryBo; import org.dromara.zsjy.domain.bo.ZsjyInternshipDailyQueryBo;
import org.dromara.zsjy.domain.vo.ZsjyInternshipDailyVo; import org.dromara.zsjy.domain.vo.ZsjyInternshipDailyVo;
@@ -58,7 +59,7 @@ public class ZsjyInternshipDailyController extends BaseController {
@Operation(summary = "学生签到打卡", description = "学生进行实习日常签到打卡") @Operation(summary = "学生签到打卡", description = "学生进行实习日常签到打卡")
@SaCheckPermission("zsjy:internshipdaily:checkin") @SaCheckPermission("zsjy:internshipdaily:checkin")
@PostMapping("/checkin") @PostMapping("/checkin")
public R<Void> checkIn(@Validated(AddGroup.class) @RequestBody ZsjyInternshipDailyAddBo addBo) { public R<Void> checkIn(@Validated(CheckInGroup.class) @RequestBody ZsjyInternshipDailyAddBo addBo) {
log.info("=== Controller层调试 ==="); log.info("=== Controller层调试 ===");
log.info("接口被调用: /zsjy/internship/daily/checkin"); log.info("接口被调用: /zsjy/internship/daily/checkin");
log.info("签到参数: {}", addBo); log.info("签到参数: {}", addBo);
@@ -1,5 +1,7 @@
package org.dromara.zsjy.domain; 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.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -9,6 +11,8 @@ import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial; import java.io.Serial;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Time; import java.sql.Time;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date; import java.util.Date;
/** /**
@@ -26,74 +30,161 @@ public class ZsjyInternshipDaily extends BaseEntity {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 日常记录ID * 日常记录ID (对应数据库daily_id字段)
*/ */
@TableId(value = "daily_id") @TableId(value = "daily_id", type = IdType.ASSIGN_ID)
private Long dailyId; private Long id;
/**
* 租户ID
*/
@TableField("tenant_id")
private String tenantId;
/** /**
* 实习ID * 实习ID
*/ */
@TableField("internship_id")
private Long internshipId; private Long internshipId;
/** /**
* 学生ID * 学生ID
*/ */
@TableField("student_id")
private Long studentId; 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格式) * 图片附件(JSON格式)
*/ */
@TableField("images")
private String images; private String images;
/** /**
* 是否异常(0正常 1异常) * 是否异常(0正常 1异常)
*/ */
@TableField("is_exception")
private String isException; private String isException;
/** /**
* 异常原因 * 异常原因
*/ */
@TableField("exception_reason")
private String exceptionReason; private String exceptionReason;
/** /**
* 异常处理状态(0待处理 1已处理) * 异常处理状态(0待处理 1已处理)
*/ */
@TableField("exception_status")
private String exceptionStatus; private String exceptionStatus;
/** /**
* 状态(0正常 1停用) * 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工)
*/ */
@TableField("status")
private String 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;
} }
@@ -10,7 +10,8 @@ import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import java.io.Serial; import java.io.Serial;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Time; import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date; import java.util.Date;
/** /**
@@ -31,53 +32,87 @@ public class ZsjyInternshipDailyAddBo extends BaseEntity {
* 实习ID * 实习ID
*/ */
@Schema(description = "实习ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "实习ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "实习ID不能为空", groups = {AddGroup.class}) @NotNull(message = "实习ID不能为空", groups = {AddGroup.class, CheckInGroup.class})
private Long internshipId; private Long internshipId;
/** /**
* 学生ID * 学生ID
*/ */
@Schema(description = "学生ID", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "学生ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "学生ID不能为空", groups = {AddGroup.class}) @NotNull(message = "学生ID不能为空", groups = {AddGroup.class, CheckInGroup.class})
private Long studentId; private Long studentId;
/** /**
* 打卡日期 * 签到日期
*/ */
@Schema(description = "打卡日期", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "签到日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "打卡日期不能为空", groups = {AddGroup.class}) @NotNull(message = "签到日期不能为空", groups = {AddGroup.class, CheckInGroup.class})
private Date checkDate; private LocalDate checkDate;
/** /**
* 签到时间 * 签到时间
*/ */
@Schema(description = "签到时间") @Schema(description = "签到时间", requiredMode = Schema.RequiredMode.REQUIRED)
private Time checkInTime; @NotNull(message = "签到时间不能为空", groups = {AddGroup.class, CheckInGroup.class})
private LocalTime checkInTime;
/** /**
* 签到位置 * 签退时间
*/ */
@Schema(description = "签到位置") @Schema(description = "签退时间")
@Size(max = 200, message = "签到位置长度不能超过200个字符") 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; private String checkInLocation;
/** /**
* 纬度 * 签到纬度 (前端传递字段,映射到数据库latitude字段)
*/ */
@Schema(description = "纬度") @Schema(description = "签到纬度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到纬度不能为空", groups = {CheckInGroup.class})
private BigDecimal latitude; private BigDecimal latitude;
/** /**
* 经度 * 签到经度 (前端传递字段,映射到数据库longitude字段)
*/ */
@Schema(description = "经度") @Schema(description = "签到经度", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "签到经度不能为空", groups = {CheckInGroup.class})
private BigDecimal longitude; private BigDecimal longitude;
/** /**
* 日总结 * 签退地点 (对应数据库check_in_location字段,实际存储签退地点)
*/ */
@Schema(description = "日总结") @Schema(description = "签退地点", requiredMode = Schema.RequiredMode.REQUIRED)
private String dailySummary; @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格式) * 图片附件(JSON格式)
@@ -95,25 +130,112 @@ public class ZsjyInternshipDailyAddBo extends BaseEntity {
* 异常原因 * 异常原因
*/ */
@Schema(description = "异常原因") @Schema(description = "异常原因")
@Size(max = 500, message = "异常原因长度不能超过500个字符")
private String exceptionReason; private String exceptionReason;
/** /**
* 异常处理状态(0待处理 1已处理) * 考勤状态(0=未签到 1=正常 2=迟到 3=早退 4=旷工)
*/ */
@Schema(description = "异常处理状态") @Schema(description = "考勤状态")
private String exceptionStatus;
/**
* 状态(0正常 1停用)
*/
@Schema(description = "状态")
private String status; private String status;
/** /**
* 备注 * 备注
*/ */
@Schema(description = "备注") @Schema(description = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark; 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;
}
} }
@@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils; 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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
@@ -22,8 +23,11 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.sql.Time; import java.sql.Time;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth; import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*; import java.util.*;
/** /**
@@ -64,32 +68,70 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public R<Void> checkIn(ZsjyInternshipDailyAddBo addBo) { public R<Void> checkIn(ZsjyInternshipDailyAddBo addBo) {
try { try {
// 1. 验证学生当日是否已签到 // 1. 验证学生当日是否已签到 - 将LocalDate转换为Date
boolean exists = baseMapper.existsByStudentAndDate(addBo.getStudentId(), addBo.getCheckDate()); Date checkDateAsDate = Date.from(addBo.getCheckDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
boolean exists = baseMapper.existsByStudentAndDate(addBo.getStudentId(), checkDateAsDate);
if (exists) { if (exists) {
return R.fail("今日已签到,请勿重复签到"); return R.fail("今日已签到,请勿重复签到");
} }
// 2. 构建实体对象 // 2. 处理兼容字段映射(移动端可能使用的别名映射到正确的字段)
ZsjyInternshipDaily entity = MapstructUtils.convert(addBo, ZsjyInternshipDaily.class); 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())) { if (ObjectUtil.isNull(entity.getCheckInTime())) {
entity.setCheckInTime(Time.valueOf(DateUtil.format(new Date(), "HH:mm:ss"))); entity.setCheckInTime(LocalTime.now());
} }
// 4. 设置默认值 // 5. 设置默认状态
if (ObjectUtil.isNull(entity.getIsException())) {
entity.setIsException("0"); // 默认正常
}
if (ObjectUtil.isNull(entity.getExceptionStatus())) {
entity.setExceptionStatus("0"); // 默认待处理
}
if (ObjectUtil.isNull(entity.getStatus())) { 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; boolean result = baseMapper.insert(entity) > 0;
if (!result) { if (!result) {
return R.fail("签到失败,请稍后重试"); return R.fail("签到失败,请稍后重试");
@@ -100,7 +142,7 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi
} catch (Exception e) { } catch (Exception e) {
log.error("学生签到失败: {}", e.getMessage(), e); log.error("学生签到失败: {}", e.getMessage(), e);
throw new ServiceException("签到失败: " + e.getMessage()); return R.fail("签到失败: " + e.getMessage());
} }
} }
+8
View File
@@ -119,6 +119,14 @@
"navigationBarTitleText": "微信JS-SDK测试", "navigationBarTitleText": "微信JS-SDK测试",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},
{
"path": "pages/internship/index",
"style": {
"navigationBarTitleText": "实习打卡",
"navigationBarBackgroundColor": "#0051d9",
"navigationBarTextStyle": "white"
}
} }
], ],
"globalStyle": { "globalStyle": {
+23 -1
View File
@@ -154,6 +154,20 @@
/> />
</template> </template>
</ServiceItem> </ServiceItem>
<ServiceItem
v-if="hasPermi(['student:internship:list'])"
title="实习打卡"
@click="gotoInternshipManage"
>
<template #icon>
<image
src="/static/00116.png"
mode="aspectFit"
style="width: 24px; height: 24px"
/>
</template>
</ServiceItem>
</GridLayout> </GridLayout>
</Card> </Card>
@@ -575,7 +589,8 @@ export default {
this.hasPermi(['student:psychology:list']) || this.hasPermi(['student:psychology:list']) ||
this.hasPermi(['student:club:list']) || this.hasPermi(['student:club:list']) ||
this.hasPermi(['student:counsel: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) { handleImageLoad(event) {
console.log('✅ 轮播图片加载成功:', event.detail); console.log('✅ 轮播图片加载成功:', event.detail);
+26
View File
@@ -14,6 +14,10 @@ export const checkPermi = (value) => {
if (value && value instanceof Array && value.length > 0) { if (value && value instanceof Array && value.length > 0) {
const userInfo = userStorage.getUserInfo(); const userInfo = userStorage.getUserInfo();
if (!userInfo || !userInfo.permissions) { if (!userInfo || !userInfo.permissions) {
console.warn('🚫 权限检查失败: 用户信息或权限列表不存在', {
hasUserInfo: !!userInfo,
hasPermissions: !!(userInfo && userInfo.permissions)
});
return false; return false;
} }
@@ -21,11 +25,33 @@ export const checkPermi = (value) => {
const permissionDatas = value; const permissionDatas = value;
const all_permission = '*:*:*'; 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) => { const hasPermission = permissions.some((permission) => {
return all_permission === permission || permissionDatas.includes(permission); return all_permission === permission || permissionDatas.includes(permission);
}); });
if (!hasPermission) { if (!hasPermission) {
console.warn('🚫 权限验证失败:', {
需要权限: permissionDatas,
用户ID: userInfo.user?.userId,
用户名: userInfo.user?.userName
});
return false; return false;
} }
return true; return true;
@@ -125,9 +125,9 @@
<div class="card-header-vertical"> <div class="card-header-vertical">
<div class="toolbar-title">实习日常管理</div> <div class="toolbar-title">实习日常管理</div>
<div class="button-group"> <div class="button-group">
<el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['zsjy:internship:daily:add']">新增签到</el-button> <el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['zsjy:internshipdaily:add']">新增签到</el-button>
<el-button plain icon="Search" @click="showSearch = !showSearch">搜索</el-button> <el-button plain icon="Search" @click="showSearch = !showSearch">搜索</el-button>
<el-button type="primary" plain icon="Download" @click="handleExport" v-hasPermi="['zsjy:internship:daily:export']">导出</el-button> <el-button type="primary" plain icon="Download" @click="handleExport" v-hasPermi="['zsjy:internshipdaily:export']">导出</el-button>
</div> </div>
</div> </div>
</el-card> </el-card>
@@ -578,7 +578,7 @@ const submitAdd = () => {
proxy.$refs.addFormRef.validate(valid => { proxy.$refs.addFormRef.validate(valid => {
if (valid) { if (valid) {
addLoading.value = true; addLoading.value = true;
addInternshipDaily(addForm.value).then(response => { addInternshipDaily(addForm.value).then(response => {
proxy.$modal.msgSuccess("新增签到记录成功"); proxy.$modal.msgSuccess("新增签到记录成功");
addDialogVisible.value = false; addDialogVisible.value = false;