前端代码

This commit is contained in:
liumengyu
2026-08-21 18:42:51 +08:00
parent 054947482f
commit 04e06a9c9a
762 changed files with 62992 additions and 0 deletions
@@ -0,0 +1,203 @@
package com.roomroot.jwgl.interceptor;
import com.roomroot.jwgl.unit.Result;
import com.roomroot.jwgl.utils.JwglRoleHelper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import tools.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* 按角色限制教务接口访问范围。管理员放行全部。
*/
@Component
public class JwglApiAccessInterceptor implements HandlerInterceptor {
private final JwglRoleHelper roleHelper;
private final ObjectMapper objectMapper;
public JwglApiAccessInterceptor(JwglRoleHelper roleHelper, ObjectMapper objectMapper) {
this.roleHelper = roleHelper;
this.objectMapper = objectMapper;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
return true;
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()
|| "anonymousUser".equals(String.valueOf(authentication.getPrincipal()))) {
return true;
}
if (roleHelper.isAdmin()) {
return true;
}
String path = request.getRequestURI();
String context = request.getContextPath();
if (context != null && !context.isEmpty() && path.startsWith(context)) {
path = path.substring(context.length());
}
if (path.isEmpty()) {
path = "/";
}
if (roleHelper.isStudent()) {
if (isStudentAllowed(path, request.getMethod())) {
return true;
}
return deny(response, "学员无权访问该功能");
}
if (roleHelper.isTeacher()) {
if (isTeacherDenied(path)) {
return deny(response, "教员无权访问该功能");
}
if (isTeacherAdjustDenied(path, request.getMethod())) {
return deny(response, "教员只能提交、查看和撤销本人的调课申请");
}
return true;
}
if (roleHelper.isResearchOffice()) {
if (isOfficeDenied(path)) {
return deny(response, "教研室无权访问系统管理功能");
}
if (isResearchOfficeAdjustDenied(path)) {
return deny(response, "教研室仅可查看和审批本室调课申请");
}
return true;
}
if (roleHelper.isDepartmentPersonnel()) {
if (isOfficeDenied(path)) {
return deny(response, "机关人员无权访问系统管理功能");
}
if (isOfficeAdjustDenied(path, request.getMethod())) {
return deny(response, "机关人员仅可查看和审批调课申请");
}
return true;
}
return true;
}
private boolean isStudentAllowed(String path, String method) {
if (startsWithAny(path, "/getInfo", "/getRouters", "/logout", "/system/user/profile")) {
return true;
}
if (!HttpMethod.GET.matches(method)) {
return false;
}
return startsWithAny(path,
"/xqxlb",
"/kcb",
"/studentTeamOutputSchedule",
"/classCalendar",
"/course-running/plan/list",
"/course-running/plan/detail",
"/course-running/plan/export",
"/student-records/warning-result",
"/student-records/get",
"/student-records/list",
"/student-records/grades",
"/student-records/process-grades");
}
private boolean isTeacherAdjustDenied(String path, String method) {
if (!path.startsWith("/course-running/adjust")) {
return false;
}
if (path.startsWith("/course-running/adjust/audit")
|| path.startsWith("/course-running/adjust/receive")) {
return true;
}
if (path.equals("/course-running/adjust/submit")) {
return !HttpMethod.POST.matches(method);
}
return false;
}
private boolean isResearchOfficeAdjustDenied(String path) {
if (!path.startsWith("/course-running/adjust")) {
return false;
}
if (path.equals("/course-running/adjust/submit")
|| path.equals("/course-running/adjust/cancel")
|| path.startsWith("/course-running/adjust/lessons")
|| path.startsWith("/course-running/adjust/audit/jg")
|| path.startsWith("/course-running/adjust/audit/jxx")
|| path.startsWith("/course-running/adjust/receive/jg")) {
return true;
}
return false;
}
private boolean isOfficeAdjustDenied(String path, String method) {
if (!path.startsWith("/course-running/adjust")) {
return false;
}
if (HttpMethod.GET.matches(method)) {
return path.startsWith("/course-running/adjust/lessons")
|| path.startsWith("/course-running/adjust/strategy");
}
return !(path.startsWith("/course-running/adjust/audit/jg")
|| path.startsWith("/course-running/adjust/receive/jg"));
}
private boolean isTeacherDenied(String path) {
return startsWithAny(path,
"/faculty",
"/jys",
"/elective",
"/department",
"/department-personnel",
"/account-management",
"/system-initialization",
"/system/user",
"/system/role",
"/system/menu",
"/system/dept",
"/system/post",
"/monitor",
"/tool")
&& !path.startsWith("/system/user/profile");
}
private boolean isOfficeDenied(String path) {
return startsWithAny(path,
"/account-management",
"/system-initialization",
"/system/user",
"/system/role",
"/system/menu",
"/system/dept",
"/system/post",
"/monitor",
"/tool")
&& !path.startsWith("/system/user/profile");
}
private boolean startsWithAny(String path, String... prefixes) {
for (String prefix : prefixes) {
if (path.equals(prefix) || path.startsWith(prefix + "/") || path.startsWith(prefix + "?")) {
return true;
}
}
return false;
}
private boolean deny(HttpServletResponse response, String message) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(objectMapper.writeValueAsString(Result.forbidden(message)));
return false;
}
}
@@ -0,0 +1,19 @@
package com.roomroot.jwgl.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.roomroot.jwgl.entity.JYSDLB;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* 教研室登录表 Mapper。
*/
@Mapper
public interface JYSDLBMapper extends BaseMapper<JYSDLB> {
@Select("SELECT TRIM(b.\"教研室代号\") FROM \"教研室登录表\" b "
+ "JOIN \"登录信息表\" a ON TRIM(a.\"编号\") = TRIM(b.\"登录信息编号\") "
+ "WHERE TRIM(a.\"账号\") = #{username}")
String selectResearchOfficeIdByAccount(@Param("username") String username);
}
@@ -0,0 +1,181 @@
package com.roomroot.jwgl.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.jwgl.entity.JYB;
import com.roomroot.jwgl.entity.XYXX;
import com.roomroot.jwgl.mapper.JYBMapper;
import com.roomroot.jwgl.mapper.JYSDLBMapper;
import com.roomroot.jwgl.mapper.XYXXMapper;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.List;
import static com.roomroot.jwgl.utils.AccountManagementConstants.ROLE_DEPARTMENT_PERSONNEL;
import static com.roomroot.jwgl.utils.AccountManagementConstants.ROLE_RESEARCH_OFFICE;
import static com.roomroot.jwgl.utils.AccountManagementConstants.ROLE_STUDENT;
import static com.roomroot.jwgl.utils.AccountManagementConstants.ROLE_TEACHER;
import static com.roomroot.jwgl.utils.BasicManagementConstants.FORBIDDEN;
/**
* 教务角色识别与本人数据范围。
* <p>管理员、机关人员(教务部)看全部;教员看本人;学员看本人。</p>
*/
@Component
public class JwglRoleHelper {
@Resource
private JYBMapper jybMapper;
@Resource
private XYXXMapper xyxxMapper;
@Resource
private JYSDLBMapper jysdlbMapper;
public boolean isAdmin() {
try {
if (SecurityUtils.isAdmin()) {
return true;
}
return hasRoleKey(Constants.SUPER_ADMIN);
} catch (Exception ex) {
return false;
}
}
public boolean isDepartmentPersonnel() {
return isAdmin() || hasRoleKey(ROLE_DEPARTMENT_PERSONNEL);
}
public boolean isResearchOffice() {
if (isDepartmentPersonnel()) {
return false;
}
if (hasRoleKey(ROLE_RESEARCH_OFFICE)) {
return true;
}
if (hasRoleKey(ROLE_TEACHER)) {
return false;
}
return StringUtils.isNotEmpty(findResearchOfficeId());
}
public boolean isTeacher() {
return !isDepartmentPersonnel() && !isResearchOffice() && hasRoleKey(ROLE_TEACHER);
}
public boolean isStudent() {
return !isDepartmentPersonnel() && !hasRoleKey(ROLE_TEACHER) && hasRoleKey(ROLE_STUDENT);
}
public String requireTeacherId() {
String teacherId = findTeacherId();
if (StringUtils.isEmpty(teacherId)) {
throw new ServiceException("当前登录用户不是教员,无法查看教员数据", FORBIDDEN);
}
return teacherId;
}
public String requireResearchOfficeId() {
String officeId = findResearchOfficeId();
if (StringUtils.isEmpty(officeId)) {
throw new ServiceException("当前登录用户不是教研室账号,无法审批本室申请", FORBIDDEN);
}
return officeId;
}
public String findResearchOfficeId() {
try {
String username = SecurityUtils.getUsername();
if (StringUtils.isEmpty(username) || jysdlbMapper == null) {
return null;
}
return jysdlbMapper.selectResearchOfficeIdByAccount(username);
} catch (Exception ignored) {
return null;
}
}
public String requireStudentId() {
String studentId = findStudentId();
if (StringUtils.isEmpty(studentId)) {
throw new ServiceException("当前登录用户不是学员,无法查看学员数据", FORBIDDEN);
}
return studentId;
}
public String findTeacherId() {
try {
String username = SecurityUtils.getUsername();
if (StringUtils.isNotEmpty(username)) {
String fromLogin = jybMapper.selectTeacherIdByAccount(username);
if (StringUtils.isNotEmpty(fromLogin)) {
return fromLogin.trim();
}
JYB byId = jybMapper.selectById(username);
if (byId != null) {
return byId.getJybh();
}
}
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser user = loginUser.getUser();
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();
}
}
} catch (Exception ignored) {
return null;
}
return null;
}
public String findStudentId() {
try {
String username = SecurityUtils.getUsername();
if (StringUtils.isNotEmpty(username)) {
XYXX byXh = xyxxMapper.selectOne(
new LambdaQueryWrapper<XYXX>().eq(XYXX::getXh, username));
if (byXh != null) {
return byXh.getBh();
}
XYXX byBh = xyxxMapper.selectById(username);
if (byBh != null) {
return byBh.getBh();
}
}
} catch (Exception ignored) {
return null;
}
return null;
}
private boolean hasRoleKey(String roleKey) {
try {
LoginUser loginUser = SecurityUtils.getLoginUser();
SysUser user = loginUser.getUser();
if (user == null || user.getRoles() == null || StringUtils.isEmpty(roleKey)) {
return false;
}
for (SysRole role : user.getRoles()) {
if (role != null && roleKey.equalsIgnoreCase(role.getRoleKey())) {
return true;
}
}
return false;
} catch (Exception ex) {
return false;
}
}
}
@@ -0,0 +1,52 @@
package com.roomroot.jwgl.vo.courserunning;
import lombok.Data;
/**
* 可供调课的课次,来自学员队任务表,并关联课表、课程表。
*/
@Data
public class AdjustableLessonVO {
/** 实施_课程表编号(实施_调课申请主关联) */
private String sskcbbh;
/** 原上课日期 */
private java.time.LocalDateTime rq;
/** 原节次 */
private Integer jc;
/** 学员队任务表编号 */
private String xydrwbh;
/** 课表.课编号 */
private String kbh;
/** 课程名称 */
private String kcmc;
/** 学员队编号 */
private String xydbh;
/** 学员队名称 */
private String xydmc;
/** 教员编号 */
private String jybh;
/** 课次序号 */
private Integer kcxh;
/** 教室编号 */
private String jsbh;
/** 年度 */
private Integer nd;
/** 教研室代号 */
private String jysdh;
/** 课程表编号 */
private String kcbbh;
}