前端代码 和 权限校验

This commit is contained in:
liumengyu
2026-08-21 17:46:50 +08:00
parent 179b12e3bf
commit 8312231af5
11 changed files with 201 additions and 93 deletions
@@ -1,6 +1,7 @@
package com.roomroot.jwgl.config;
import com.roomroot.jwgl.interceptor.AccountManagementAuthorizationInterceptor;
import com.roomroot.jwgl.interceptor.JwglApiAccessInterceptor;
import com.roomroot.jwgl.interceptor.OperationLogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@@ -26,21 +27,27 @@ public class AccountManagementWebMvcConfig implements WebMvcConfigurer {
*/
private final OperationLogInterceptor operationLogInterceptor;
private final JwglApiAccessInterceptor jwglApiAccessInterceptor;
/**
* 构造账户管理和操作日志统一 Web MVC 配置。
*
* @param authorizationInterceptor 账户管理身份和权限拦截器
* @param operationLogInterceptor 操作日志统一请求采集拦截器
* @param jwglApiAccessInterceptor 教务角色接口访问拦截器
*/
public AccountManagementWebMvcConfig(
AccountManagementAuthorizationInterceptor
authorizationInterceptor,
OperationLogInterceptor operationLogInterceptor) {
OperationLogInterceptor operationLogInterceptor,
JwglApiAccessInterceptor jwglApiAccessInterceptor) {
// 第一步:保存账户管理专用拦截器,供 MVC 注册阶段使用。
this.authorizationInterceptor = authorizationInterceptor;
// 第二步:保存操作日志采集拦截器,供 MVC 注册阶段使用。
this.operationLogInterceptor = operationLogInterceptor;
this.jwglApiAccessInterceptor = jwglApiAccessInterceptor;
}
/**
@@ -65,6 +72,17 @@ public class AccountManagementWebMvcConfig implements WebMvcConfigurer {
* 第五步:覆盖全部 Controller 请求,由采集拦截器自行跳过
* 非 Controller 处理器和没有有效登录记录的请求。
*/
registry.addInterceptor(jwglApiAccessInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(
"/login",
"/register",
"/captchaImage",
"/jys/teacher/list",
"/swagger-ui/**",
"/v3/api-docs/**",
"/druid/**");
registry.addInterceptor(operationLogInterceptor)
.addPathPatterns("/**");
}
@@ -85,6 +85,9 @@
<if test="cond.kcmc != null and cond.kcmc != ''">
AND k."课名称" LIKE CONCAT('%', #{cond.kcmc}, '%')
</if>
<if test="cond.jybh != null and cond.jybh != ''">
AND r."教员编号" = #{cond.jybh}
</if>
<if test="cond.skjy != null and cond.skjy != ''">
AND j."教员姓名" LIKE CONCAT('%', #{cond.skjy}, '%')
</if>
@@ -1,6 +1,7 @@
package com.roomroot.jwgl.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.jwgl.entity.XYKCCJ;
import com.roomroot.jwgl.vo.elective.StudentGradeVO;
import org.apache.ibatis.annotations.Mapper;
@@ -13,6 +14,14 @@ public interface XYKCCJMapper extends BaseMapper<XYKCCJ> {
List<XYKCCJ> selectByStudentId(@Param("xybh") String xybh);
/**
* 分页条件查询课程成绩。
* <p>学员编号、年度可选;年度未传时默认取最大年度(最新年度)的数据。</p>
*/
Page<XYKCCJ> selectPageByCondition(Page<XYKCCJ> page,
@Param("xybh") String xybh,
@Param("nd") Integer nd);
/** 按学员队查询成绩(含学员姓名学号) */
List<StudentGradeVO> selectGradeByXydbh(@Param("xydbh") String xydbh, @Param("kmbh") String kmbh);
}
@@ -36,6 +36,23 @@
ORDER BY 年度 DESC, 科目编号
</select>
<!-- 分页条件查询课程成绩:学员编号、年度可选;年度未传时默认取最大年度(最新年度) -->
<select id="selectPageByCondition" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM "学员课程成绩"
WHERE 1=1
<if test="xybh != null and xybh != ''">
AND 学员编号 = #{xybh}
</if>
<if test="nd != null">
AND 年度 = #{nd}
</if>
<if test="nd == null">
AND 年度 = (SELECT MAX(年度) FROM "学员课程成绩")
</if>
ORDER BY 年度 DESC, 科目编号
</select>
<resultMap id="GradeResultMap" type="com.roomroot.jwgl.vo.elective.StudentGradeVO">
<result column="学员编号" property="xybh"/>
<result column="姓名" property="xm"/>
@@ -1,6 +1,7 @@
package com.roomroot.jwgl.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.jwgl.entity.XYKCGCCJ;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -11,4 +12,12 @@ import java.util.List;
public interface XYKCGCCJMapper extends BaseMapper<XYKCGCCJ> {
List<XYKCGCCJ> selectByStudentId(@Param("xybh") String xybh);
/**
* 分页条件查询课程过程成绩。
* <p>学员编号、年度可选;年度未传时默认取最大年度(最新年度)的数据。</p>
*/
Page<XYKCGCCJ> selectPageByCondition(Page<XYKCGCCJ> page,
@Param("xybh") String xybh,
@Param("nd") Integer nd);
}
@@ -37,4 +37,21 @@
ORDER BY 年度 DESC, 科目编号
</select>
<!-- 分页条件查询课程过程成绩:学员编号、年度可选;年度未传时默认取最大年度(最新年度) -->
<select id="selectPageByCondition" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM "学员课程过程成绩"
WHERE 1=1
<if test="xybh != null and xybh != ''">
AND 学员编号 = #{xybh}
</if>
<if test="nd != null">
AND 年度 = #{nd}
</if>
<if test="nd == null">
AND 年度 = (SELECT MAX(年度) FROM "学员课程过程成绩")
</if>
ORDER BY 年度 DESC, 科目编号
</select>
</mapper>
@@ -47,11 +47,11 @@ public interface StudentRecordsService {
// ========== 学员课程成绩查询 ==========
/** 查询学员的所有课程成绩 */
List<XYKCCJ> getCourseGrades(String xybh);
/** 分页查询学员的课程成绩列表(按学员编号、年度筛选,年度为空默认最新年度) */
PageResult<XYKCCJ> pageCourseGrades(PageQuery query, String xybh, Integer nd);
/** 查询学员的所有课程过程成绩 */
List<XYKCGCCJ> getCourseProcessGrades(String xybh);
/** 分页查询学员的课程过程成绩列表(按学员编号、年度筛选,年度为空默认最新年度) */
PageResult<XYKCGCCJ> pageCourseProcessGrades(PageQuery query, String xybh, Integer nd);
// ========== Excel 导出 ==========
@@ -2,24 +2,18 @@ package com.roomroot.jwgl.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.common.constant.Constants;
import com.roomroot.common.core.domain.entity.SysRole;
import com.roomroot.common.core.domain.entity.SysUser;
import com.roomroot.common.core.domain.model.LoginUser;
import com.roomroot.common.exception.ServiceException;
import com.roomroot.common.utils.SecurityUtils;
import com.roomroot.common.utils.StringUtils;
import com.roomroot.common.utils.poi.ExcelUtil;
import com.roomroot.jwgl.dto.ks.HourStatisticsQuery;
import com.roomroot.jwgl.entity.JYB;
import com.roomroot.jwgl.entity.KSFBZ;
import com.roomroot.jwgl.mapper.JYBMapper;
import com.roomroot.jwgl.mapper.KSFBZMapper;
import com.roomroot.jwgl.mapper.KSTJBMapper;
import com.roomroot.jwgl.mapper.SystemInitializationMapper;
import com.roomroot.jwgl.service.KSService;
import com.roomroot.jwgl.unit.PageQuery;
import com.roomroot.jwgl.unit.PageResult;
import com.roomroot.jwgl.utils.JwglRoleHelper;
import com.roomroot.jwgl.vo.ks.HourStatisticsVO;
import com.roomroot.jwgl.vo.systeminitialization.SemesterInitializationVO;
import jakarta.servlet.http.HttpServletResponse;
@@ -31,9 +25,7 @@ import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.List;
import static com.roomroot.jwgl.utils.AccountManagementConstants.ROLE_DEPARTMENT_PERSONNEL;
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
import static com.roomroot.jwgl.utils.BasicManagementConstants.FORBIDDEN;
import static com.roomroot.jwgl.utils.BasicManagementConstants.NOT_FOUND;
/**
@@ -45,18 +37,18 @@ public class KSServiceImpl implements KSService {
private static final double DEFAULT_STANDARD_HOURS = 180D;
private static final double DEFAULT_BASE_RATE = 13D;
@Resource
private KSTJBMapper kstjbMapper;
@Resource
private KSFBZMapper ksfbzMapper;
@Resource
private JYBMapper jybMapper;
private KSTJBMapper kstjbMapper;
@Resource
private SystemInitializationMapper systemInitializationMapper;
@Resource
private JwglRoleHelper jwglRoleHelper;
@Override
public PageResult<HourStatisticsVO> pageHourStatistics(PageQuery query, HourStatisticsQuery cond) {
Page<HourStatisticsVO> page = queryHours(query, cond);
@@ -132,65 +124,14 @@ public class KSServiceImpl implements KSService {
filter.setNd(LocalDate.now().getYear());
}
}
if (isAdminViewer()) {
if (jwglRoleHelper.isDepartmentPersonnel()) {
return;
}
String teacherId = resolveLoginTeacherId();
String teacherId = jwglRoleHelper.requireTeacherId();
filter.setJybh(teacherId);
filter.setJyxm(null);
}
private boolean isAdminViewer() {
try {
if (SecurityUtils.isAdmin()) {
return true;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser.getPermissions() != null
&& loginUser.getPermissions().contains(Constants.ALL_PERMISSION)) {
return true;
}
SysUser user = loginUser.getUser();
if (user == null || user.getRoles() == null) {
return false;
}
for (SysRole role : user.getRoles()) {
if (role == null || StringUtils.isEmpty(role.getRoleKey())) {
continue;
}
String key = role.getRoleKey();
if (Constants.SUPER_ADMIN.equals(key)
|| ROLE_DEPARTMENT_PERSONNEL.equalsIgnoreCase(key)) {
return true;
}
}
return false;
} catch (Exception ex) {
return false;
}
}
private String resolveLoginTeacherId() {
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser user = loginUser.getUser();
String username = loginUser.getUsername();
if (StringUtils.isNotEmpty(username)) {
JYB byId = jybMapper.selectById(username);
if (byId != null) {
return byId.getJybh();
}
}
String nickName = user == null ? null : user.getNickName();
if (StringUtils.isNotEmpty(nickName)) {
List<JYB> matched = jybMapper.selectList(
new LambdaQueryWrapper<JYB>().eq(JYB::getJyxm, nickName));
if (matched != null && matched.size() == 1) {
return matched.get(0).getJybh();
}
}
throw new ServiceException("当前登录用户不是教员,无法查看课时统计", FORBIDDEN);
}
private SemesterInitializationVO resolveCurrentSemester() {
return systemInitializationMapper.selectCurrentSemester();
}
@@ -6,9 +6,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.jwgl.entity.*;
import com.roomroot.jwgl.mapper.*;
import com.roomroot.jwgl.mapper.*;
import com.roomroot.common.exception.ServiceException;
import com.roomroot.jwgl.service.LogService;
import com.roomroot.jwgl.unit.PageQuery;
import com.roomroot.jwgl.unit.PageResult;
import com.roomroot.jwgl.utils.JwglRoleHelper;
import com.roomroot.jwgl.vo.log.TeacherHoursVO;
import com.roomroot.jwgl.vo.log.TeachingLogListVO;
import org.springframework.stereotype.Service;
@@ -23,6 +25,8 @@ import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import static com.roomroot.jwgl.utils.BasicManagementConstants.FORBIDDEN;
/**
* 教学日志管理服务实现
*/
@@ -70,6 +74,9 @@ public class LogServiceImpl implements LogService {
@Resource
private TeacherHoursMapper teacherHoursMapper;
@Resource
private JwglRoleHelper jwglRoleHelper;
// ==================== 教学日志核心 ====================
@Override
@@ -99,11 +106,29 @@ public class LogServiceImpl implements LogService {
@Override
public PageResult<TeachingLogListVO> pageTeachingLogDetail(PageQuery query, TeachingLogListVO cond) {
TeachingLogListVO filter = cond == null ? new TeachingLogListVO() : cond;
applyTeachingLogScope(filter);
Page<TeachingLogListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
Page<TeachingLogListVO> result = sskcbRzMapper.selectTeachingLogList(page, cond);
Page<TeachingLogListVO> result = sskcbRzMapper.selectTeachingLogList(page, filter);
return new PageResult<>(result.getRecords(), result.getTotal(), query.getPageNum(), query.getPageSize());
}
/**
* 学员不可看教学日志;教员只看本人;机关人员看全部(已上报待审核由查询状态控制)。
*/
private void applyTeachingLogScope(TeachingLogListVO filter) {
if (jwglRoleHelper.isAdmin() || jwglRoleHelper.isDepartmentPersonnel()) {
return;
}
if (jwglRoleHelper.isStudent()) {
throw new ServiceException("学员无权查看教学日志", FORBIDDEN);
}
if (jwglRoleHelper.isTeacher()) {
filter.setJybh(jwglRoleHelper.requireTeacherId());
filter.setSkjy(null);
}
}
// ==================== 教学日志(实施_课程表_日志 36字段表) ====================
@Override
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roomroot.common.exception.ServiceException;
import com.roomroot.jwgl.entity.XYXX;
import com.roomroot.jwgl.entity.XYDB;
import com.roomroot.jwgl.entity.XYXJYDSQB;
@@ -22,6 +23,7 @@ import com.roomroot.jwgl.service.StudentRecordsService;
import com.roomroot.jwgl.unit.PageQuery;
import com.roomroot.jwgl.unit.PageResult;
import com.roomroot.jwgl.utils.ExcelParseUtil;
import com.roomroot.jwgl.utils.JwglRoleHelper;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
@@ -40,6 +42,8 @@ import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import static com.roomroot.jwgl.utils.BasicManagementConstants.FORBIDDEN;
/**
* 学员档案管理服务实现类
*/
@@ -67,9 +71,13 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
@Resource
private XYKCGCCJMapper xykgccjMapper;
@Resource
private JwglRoleHelper jwglRoleHelper;
@Override
@Transactional
public void add(XYXX xyxx) {
denyStudentWrite();
xyxx.setTxzt(0);
xyxx.setLjzt(0);
xyxx.setFbzt(0);
@@ -79,6 +87,7 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
@Override
@Transactional
public void delete(String bh) {
denyStudentWrite();
XYXX xyxx = new XYXX();
xyxx.setBh(bh);
xyxx.setTxzt(1);
@@ -88,18 +97,24 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
@Override
@Transactional
public void update(XYXX xyxx) {
denyStudentWrite();
xyxxMapper.updateById(xyxx);
}
@Override
public XYXX getById(String bh) {
assertStudentOwn(bh);
return xyxxMapper.selectById(bh);
}
@Override
public PageResult<XYXX> pageList(PageQuery query, XYXX xyxx) {
XYXX filter = xyxx == null ? new XYXX() : xyxx;
if (jwglRoleHelper.isStudent()) {
filter.setBh(jwglRoleHelper.requireStudentId());
}
Page<XYXX> page = new Page<>(query.getPageNum(), query.getPageSize());
Page<XYXX> result = xyxxMapper.selectPage(page, buildQueryWrapper(xyxx));
Page<XYXX> result = xyxxMapper.selectPage(page, buildQueryWrapper(filter));
return new PageResult<>(result.getRecords(), result.getTotal(),
query.getPageNum(), query.getPageSize());
}
@@ -176,13 +191,27 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
// ========== 学员课程成绩查询 ==========
@Override
public List<XYKCCJ> getCourseGrades(String xybh) {
return xykccjMapper.selectByStudentId(xybh);
public PageResult<XYKCCJ> pageCourseGrades(PageQuery query, String xybh, Integer nd) {
String studentId = xybh;
if (jwglRoleHelper.isStudent()) {
studentId = jwglRoleHelper.requireStudentId();
}
Page<XYKCCJ> page = new Page<>(query.getPageNum(), query.getPageSize());
Page<XYKCCJ> result = xykccjMapper.selectPageByCondition(page, studentId, nd);
return new PageResult<>(result.getRecords(), result.getTotal(),
query.getPageNum(), query.getPageSize());
}
@Override
public List<XYKCGCCJ> getCourseProcessGrades(String xybh) {
return xykgccjMapper.selectByStudentId(xybh);
public PageResult<XYKCGCCJ> pageCourseProcessGrades(PageQuery query, String xybh, Integer nd) {
String studentId = xybh;
if (jwglRoleHelper.isStudent()) {
studentId = jwglRoleHelper.requireStudentId();
}
Page<XYKCGCCJ> page = new Page<>(query.getPageNum(), query.getPageSize());
Page<XYKCGCCJ> result = xykgccjMapper.selectPageByCondition(page, studentId, nd);
return new PageResult<>(result.getRecords(), result.getTotal(),
query.getPageNum(), query.getPageSize());
}
// ========== Excel 导出 ==========
@@ -409,6 +438,22 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
return value != null && !value.isEmpty();
}
private void denyStudentWrite() {
if (jwglRoleHelper.isStudent()) {
throw new ServiceException("学员无权修改学籍档案", FORBIDDEN);
}
}
private void assertStudentOwn(String studentId) {
if (!jwglRoleHelper.isStudent()) {
return;
}
String ownId = jwglRoleHelper.requireStudentId();
if (studentId == null || !ownId.equals(studentId)) {
throw new ServiceException("学员只能查看本人数据", FORBIDDEN);
}
}
// ========== 学员学籍预警条件管理 ==========
@Override
@@ -460,20 +505,26 @@ public class StudentRecordsServiceImpl implements StudentRecordsService {
@Override
public XYXJYJJGB getWarningResultById(String bh) {
return xyxjyjjgbMapper.selectById(bh);
XYXJYJJGB result = xyxjyjjgbMapper.selectById(bh);
if (result != null && jwglRoleHelper.isStudent()) {
assertStudentOwn(result.getXybh());
}
return result;
}
@Override
public PageResult<XYXJYJJGB> pageWarningResult(PageQuery query, XYXJYJJGB cond) {
XYXJYJJGB filter = cond == null ? new XYXJYJJGB() : cond;
if (jwglRoleHelper.isStudent()) {
filter.setXybh(jwglRoleHelper.requireStudentId());
}
Page<XYXJYJJGB> page = new Page<>(query.getPageNum(), query.getPageSize());
LambdaQueryWrapper<XYXJYJJGB> wrapper = new LambdaQueryWrapper<>();
if (cond != null) {
wrapper.eq(isNotBlank(cond.getBh()), XYXJYJJGB::getBh, cond.getBh());
wrapper.eq(cond.getNd() != null, XYXJYJJGB::getNd, cond.getNd());
wrapper.eq(isNotBlank(cond.getYjtjbh()), XYXJYJJGB::getYjtjbh, cond.getYjtjbh());
wrapper.eq(isNotBlank(cond.getXybh()), XYXJYJJGB::getXybh, cond.getXybh());
wrapper.eq(cond.getFb() != null, XYXJYJJGB::getFb, cond.getFb());
}
wrapper.eq(isNotBlank(filter.getBh()), XYXJYJJGB::getBh, filter.getBh());
wrapper.eq(filter.getNd() != null, XYXJYJJGB::getNd, filter.getNd());
wrapper.eq(isNotBlank(filter.getYjtjbh()), XYXJYJJGB::getYjtjbh, filter.getYjtjbh());
wrapper.eq(isNotBlank(filter.getXybh()), XYXJYJJGB::getXybh, filter.getXybh());
wrapper.eq(filter.getFb() != null, XYXJYJJGB::getFb, filter.getFb());
wrapper.orderByDesc(XYXJYJJGB::getCjsj);
Page<XYXJYJJGB> result = xyxjyjjgbMapper.selectPage(page, wrapper);
return new PageResult<>(result.getRecords(), result.getTotal(),