Jelajahi Sumber

fast:完成登入密码加密

sakura 1 tahun lalu
induk
melakukan
9a3166b3dc
38 mengubah file dengan 1701 tambahan dan 1387 penghapusan
  1. 43 54
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/common/CommonController.java
  2. 93 0
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/ParentController.java
  3. 1 1
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/StudentController.java
  4. 7 7
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysIndexController.java
  5. 16 19
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysLoginController.java
  6. 21 36
      school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysProfileController.java
  7. 1 1
      school-in-out-admin/src/main/resources/application.yml
  8. 194 0
      school-in-out-common/src/main/java/com/schoolinout/common/utils/sign/RSAUtil.java
  9. 1 0
      school-in-out-framework/src/main/java/com/schoolinout/framework/config/SecurityConfig.java
  10. 40 59
      school-in-out-framework/src/main/java/com/schoolinout/framework/web/service/SysLoginService.java
  11. 112 0
      school-in-out-system/src/main/java/com/schoolinout/system/domain/Parent.java
  12. 34 0
      school-in-out-system/src/main/java/com/schoolinout/system/domain/ParentStudent.java
  13. 95 0
      school-in-out-system/src/main/java/com/schoolinout/system/domain/dto/ParentDto.java
  14. 9 0
      school-in-out-system/src/main/java/com/schoolinout/system/domain/vo/StudentListVo.java
  15. 63 0
      school-in-out-system/src/main/java/com/schoolinout/system/mapper/ParentMapper.java
  16. 17 0
      school-in-out-system/src/main/java/com/schoolinout/system/mapper/ParentStudentMapper.java
  17. 72 0
      school-in-out-system/src/main/java/com/schoolinout/system/service/IParentService.java
  18. 133 0
      school-in-out-system/src/main/java/com/schoolinout/system/service/impl/ParentServiceImpl.java
  19. 121 0
      school-in-out-system/src/main/resources/mapper/system/ParentMapper.xml
  20. 19 0
      school-in-out-system/src/main/resources/mapper/system/ParentStudentMapper.xml
  21. 1 0
      school-in-out-system/src/main/resources/mapper/system/StudentMapper.xml
  22. 7 0
      school-in-out-ui/src/api/login.js
  23. 44 0
      school-in-out-ui/src/api/system/parent.js
  24. 1 1
      school-in-out-ui/src/assets/icons/svg/parent-fill.svg
  25. TEMPAT SAMPAH
      school-in-out-ui/src/assets/images/a.jpg
  26. 0 1
      school-in-out-ui/src/components/DictTag/index.vue
  27. 1 1
      school-in-out-ui/src/components/TopNav/index.vue
  28. 4 4
      school-in-out-ui/src/layout/components/Navbar.vue
  29. 38 25
      school-in-out-ui/src/store/modules/user.js
  30. 11 20
      school-in-out-ui/src/utils/jsencrypt.js
  31. 71 1039
      school-in-out-ui/src/views/index.vue
  32. 0 98
      school-in-out-ui/src/views/index_v1.vue
  33. 6 5
      school-in-out-ui/src/views/login.vue
  34. 379 0
      school-in-out-ui/src/views/system/parent/index.vue
  35. 21 13
      school-in-out-ui/src/views/system/student/module/StudentInoutLog.vue
  36. 25 3
      school-in-out-ui/src/views/system/user/profile/resetPwd.vue
  37. TEMPAT SAMPAH
      uploadPath/upload/2024/01/08/1_20240108101638A001.jpg
  38. TEMPAT SAMPAH
      uploadPath/upload/2024/01/09/1_20240109130517A001.jpg

+ 43 - 54
school-in-out-admin/src/main/java/com/schoolinout/web/controller/common/CommonController.java

@@ -1,9 +1,13 @@
 package com.schoolinout.web.controller.common;
 
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import com.schoolinout.common.config.RuoYiConfig;
+import com.schoolinout.common.constant.Constants;
+import com.schoolinout.common.core.domain.AjaxResult;
+import com.schoolinout.common.utils.StringUtils;
+import com.schoolinout.common.utils.file.FileUploadUtils;
+import com.schoolinout.common.utils.file.FileUtils;
+import com.schoolinout.common.utils.sign.RSAUtil;
+import com.schoolinout.framework.config.ServerConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,43 +17,45 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
-import com.schoolinout.common.config.RuoYiConfig;
-import com.schoolinout.common.constant.Constants;
-import com.schoolinout.common.core.domain.AjaxResult;
-import com.schoolinout.common.utils.StringUtils;
-import com.schoolinout.common.utils.file.FileUploadUtils;
-import com.schoolinout.common.utils.file.FileUtils;
-import com.schoolinout.framework.config.ServerConfig;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 通用请求处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/common")
-public class CommonController
-{
+public class CommonController {
     private static final Logger log = LoggerFactory.getLogger(CommonController.class);
-
+    private static final String FILE_DELIMETER = ",";
     @Autowired
     private ServerConfig serverConfig;
 
-    private static final String FILE_DELIMETER = ",";
+    /**
+     * 获取公钥:前端用来密码加密
+     *
+     * @return
+     */
+    @GetMapping("/getPublicKey")
+    public RSAUtil.RSAKeyPair getPublicKey() {
+        return RSAUtil.rsaKeyPair();
+    }
 
     /**
      * 通用下载请求
-     * 
+     *
      * @param fileName 文件名称
-     * @param delete 是否删除
+     * @param delete   是否删除
      */
     @GetMapping("/download")
-    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(fileName))
-            {
+    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
+        try {
+            if (!FileUtils.checkAllowDownload(fileName)) {
                 throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
             }
             String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
@@ -58,13 +64,10 @@ public class CommonController
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, realFileName);
             FileUtils.writeBytes(filePath, response.getOutputStream());
-            if (delete)
-            {
+            if (delete) {
                 FileUtils.deleteFile(filePath);
             }
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }
@@ -73,10 +76,8 @@ public class CommonController
      * 通用上传请求(单个)
      */
     @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file) throws Exception
-    {
-        try
-        {
+    public AjaxResult uploadFile(MultipartFile file) throws Exception {
+        try {
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             // 上传并返回新文件名称
@@ -88,9 +89,7 @@ public class CommonController
             ajax.put("newFileName", FileUtils.getName(fileName));
             ajax.put("originalFilename", file.getOriginalFilename());
             return ajax;
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             return AjaxResult.error(e.getMessage());
         }
     }
@@ -99,18 +98,15 @@ public class CommonController
      * 通用上传请求(多个)
      */
     @PostMapping("/uploads")
-    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
-    {
-        try
-        {
+    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
+        try {
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             List<String> urls = new ArrayList<String>();
             List<String> fileNames = new ArrayList<String>();
             List<String> newFileNames = new ArrayList<String>();
             List<String> originalFilenames = new ArrayList<String>();
-            for (MultipartFile file : files)
-            {
+            for (MultipartFile file : files) {
                 // 上传并返回新文件名称
                 String fileName = FileUploadUtils.upload(filePath, file);
                 String url = serverConfig.getUrl() + fileName;
@@ -125,9 +121,7 @@ public class CommonController
             ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
             ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
             return ajax;
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             return AjaxResult.error(e.getMessage());
         }
     }
@@ -137,12 +131,9 @@ public class CommonController
      */
     @GetMapping("/download/resource")
     public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
-            throws Exception
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(resource))
-            {
+            throws Exception {
+        try {
+            if (!FileUtils.checkAllowDownload(resource)) {
                 throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
             }
             // 本地资源路径
@@ -154,9 +145,7 @@ public class CommonController
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, downloadName);
             FileUtils.writeBytes(downloadPath, response.getOutputStream());
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }

+ 93 - 0
school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/ParentController.java

@@ -0,0 +1,93 @@
+package com.schoolinout.web.controller.system;
+
+import com.schoolinout.common.annotation.Log;
+import com.schoolinout.common.core.controller.BaseController;
+import com.schoolinout.common.core.domain.AjaxResult;
+import com.schoolinout.common.core.page.TableDataInfo;
+import com.schoolinout.common.enums.BusinessType;
+import com.schoolinout.common.utils.poi.ExcelUtil;
+import com.schoolinout.system.domain.Parent;
+import com.schoolinout.system.domain.dto.ParentDto;
+import com.schoolinout.system.service.IParentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 家长管理Controller
+ *
+ * @author sakura
+ * @date 2024-01-09
+ */
+@RestController
+@RequestMapping("/system/parent")
+public class ParentController extends BaseController {
+    @Autowired
+    private IParentService parentService;
+
+    /**
+     * 查询家长管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(Parent parent) {
+        startPage();
+        List<Parent> list = parentService.selectParentList(parent);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出家长管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:export')")
+    @Log(title = "家长管理", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, Parent parent) {
+        List<Parent> list = parentService.selectParentList(parent);
+        ExcelUtil<Parent> util = new ExcelUtil<Parent>(Parent.class);
+        util.exportExcel(response, list, "家长管理数据");
+    }
+
+    /**
+     * 获取家长管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(parentService.selectParentById(id));
+    }
+
+    /**
+     * 新增家长管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:add')")
+    @Log(title = "家长管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Validated @RequestBody ParentDto parent) {
+        return toAjax(parentService.saveParent(parent));
+    }
+
+    /**
+     * 修改家长管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:edit')")
+    @Log(title = "家长管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody Parent parent) {
+        return toAjax(parentService.updateParent(parent));
+    }
+
+    /**
+     * 删除家长管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:parent:remove')")
+    @Log(title = "家长管理", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(parentService.deleteParentByIds(ids));
+    }
+}

+ 1 - 1
school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/StudentController.java

@@ -28,7 +28,7 @@ import java.util.List;
 public class StudentController extends BaseController {
     @Autowired
     private IStudentService studentService;
-
+    
     @GetMapping("/list/all")
     public AjaxResult getAll(Student student) {
         return success(studentService.listAll(student));

+ 7 - 7
school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysIndexController.java

@@ -1,10 +1,10 @@
 package com.schoolinout.web.controller.system;
 
+import com.schoolinout.common.config.RuoYiConfig;
+import com.schoolinout.common.utils.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import com.schoolinout.common.config.RuoYiConfig;
-import com.schoolinout.common.utils.StringUtils;
 
 /**
  * 首页
@@ -12,9 +12,10 @@ import com.schoolinout.common.utils.StringUtils;
  * @author ruoyi
  */
 @RestController
-public class SysIndexController
-{
-    /** 系统基础配置 */
+public class SysIndexController {
+    /**
+     * 系统基础配置
+     */
     @Autowired
     private RuoYiConfig ruoyiConfig;
 
@@ -22,8 +23,7 @@ public class SysIndexController
      * 访问首页,提示语
      */
     @RequestMapping("/")
-    public String index()
-    {
+    public String index() {
         return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
     }
 }

+ 16 - 19
school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysLoginController.java

@@ -1,12 +1,5 @@
 package com.schoolinout.web.controller.system;
 
-import java.util.List;
-import java.util.Set;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
 import com.schoolinout.common.constant.Constants;
 import com.schoolinout.common.core.domain.AjaxResult;
 import com.schoolinout.common.core.domain.entity.SysMenu;
@@ -16,15 +9,22 @@ import com.schoolinout.common.utils.SecurityUtils;
 import com.schoolinout.framework.web.service.SysLoginService;
 import com.schoolinout.framework.web.service.SysPermissionService;
 import com.schoolinout.system.service.ISysMenuService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Set;
 
 /**
  * 登录验证
- * 
+ *
  * @author ruoyi
  */
 @RestController
-public class SysLoginController
-{
+public class SysLoginController {
     @Autowired
     private SysLoginService loginService;
 
@@ -36,13 +36,12 @@ public class SysLoginController
 
     /**
      * 登录方法
-     * 
+     *
      * @param loginBody 登录信息
      * @return 结果
      */
     @PostMapping("/login")
-    public AjaxResult login(@RequestBody LoginBody loginBody)
-    {
+    public AjaxResult login(@RequestBody LoginBody loginBody) {
         AjaxResult ajax = AjaxResult.success();
         // 生成令牌
         String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
@@ -53,12 +52,11 @@ public class SysLoginController
 
     /**
      * 获取用户信息
-     * 
+     *
      * @return 用户信息
      */
     @GetMapping("getInfo")
-    public AjaxResult getInfo()
-    {
+    public AjaxResult getInfo() {
         SysUser user = SecurityUtils.getLoginUser().getUser();
         // 角色集合
         Set<String> roles = permissionService.getRolePermission(user);
@@ -73,12 +71,11 @@ public class SysLoginController
 
     /**
      * 获取路由信息
-     * 
+     *
      * @return 路由信息
      */
     @GetMapping("getRouters")
-    public AjaxResult getRouters()
-    {
+    public AjaxResult getRouters() {
         Long userId = SecurityUtils.getUserId();
         List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
         return AjaxResult.success(menuService.buildMenus(menus));

+ 21 - 36
school-in-out-admin/src/main/java/com/schoolinout/web/controller/system/SysProfileController.java

@@ -1,14 +1,5 @@
 package com.schoolinout.web.controller.system;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
 import com.schoolinout.common.annotation.Log;
 import com.schoolinout.common.config.RuoYiConfig;
 import com.schoolinout.common.core.controller.BaseController;
@@ -20,18 +11,21 @@ import com.schoolinout.common.utils.SecurityUtils;
 import com.schoolinout.common.utils.StringUtils;
 import com.schoolinout.common.utils.file.FileUploadUtils;
 import com.schoolinout.common.utils.file.MimeTypeUtils;
+import com.schoolinout.common.utils.sign.RSAUtil;
 import com.schoolinout.framework.web.service.TokenService;
 import com.schoolinout.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 个人信息 业务处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/system/user/profile")
-public class SysProfileController extends BaseController
-{
+public class SysProfileController extends BaseController {
     @Autowired
     private ISysUserService userService;
 
@@ -42,8 +36,7 @@ public class SysProfileController extends BaseController
      * 个人信息
      */
     @GetMapping
-    public AjaxResult profile()
-    {
+    public AjaxResult profile() {
         LoginUser loginUser = getLoginUser();
         SysUser user = loginUser.getUser();
         AjaxResult ajax = AjaxResult.success(user);
@@ -57,24 +50,20 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult updateProfile(@RequestBody SysUser user)
-    {
+    public AjaxResult updateProfile(@RequestBody SysUser user) {
         LoginUser loginUser = getLoginUser();
         SysUser currentUser = loginUser.getUser();
         currentUser.setNickName(user.getNickName());
         currentUser.setEmail(user.getEmail());
         currentUser.setPhonenumber(user.getPhonenumber());
         currentUser.setSex(user.getSex());
-        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
-        {
+        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser)) {
             return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
         }
-        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
-        {
+        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser)) {
             return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
         }
-        if (userService.updateUserProfile(currentUser) > 0)
-        {
+        if (userService.updateUserProfile(currentUser) > 0) {
             // 更新缓存用户信息
             tokenService.setLoginUser(loginUser);
             return success();
@@ -87,22 +76,21 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PutMapping("/updatePwd")
-    public AjaxResult updatePwd(String oldPassword, String newPassword)
-    {
+    public AjaxResult updatePwd(String oldPassword, String newPassword) throws Exception {
         LoginUser loginUser = getLoginUser();
         String userName = loginUser.getUsername();
         String password = loginUser.getPassword();
-        if (!SecurityUtils.matchesPassword(oldPassword, password))
-        {
+        //解密
+        oldPassword = RSAUtil.decryptByPrivateKey(oldPassword);
+        newPassword = RSAUtil.decryptByPrivateKey(newPassword);
+        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
             return error("修改密码失败,旧密码错误");
         }
-        if (SecurityUtils.matchesPassword(newPassword, password))
-        {
+        if (SecurityUtils.matchesPassword(newPassword, password)) {
             return error("新密码不能与旧密码相同");
         }
         newPassword = SecurityUtils.encryptPassword(newPassword);
-        if (userService.resetUserPwd(userName, newPassword) > 0)
-        {
+        if (userService.resetUserPwd(userName, newPassword) > 0) {
             // 更新缓存用户密码
             loginUser.getUser().setPassword(newPassword);
             tokenService.setLoginUser(loginUser);
@@ -116,14 +104,11 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "用户头像", businessType = BusinessType.UPDATE)
     @PostMapping("/avatar")
-    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
-    {
-        if (!file.isEmpty())
-        {
+    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
+        if (!file.isEmpty()) {
             LoginUser loginUser = getLoginUser();
             String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
-            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
-            {
+            if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
                 AjaxResult ajax = AjaxResult.success();
                 ajax.put("imgUrl", avatar);
                 // 更新缓存用户头像

+ 1 - 1
school-in-out-admin/src/main/resources/application.yml

@@ -34,7 +34,7 @@ server:
 # 日志配置
 logging:
   level:
-    com.schoolinout: info
+    com.schoolinout: debug
     org.springframework: debug
 
 # 用户配置

+ 194 - 0
school-in-out-common/src/main/java/com/schoolinout/common/utils/sign/RSAUtil.java

@@ -0,0 +1,194 @@
+package com.schoolinout.common.utils.sign;
+
+import org.apache.commons.codec.binary.Base64;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.Cipher;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+@Component
+public class RSAUtil {
+    private static final RSAKeyPair rsaKeyPair = new RSAKeyPair();
+    // Rsa 私钥 也可固定秘钥对 若依原写法(不安全)
+    public static String privateKeys = "";
+    private static String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+nZS3z0N7Yv6++/BpqK\n" +
+            "ee0x+G3G0p3YcQPw0twfGAfH1FPsj69QF9nm/UjjEaqzgzSM8ScaSo6eziXoeqJL\n" +
+            "VhknA9LknIEuMc+zEftjEpGv+7TPQeaKnw/toh9tYR5ItT1MIimqj/rGc9cPZeBy\n" +
+            "lKnZ+yiGKoMVOTQmiVaORHYjV6Syg8sIkfGyWLb5BSvfOv+TOdjlP2+H0yj1r9oT\n" +
+            "k67ZV9plpfTCCEa+xb1tgcSuWBwCpRR5AjlMU7uH18a1cyXV++7NRhmZd/Jd9KB+\n" +
+            "WNbS1MtpIyqSlvyPFzpQvPTPxCV2TFb+uqDTX4WIBJNFDRUJe8JjTEjlf+AF5yCD\n" +
+            "7QIDAQAB";
+    private static String privateKeyStr = "MIIEowIBAAKCAQEAt+nZS3z0N7Yv6++/BpqKee0x+G3G0p3YcQPw0twfGAfH1FPs\n" +
+            "j69QF9nm/UjjEaqzgzSM8ScaSo6eziXoeqJLVhknA9LknIEuMc+zEftjEpGv+7TP\n" +
+            "QeaKnw/toh9tYR5ItT1MIimqj/rGc9cPZeBylKnZ+yiGKoMVOTQmiVaORHYjV6Sy\n" +
+            "g8sIkfGyWLb5BSvfOv+TOdjlP2+H0yj1r9oTk67ZV9plpfTCCEa+xb1tgcSuWBwC\n" +
+            "pRR5AjlMU7uH18a1cyXV++7NRhmZd/Jd9KB+WNbS1MtpIyqSlvyPFzpQvPTPxCV2\n" +
+            "TFb+uqDTX4WIBJNFDRUJe8JjTEjlf+AF5yCD7QIDAQABAoIBAAI+uIhTXifP8YXP\n" +
+            "x2UtPcN/Qbzmmia4Boxan/Xy+e4xKh9NZvXaDgA8iLVOznbIvqg7W/0VnRyL4SRj\n" +
+            "EhNtJ75FUFSbnm7KpOW2w1jU2MDBRoSsEFudlNOcPipcd9lXpUuRE/zWxV48kW+Y\n" +
+            "kHeN5dgqup52QC0ErJ2mJVJH3DS5tyRg5icvhGW92FcJWszrf8oKN94RBe7t9vn8\n" +
+            "kx/sVzzCfQNIBAKtZzcpbBmO0ZaWy6vgpQ6UUo0AEbW4S3OS8wXotELMw+dfWOne\n" +
+            "6bZX2vX5ANJCpJOaybYFLmX1llAyCFte8gQ4weVlUGpZ05vb5R7dfMqRQxy7P5+/\n" +
+            "odXdO4ECgYEA6sEkFCAwAMyaTjTl8OhKc0K8CNZKnaJ19zqFUHyQGRwkFWBuWw4m\n" +
+            "aErZgsZxOyWlJE5K00VAi0gt2IY7ZHR3I0bL/V5j6BBcD6PdqZpakaCyhikTdYFO\n" +
+            "5Y2folt1I6ZVl5hkO8Q9aP5ncNsf8ip7ALuNNmg3ah26xS9Hns80DVcCgYEAyI7P\n" +
+            "Kyl4mpFsfC2DpNMvRlt2IVZ4hRF8y33nITN1xFrUcDNAv33A8eEQB9f2tb/XIshv\n" +
+            "mySBpZ+bOaFWzauAqPBHO1WIwAu9cmYOcBxU3g3pzi+64kXmxmDB6Ssih2XfCuv6\n" +
+            "YnppjBYTr2yjraHu/lCyLKilUN0o5HnLGIjcqlsCgYBNxOQ94pfke+OWiwGt+FZJ\n" +
+            "rs76InufkyV/XJyzmEBogSEXD9YfRiXFIR7Dqxfx3zvBNkqliOij+6psc7OTSN37\n" +
+            "CsYjTrTMOTc2WzPgrujYG6NovIzcvZS0iWFb+O5qe/0Y9nwmLJGnibgc9Aq2QAp1\n" +
+            "qKxUXNwWxHiOQGZ6nuwAiwKBgGNN4uJaPG88Rl0OJDq+no/VxZ4oNLCewg34HzNf\n" +
+            "SZaZ6spLdmnamGirqcZYdr3zaVC9shU9dDxP1QoqCtL3clMz9fE5HucIaRt10PxN\n" +
+            "6u+wL+55z60uM2BSlHEhfI1SMag0w9tzBUPpwoF/52OX5MBjsHVQY9qwRwkqDRfu\n" +
+            "3GQ1AoGBAM5j3geg4MwU/7Uxd/zG4Jv800RZwLxoAj8yj++sDQaTwooZxuwBL91t\n" +
+            "6hKmDlpOMMGsK/BS/2IO7CRxM9RB8dvNhU5/YrfszsKfJ/Fcs7XNcAQn6uqMOJAx\n" +
+            "lZd4FKpkpCcJQDkeh9unIQzxwDabXG6BMaxyWLLhSdRJEmSBjmPJ";
+
+    /**
+     * 私钥解密
+     *
+     * @param text 待解密的文本
+     * @return 解密后的文本
+     */
+    public static String decryptByPrivateKey(String text) throws Exception {
+        return decryptByPrivateKey(rsaKeyPair.getPrivateKey(), text);
+    }
+
+    /**
+     * 公钥解密
+     *
+     * @param publicKeyString 公钥
+     * @param text            待解密的信息
+     * @return 解密后的文本
+     */
+    public static String decryptByPublicKey(String publicKeyString, String text) throws Exception {
+        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, publicKey);
+        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
+        return new String(result);
+    }
+
+    /**
+     * 私钥加密
+     *
+     * @param privateKeyString 私钥
+     * @param text             待加密的信息
+     * @return 加密后的文本
+     */
+    public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception {
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+        byte[] result = cipher.doFinal(text.getBytes());
+        return Base64.encodeBase64String(result);
+    }
+
+    /**
+     * 私钥解密
+     *
+     * @param privateKeyString 私钥
+     * @param text             待解密的文本
+     * @return 解密后的文本
+     */
+    public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception {
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, privateKey);
+        byte[] result = cipher.doFinal(Base64.decodeBase64(text));
+        return new String(result);
+    }
+
+    /**
+     * 公钥加密
+     *
+     * @param publicKeyString 公钥
+     * @param text            待加密的文本
+     * @return 加密后的文本
+     */
+    public static String encryptByPublicKey(String publicKeyString, String text) throws Exception {
+        X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        byte[] result = cipher.doFinal(text.getBytes());
+        return Base64.encodeBase64String(result);
+    }
+
+    public static String getPublicKey() {
+        return publicKeyStr;
+    }
+
+    public static String getPrivateKey() {
+        return privateKeyStr;
+    }
+
+    public static RSAKeyPair rsaKeyPair() {
+        return rsaKeyPair;
+    }
+
+    /**
+     * 构建RSA密钥对
+     *
+     * @return 生成后的公私钥信息
+     */
+    @Bean
+    public void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(1024);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
+        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
+        String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
+        String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
+        rsaKeyPair.setPrivateKey(privateKeyString);
+        rsaKeyPair.setPublicKey(publicKeyString);
+        publicKeyStr = publicKeyString;
+        privateKeyStr = privateKeyString;
+    }
+
+    /**
+     * RSA密钥对对象
+     */
+    public static class RSAKeyPair {
+        private String publicKey;
+        private String privateKey;
+
+        public RSAKeyPair() {
+
+        }
+
+        public RSAKeyPair(String publicKey, String privateKey) {
+            this.publicKey = publicKey;
+            this.privateKey = privateKey;
+        }
+
+        public String getPublicKey() {
+            return publicKey;
+        }
+
+        public void setPublicKey(String publicKey) {
+            this.publicKey = publicKey;
+        }
+
+        public String getPrivateKey() {
+            return privateKey;
+        }
+
+        public void setPrivateKey(String privateKey) {
+            this.privateKey = privateKey;
+        }
+    }
+}

+ 1 - 0
school-in-out-framework/src/main/java/com/schoolinout/framework/config/SecurityConfig.java

@@ -112,6 +112,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**", "/doc.html", "/v3/api-docs/**").permitAll()
+                .antMatchers("/common/getPublicKey").permitAll()
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()
                 .and()

+ 40 - 59
school-in-out-framework/src/main/java/com/schoolinout/framework/web/service/SysLoginService.java

@@ -1,12 +1,5 @@
 package com.schoolinout.framework.web.service;
 
-import javax.annotation.Resource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.stereotype.Component;
 import com.schoolinout.common.constant.CacheConstants;
 import com.schoolinout.common.constant.Constants;
 import com.schoolinout.common.constant.UserConstants;
@@ -14,29 +7,33 @@ import com.schoolinout.common.core.domain.entity.SysUser;
 import com.schoolinout.common.core.domain.model.LoginUser;
 import com.schoolinout.common.core.redis.RedisCache;
 import com.schoolinout.common.exception.ServiceException;
-import com.schoolinout.common.exception.user.BlackListException;
-import com.schoolinout.common.exception.user.CaptchaException;
-import com.schoolinout.common.exception.user.CaptchaExpireException;
-import com.schoolinout.common.exception.user.UserNotExistsException;
-import com.schoolinout.common.exception.user.UserPasswordNotMatchException;
+import com.schoolinout.common.exception.user.*;
 import com.schoolinout.common.utils.DateUtils;
 import com.schoolinout.common.utils.MessageUtils;
 import com.schoolinout.common.utils.StringUtils;
 import com.schoolinout.common.utils.ip.IpUtils;
+import com.schoolinout.common.utils.sign.RSAUtil;
 import com.schoolinout.framework.manager.AsyncManager;
 import com.schoolinout.framework.manager.factory.AsyncFactory;
 import com.schoolinout.framework.security.context.AuthenticationContextHolder;
 import com.schoolinout.system.service.ISysConfigService;
 import com.schoolinout.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
 
 /**
  * 登录校验方法
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class SysLoginService
-{
+public class SysLoginService {
     @Autowired
     private TokenService tokenService;
 
@@ -45,7 +42,7 @@ public class SysLoginService
 
     @Autowired
     private RedisCache redisCache;
-    
+
     @Autowired
     private ISysUserService userService;
 
@@ -54,43 +51,36 @@ public class SysLoginService
 
     /**
      * 登录验证
-     * 
+     *
      * @param username 用户名
      * @param password 密码
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public String login(String username, String password, String code, String uuid)
-    {
+    public String login(String username, String password, String code, String uuid) {
         // 验证码校验
         validateCaptcha(username, code, uuid);
-        // 登录前置校验
-        loginPreCheck(username, password);
+
         // 用户验证
         Authentication authentication = null;
-        try
-        {
+        try {
+            password = RSAUtil.decryptByPrivateKey(password);
+            // 登录前置校验
+            loginPreCheck(username, password);
             UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
             AuthenticationContextHolder.setContext(authenticationToken);
             // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
             authentication = authenticationManager.authenticate(authenticationToken);
-        }
-        catch (Exception e)
-        {
-            if (e instanceof BadCredentialsException)
-            {
+        } catch (Exception e) {
+            if (e instanceof BadCredentialsException) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                 throw new UserPasswordNotMatchException();
-            }
-            else
-            {
+            } else {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                 throw new ServiceException(e.getMessage());
             }
-        }
-        finally
-        {
+        } finally {
             AuthenticationContextHolder.clearContext();
         }
         AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
@@ -102,27 +92,23 @@ public class SysLoginService
 
     /**
      * 校验验证码
-     * 
+     *
      * @param username 用户名
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public void validateCaptcha(String username, String code, String uuid)
-    {
+    public void validateCaptcha(String username, String code, String uuid) {
         boolean captchaEnabled = configService.selectCaptchaEnabled();
-        if (captchaEnabled)
-        {
+        if (captchaEnabled) {
             String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
             String captcha = redisCache.getCacheObject(verifyKey);
             redisCache.deleteObject(verifyKey);
-            if (captcha == null)
-            {
+            if (captcha == null) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
                 throw new CaptchaExpireException();
             }
-            if (!code.equalsIgnoreCase(captcha))
-            {
+            if (!code.equalsIgnoreCase(captcha)) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                 throw new CaptchaException();
             }
@@ -131,35 +117,31 @@ public class SysLoginService
 
     /**
      * 登录前置校验
+     *
      * @param username 用户名
      * @param password 用户密码
      */
-    public void loginPreCheck(String username, String password)
-    {
+    public void loginPreCheck(String username, String password) {
         // 用户名或密码为空 错误
-        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
-        {
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
             throw new UserNotExistsException();
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
-                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
-        {
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
             throw new UserPasswordNotMatchException();
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
-                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
-        {
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
             throw new UserPasswordNotMatchException();
         }
         // IP黑名单校验
         String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
-        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
-        {
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
             throw new BlackListException();
         }
@@ -170,8 +152,7 @@ public class SysLoginService
      *
      * @param userId 用户ID
      */
-    public void recordLoginInfo(Long userId)
-    {
+    public void recordLoginInfo(Long userId) {
         SysUser sysUser = new SysUser();
         sysUser.setUserId(userId);
         sysUser.setLoginIp(IpUtils.getIpAddr());

+ 112 - 0
school-in-out-system/src/main/java/com/schoolinout/system/domain/Parent.java

@@ -0,0 +1,112 @@
+package com.schoolinout.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.schoolinout.common.annotation.Excel;
+import com.schoolinout.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 家长管理对象 tb_school_parent
+ *
+ * @author sakura
+ * @date 2024-01-09
+ */
+public class Parent extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    private Long id;
+
+    @TableField(exist = false)
+    private String studentIds;
+
+
+    /**
+     * 家长姓名
+     */
+    @Excel(name = "家长姓名")
+    private String parentName;
+
+    /**
+     * 家长电话
+     */
+    @Excel(name = "家长电话")
+    private String parentPhone;
+
+    /**
+     * 与学生的关系
+     */
+    @Excel(name = "与学生的关系")
+    private String relation;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getStudentIds() {
+        return studentIds;
+    }
+
+    public void setStudentIds(String studentIds) {
+        this.studentIds = studentIds;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public String getParentPhone() {
+        return parentPhone;
+    }
+
+    public void setParentPhone(String parentPhone) {
+        this.parentPhone = parentPhone;
+    }
+
+    public String getRelation() {
+        return relation;
+    }
+
+    public void setRelation(String relation) {
+        this.relation = relation;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("id", getId())
+                .append("parentName", getParentName())
+                .append("parentPhone", getParentPhone())
+                .append("relation", getRelation())
+                .append("delFlag", getDelFlag())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .toString();
+    }
+}

+ 34 - 0
school-in-out-system/src/main/java/com/schoolinout/system/domain/ParentStudent.java

@@ -0,0 +1,34 @@
+package com.schoolinout.system.domain;
+
+/**
+ * @author sakura
+ * @date 2024/1/9 11:11:14 Tue
+ */
+public class ParentStudent {
+    private Long studentId;
+    private Long parentId;
+
+    public ParentStudent() {
+    }
+
+    public ParentStudent(Long studentId, Long parentId) {
+        this.studentId = studentId;
+        this.parentId = parentId;
+    }
+
+    public Long getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(Long studentId) {
+        this.studentId = studentId;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+}

+ 95 - 0
school-in-out-system/src/main/java/com/schoolinout/system/domain/dto/ParentDto.java

@@ -0,0 +1,95 @@
+package com.schoolinout.system.domain.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.util.List;
+
+/**
+ * @author sakura
+ * @date 2024/1/9 10:10:44 Tue
+ */
+@Schema(name = "新增家长请求参数实体")
+public class ParentDto {
+
+    @Schema(description = "家长id")
+    private Long id;
+
+    @Schema(description = "绑定学生列表")
+    @NotNull(message = "学生不能为空")
+    private List<Long> studentIds;
+
+    /**
+     * 家长姓名
+     */
+    @Schema(description = "家长姓名")
+    @NotBlank(message = "姓名不能为空")
+    private String parentName;
+
+    /**
+     * 家长电话
+     */
+    @Schema(description = "家长电话")
+    @NotNull(message = "家长电话不能为空")
+    @Pattern(regexp = "^1[34578]\\d{9}$", message = "家长电话格式不正确")
+    private String parentPhone;
+
+    /**
+     * 与学生的关系
+     */
+    @Schema(description = "与学生的关系")
+    @NotBlank(message = "关系不能为空")
+    private String relation;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String toString() {
+        return "AddParentDto{" +
+                "studentIds=" + studentIds +
+                ", parentName='" + parentName + '\'' +
+                ", parentPhone='" + parentPhone + '\'' +
+                ", relation='" + relation + '\'' +
+                '}';
+    }
+
+    public List<Long> getStudentIds() {
+        return studentIds;
+    }
+
+    public void setStudentIds(List<Long> studentIds) {
+        this.studentIds = studentIds;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public String getParentPhone() {
+        return parentPhone;
+    }
+
+    public void setParentPhone(String parentPhone) {
+        this.parentPhone = parentPhone;
+    }
+
+    public String getRelation() {
+        return relation;
+    }
+
+    public void setRelation(String relation) {
+        this.relation = relation;
+    }
+}

+ 9 - 0
school-in-out-system/src/main/java/com/schoolinout/system/domain/vo/StudentListVo.java

@@ -6,6 +6,7 @@ package com.schoolinout.system.domain.vo;
  */
 public class StudentListVo {
 
+    private Long id;
     private String className;
     private String schoolName;
     private String studentName;
@@ -25,6 +26,14 @@ public class StudentListVo {
      */
     private String studentNum;
 
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
     public String getClassName() {
         return className;
     }

+ 63 - 0
school-in-out-system/src/main/java/com/schoolinout/system/mapper/ParentMapper.java

@@ -0,0 +1,63 @@
+package com.schoolinout.system.mapper;
+
+import com.schoolinout.system.domain.Parent;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 家长管理Mapper接口
+ *
+ * @author sakura
+ * @date 2024-01-09
+ */
+@Mapper
+public interface ParentMapper {
+    /**
+     * 查询家长管理
+     *
+     * @param id 家长管理主键
+     * @return 家长管理
+     */
+    public Parent selectParentById(Long id);
+
+    /**
+     * 查询家长管理列表
+     *
+     * @param parent 家长管理
+     * @return 家长管理集合
+     */
+    public List<Parent> selectParentList(Parent parent);
+
+    /**
+     * 新增家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    public int insertParent(Parent parent);
+
+    /**
+     * 修改家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    public int updateParent(Parent parent);
+
+    /**
+     * 删除家长管理
+     *
+     * @param id 家长管理主键
+     * @return 结果
+     */
+    public int deleteParentById(Long id);
+
+    /**
+     * 批量删除家长管理
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteParentByIds(Long[] ids);
+}

+ 17 - 0
school-in-out-system/src/main/java/com/schoolinout/system/mapper/ParentStudentMapper.java

@@ -0,0 +1,17 @@
+package com.schoolinout.system.mapper;
+
+import com.schoolinout.system.domain.ParentStudent;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author sakura
+ * @date 2024/1/9 11:11:14 Tue
+ */
+@Mapper
+public interface ParentStudentMapper {
+    public int insertBatch(List<ParentStudent> list);
+
+    public int delateByParentId(Long id);
+}

+ 72 - 0
school-in-out-system/src/main/java/com/schoolinout/system/service/IParentService.java

@@ -0,0 +1,72 @@
+package com.schoolinout.system.service;
+
+import com.schoolinout.system.domain.Parent;
+import com.schoolinout.system.domain.dto.ParentDto;
+
+import java.util.List;
+
+/**
+ * 家长管理Service接口
+ *
+ * @author sakura
+ * @date 2024-01-09
+ */
+public interface IParentService {
+
+
+    /**
+     * 查询家长管理
+     *
+     * @param id 家长管理主键
+     * @return 家长管理
+     */
+    public Parent selectParentById(Long id);
+
+    /**
+     * 查询家长管理列表
+     *
+     * @param parent 家长管理
+     * @return 家长管理集合
+     */
+    public List<Parent> selectParentList(Parent parent);
+
+    /**
+     * 新增家长
+     *
+     * @param dto 新增数据
+     * @return 结果
+     */
+    public int saveParent(ParentDto dto);
+
+    /**
+     * 新增家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    public int insertParent(Parent parent);
+
+    /**
+     * 修改家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    public int updateParent(Parent parent);
+
+    /**
+     * 批量删除家长管理
+     *
+     * @param ids 需要删除的家长管理主键集合
+     * @return 结果
+     */
+    public int deleteParentByIds(Long[] ids);
+
+    /**
+     * 删除家长管理信息
+     *
+     * @param id 家长管理主键
+     * @return 结果
+     */
+    public int deleteParentById(Long id);
+}

+ 133 - 0
school-in-out-system/src/main/java/com/schoolinout/system/service/impl/ParentServiceImpl.java

@@ -0,0 +1,133 @@
+package com.schoolinout.system.service.impl;
+
+import com.schoolinout.common.utils.DateUtils;
+import com.schoolinout.common.utils.bean.BeanUtils;
+import com.schoolinout.system.domain.Parent;
+import com.schoolinout.system.domain.ParentStudent;
+import com.schoolinout.system.domain.dto.ParentDto;
+import com.schoolinout.system.mapper.ParentMapper;
+import com.schoolinout.system.mapper.ParentStudentMapper;
+import com.schoolinout.system.service.IParentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 家长管理Service业务层处理
+ *
+ * @author sakura
+ * @date 2024-01-09
+ */
+@Service
+public class ParentServiceImpl implements IParentService {
+    @Autowired
+    private ParentMapper parentMapper;
+    @Autowired
+    private ParentStudentMapper parentStudentMapper;
+
+    /**
+     * 查询家长管理
+     *
+     * @param id 家长管理主键
+     * @return 家长管理
+     */
+    @Override
+    public Parent selectParentById(Long id) {
+        return parentMapper.selectParentById(id);
+    }
+
+    /**
+     * 查询家长管理列表
+     *
+     * @param parent 家长管理
+     * @return 家长管理
+     */
+    @Override
+    public List<Parent> selectParentList(Parent parent) {
+        return parentMapper.selectParentList(parent);
+    }
+
+    @Override
+    @Transactional(rollbackFor = RuntimeException.class)
+    public int saveParent(ParentDto dto) {
+        int count = 0;
+        // 一共要保存两个
+        if (dto.getId() == null) {
+            // 新增
+            // step1:先保存家长
+            Parent parent = new Parent();
+            BeanUtils.copyBeanProp(parent, dto);
+            count += parentMapper.insertParent(parent);
+
+            // step2:再保存对应的关系列表
+            List<ParentStudent> parentStudentList = dto.getStudentIds().stream()
+                    .map(item -> new ParentStudent(item, parent.getId()))
+                    .collect(Collectors.toList());
+            count += parentStudentMapper.insertBatch(parentStudentList);
+        } else {
+            // 修改
+            Parent parent = new Parent();
+            BeanUtils.copyBeanProp(parent, dto);
+            count += parentMapper.updateParent(parent);
+            // 更新对应的关系列表
+            // 删除所有
+            count += parentStudentMapper.delateByParentId(dto.getId());
+            // 更新回去
+            List<ParentStudent> parentStudentList = dto.getStudentIds().stream()
+                    .map(item -> new ParentStudent(item, parent.getId()))
+                    .collect(Collectors.toList());
+            count += parentStudentMapper.insertBatch(parentStudentList);
+        }
+
+        return count;
+    }
+
+    /**
+     * 新增家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    @Override
+    public int insertParent(Parent parent) {
+        parent.setCreateTime(DateUtils.getNowDate());
+        return parentMapper.insertParent(parent);
+    }
+
+    /**
+     * 修改家长管理
+     *
+     * @param parent 家长管理
+     * @return 结果
+     */
+    @Override
+    public int updateParent(Parent parent) {
+        parent.setUpdateTime(DateUtils.getNowDate());
+        return parentMapper.updateParent(parent);
+    }
+
+    /**
+     * 批量删除家长管理
+     *
+     * @param ids 需要删除的家长管理主键
+     * @return 结果
+     */
+    @Override
+    public int deleteParentByIds(Long[] ids) {
+        return parentMapper.deleteParentByIds(ids);
+    }
+
+    /**
+     * 删除家长管理信息
+     *
+     * @param id 家长管理主键
+     * @return 结果
+     */
+    @Override
+    public int deleteParentById(Long id) {
+        return parentMapper.deleteParentById(id);
+    }
+}

+ 121 - 0
school-in-out-system/src/main/resources/mapper/system/ParentMapper.xml

@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.schoolinout.system.mapper.ParentMapper">
+
+    <resultMap type="Parent" id="ParentResult">
+        <result property="id" column="id"/>
+        <result property="parentName" column="parent_name"/>
+        <result property="parentPhone" column="parent_phone"/>
+        <result property="studentIds" column="student_ids"/>
+        <result property="relation" column="relation"/>
+        <result property="delFlag" column="del_flag"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <sql id="selectParentVo">
+        select id,
+               parent_name,
+               parent_phone,
+               relation,
+               del_flag,
+               create_by,
+               create_time,
+               update_by,
+               update_time
+        from tb_school_parent
+    </sql>
+
+    <select id="selectParentList" parameterType="Parent" resultMap="ParentResult">
+        select p.id,
+        p.parent_name,
+        p.parent_phone,
+        p.relation,
+        p.del_flag,
+        p.create_by,
+        p.create_time,
+        p.update_by,
+        p.update_time,
+        GROUP_CONCAT(sp.student_id SEPARATOR ',') AS student_ids
+        from tb_school_parent p
+        LEFT JOIN tb_school_student_parent_relation sp ON p.id = sp.parent_id
+        <where>
+            <if test="parentName != null  and parentName != ''">and parent_name like concat('%', #{parentName}, '%')
+            </if>
+            <if test="parentPhone != null  and parentPhone != ''">and parent_phone = #{parentPhone}</if>
+            <if test="relation != null  and relation != ''">and relation = #{relation}</if>
+        </where>
+    </select>
+
+    <select id="selectParentById" parameterType="Long" resultMap="ParentResult">
+        select p.id,
+               p.parent_name,
+               p.parent_phone,
+               p.relation,
+               p.del_flag,
+               p.create_by,
+               p.create_time,
+               p.update_by,
+               p.update_time,
+               GROUP_CONCAT(sp.student_id SEPARATOR ',') AS student_ids
+        from tb_school_parent p
+                 LEFT JOIN tb_school_student_parent_relation sp ON p.id = sp.parent_id
+        where p.id = #{id}
+    </select>
+
+    <insert id="insertParent" parameterType="Parent" useGeneratedKeys="true" keyProperty="id">
+        insert into tb_school_parent
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="parentName != null and parentName != ''">parent_name,</if>
+            <if test="parentPhone != null and parentPhone != ''">parent_phone,</if>
+            <if test="relation != null and relation != ''">relation,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="parentName != null and parentName != ''">#{parentName},</if>
+            <if test="parentPhone != null and parentPhone != ''">#{parentPhone},</if>
+            <if test="relation != null and relation != ''">#{relation},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+        </trim>
+    </insert>
+
+    <update id="updateParent" parameterType="Parent">
+        update tb_school_parent
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="parentName != null and parentName != ''">parent_name = #{parentName},</if>
+            <if test="parentPhone != null and parentPhone != ''">parent_phone = #{parentPhone},</if>
+            <if test="relation != null and relation != ''">relation = #{relation},</if>
+            <if test="delFlag != null">del_flag = #{delFlag},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteParentById" parameterType="Long">
+        delete
+        from tb_school_parent
+        where id = #{id}
+    </delete>
+
+    <delete id="deleteParentByIds" parameterType="String">
+        delete from tb_school_parent where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 19 - 0
school-in-out-system/src/main/resources/mapper/system/ParentStudentMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.schoolinout.system.mapper.ParentStudentMapper">
+
+    <insert id="insertBatch" parameterType="ParentStudent" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO tb_school_student_parent_relation (student_id, parent_id)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.studentId}, #{item.parentId})
+        </foreach>
+    </insert>
+    <delete id="delateByParentId">
+        DELETE
+        FROM tb_school_student_parent_relation
+        WHERE parent_id = #{parentId}
+    </delete>
+</mapper>

+ 1 - 0
school-in-out-system/src/main/resources/mapper/system/StudentMapper.xml

@@ -55,6 +55,7 @@
     </select>
     <select id="selectStudentListAll" resultType="com.schoolinout.system.domain.vo.StudentListVo">
         SELECT
+        student.id,
         student.student_name,
         student.student_pic,
         student.student_gender,

+ 7 - 0
school-in-out-ui/src/api/login.js

@@ -1,5 +1,12 @@
 import request from '@/utils/request'
 
+// 获取公钥
+export function getPublicKey() {
+  return request({
+    url: '/common/getPublicKey',
+    method: 'get',
+  })
+}
 // 登录方法
 export function login(username, password, code, uuid) {
   const data = {

+ 44 - 0
school-in-out-ui/src/api/system/parent.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询家长管理列表
+export function listParent(query) {
+  return request({
+    url: '/system/parent/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询家长管理详细
+export function getParent(id) {
+  return request({
+    url: '/system/parent/' + id,
+    method: 'get'
+  })
+}
+
+// 新增家长管理
+export function addParent(data) {
+  return request({
+    url: '/system/parent',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改家长管理
+export function updateParent(data) {
+  return request({
+    url: '/system/parent',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除家长管理
+export function delParent(id) {
+  return request({
+    url: '/system/parent/' + id,
+    method: 'delete'
+  })
+}

+ 1 - 1
school-in-out-ui/src/assets/icons/svg/parent-fill.svg

@@ -1 +1 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1704252786493" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6911" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M298.666667 469.333333a192 192 0 1 1 0-384 192 192 0 0 1 0 384z m448 170.666667a170.666667 170.666667 0 1 1 0-341.333333 170.666667 170.666667 0 0 1 0 341.333333z m0 42.666667a192 192 0 0 1 192 192v21.333333h-384v-21.333333a192 192 0 0 1 192-192zM298.666667 512a213.333333 213.333333 0 0 1 213.333333 213.333333v170.666667H85.333333v-170.666667a213.333333 213.333333 0 0 1 213.333334-213.333333z" p-id="6912"></path></svg>
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1704778327614" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4259" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M298.666667 469.333333a192 192 0 1 1 0-384 192 192 0 0 1 0 384z m448 170.666667a170.666667 170.666667 0 1 1 0-341.333333 170.666667 170.666667 0 0 1 0 341.333333z m0 42.666667a192 192 0 0 1 192 192v21.333333h-384v-21.333333a192 192 0 0 1 192-192zM298.666667 512a213.333333 213.333333 0 0 1 213.333333 213.333333v170.666667H85.333333v-170.666667a213.333333 213.333333 0 0 1 213.333334-213.333333z" p-id="4260" fill="#ffffff"></path></svg>

TEMPAT SAMPAH
school-in-out-ui/src/assets/images/a.jpg


+ 0 - 1
school-in-out-ui/src/components/DictTag/index.vue

@@ -56,7 +56,6 @@ export default {
   computed: {
     values() {
       if (this.value === null || typeof this.value === 'undefined' || this.value === '') return []
-
       return Array.isArray(this.value) ? this.value.map(item => '' + item) : String(this.value).split(this.separator)
     },
     unmatch() {

+ 1 - 1
school-in-out-ui/src/components/TopNav/index.vue

@@ -9,7 +9,7 @@
         <svg-icon
         v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
         :icon-class="item.meta.icon"/>
-        {{ item.meta.title }}
+        {{ item.meta.title }} 
       </el-menu-item>
     </template>
 

+ 4 - 4
school-in-out-ui/src/layout/components/Navbar.vue

@@ -7,17 +7,17 @@
 
     <div class="right-menu">
       <template v-if="device!=='mobile'">
-        <search id="header-search" class="right-menu-item" />
+        <!-- <search id="header-search" class="right-menu-item" /> -->
 
-        <el-tooltip content="源码地址" effect="dark" placement="bottom">
+        <!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
           <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
         </el-tooltip>
 
         <el-tooltip content="文档地址" effect="dark" placement="bottom">
           <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
-        </el-tooltip>
+        </el-tooltip> -->
 
-        <screenfull id="screenfull" class="right-menu-item hover-effect" />
+        <!-- <screenfull id="screenfull" class="right-menu-item hover-effect" /> -->
 
         <el-tooltip content="布局大小" effect="dark" placement="bottom">
           <size-select id="size-select" class="right-menu-item hover-effect" />

+ 38 - 25
school-in-out-ui/src/store/modules/user.js

@@ -1,23 +1,20 @@
-import { login, logout, getInfo } from '@/api/login'
 import { getToken, setToken, removeToken } from '@/utils/auth'
-
+import { login, logout, getInfo, getPublicKey } from '@/api/login'
+import {encrypt} from "../../utils/jsencrypt";
+ 
 const user = {
   state: {
     token: getToken(),
-    id: '',
     name: '',
     avatar: '',
     roles: [],
     permissions: []
   },
-
+ 
   mutations: {
     SET_TOKEN: (state, token) => {
       state.token = token
     },
-    SET_ID: (state, id) => {
-      state.id = id
-    },
     SET_NAME: (state, name) => {
       state.name = name
     },
@@ -31,25 +28,42 @@ const user = {
       state.permissions = permissions
     }
   },
-
+ 
   actions: {
+    getPublicKey() {
+      return new Promise((resolve, reject) => {
+        getPublicKey()
+          .then(res => {
+            resolve(res)
+          })
+          .catch(error => {
+            reject(error)
+          })
+      })
+    },
     // 登录
-    Login({ commit }, userInfo) {
-      const username = userInfo.username.trim()
-      const password = userInfo.password
-      const code = userInfo.code
-      const uuid = userInfo.uuid
+    Login({ commit, dispatch }, userInfo) {
       return new Promise((resolve, reject) => {
-        login(username, password, code, uuid).then(res => {
-          setToken(res.token)
-          commit('SET_TOKEN', res.token)
-          resolve()
-        }).catch(error => {
-          reject(error)
+        dispatch('getPublicKey').then(res => {
+          let publicKey = res.publicKey
+          const username = userInfo.username.trim()
+          //调用加密方法(传密码和公钥)
+          const password = encrypt(userInfo.password, publicKey)
+          const code = userInfo.code
+          const uuid = userInfo.uuid
+          login(username, password, code, uuid)
+            .then(res => {
+              setToken(res.token)
+              commit('SET_TOKEN', res.token)
+              resolve()
+            })
+            .catch(error => {
+              reject(error)
+            })
         })
       })
     },
-
+ 
     // 获取用户信息
     GetInfo({ commit, state }) {
       return new Promise((resolve, reject) => {
@@ -62,7 +76,6 @@ const user = {
           } else {
             commit('SET_ROLES', ['ROLE_DEFAULT'])
           }
-          commit('SET_ID', user.userId)
           commit('SET_NAME', user.userName)
           commit('SET_AVATAR', avatar)
           resolve(res)
@@ -71,7 +84,7 @@ const user = {
         })
       })
     },
-
+ 
     // 退出系统
     LogOut({ commit, state }) {
       return new Promise((resolve, reject) => {
@@ -86,7 +99,7 @@ const user = {
         })
       })
     },
-
+ 
     // 前端 登出
     FedLogOut({ commit }) {
       return new Promise(resolve => {
@@ -97,5 +110,5 @@ const user = {
     }
   }
 }
-
-export default user
+ 
+export default user;

+ 11 - 20
school-in-out-ui/src/utils/jsencrypt.js

@@ -1,30 +1,21 @@
 import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
-
+ 
 // 密钥对生成 http://web.chacuo.net/netrsakeypair
-
-const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
-  'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
-
-const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
-  '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
-  'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
-  'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
-  'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
-  'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
-  'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
-  'UP8iWi1Qw0Y='
-
+ 
+//这里注掉了原来固定的公私钥
+//const publicKey = ''
+//const privateKey = ''
+ 
 // 加密
-export function encrypt(txt) {
+export function encrypt(txt, publicKey) {
   const encryptor = new JSEncrypt()
   encryptor.setPublicKey(publicKey) // 设置公钥
-  return encryptor.encrypt(txt) // 对数据进行加密
+  return encryptor.encrypt(txt) // 对数据
 }
-
-// 解密
+ 
+// 解密(暂无使用)
 export function decrypt(txt) {
   const encryptor = new JSEncrypt()
   encryptor.setPrivateKey(privateKey) // 设置私钥
   return encryptor.decrypt(txt) // 对数据进行解密
-}
-
+}

+ 71 - 1039
school-in-out-ui/src/views/index.vue

@@ -1,1066 +1,98 @@
 <template>
-  <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="24">
-        <blockquote class="text-warning" style="font-size: 14px">
-          领取阿里云通用云产品1888优惠券
-          <br />
-          <el-link
-            href="https://www.aliyun.com/minisite/goods?userCode=brki8iof"
-            type="primary"
-            target="_blank"
-            >https://www.aliyun.com/minisite/goods?userCode=brki8iof</el-link
-          >
-          <br />
-          领取腾讯云通用云产品2860优惠券
-          <br />
-          <el-link
-            href="https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console"
-            type="primary"
-            target="_blank"
-            >https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console</el-link
-          >
-          <br />
-          阿里云服务器折扣区
-          <el-link href="http://aly.ruoyi.vip" type="primary" target="_blank"
-            >>☛☛点我进入☚☚</el-link
-          >
-          &nbsp;&nbsp;&nbsp; 腾讯云服务器秒杀区
-          <el-link href="http://txy.ruoyi.vip" type="primary" target="_blank"
-            >>☛☛点我进入☚☚</el-link
-          ><br />
-          <h4 class="text-danger">
-            云产品通用红包,可叠加官网常规优惠使用。(仅限新用户)
-          </h4>
-        </blockquote>
+  <div class="dashboard-editor-container">
 
-        <hr />
-      </el-col>
-    </el-row>
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>若依后台管理框架</h2>
-        <p>
-          一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
-        </p>
-        <p>
-          <b>当前版本:</b> <span>v{{ version }}</span>
-        </p>
-        <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button
-            type="primary"
-            size="mini"
-            icon="el-icon-cloudy"
-            plain
-            @click="goTarget('https://gitee.com/y_project/RuoYi-Vue')"
-            >访问码云</el-button
-          >
-          <el-button
-            size="mini"
-            icon="el-icon-s-home"
-            plain
-            @click="goTarget('http://ruoyi.vip')"
-            >访问主页</el-button
-          >
-        </p>
-      </el-col>
+    <panel-group @handleSetLineChartData="handleSetLineChartData" />
 
-      <el-col :sm="24" :lg="12" style="padding-left: 50px">
-        <el-row>
-          <el-col :span="12">
-            <h2>技术选型</h2>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="6">
-            <h4>后端技术</h4>
-            <ul>
-              <li>SpringBoot</li>
-              <li>Spring Security</li>
-              <li>JWT</li>
-              <li>MyBatis</li>
-              <li>Druid</li>
-              <li>Fastjson</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-          <el-col :span="6">
-            <h4>前端技术</h4>
-            <ul>
-              <li>Vue</li>
-              <li>Vuex</li>
-              <li>Element-ui</li>
-              <li>Axios</li>
-              <li>Sass</li>
-              <li>Quill</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-        </el-row>
-      </el-col>
+    <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
+      <line-chart :chart-data="lineChartData" />
     </el-row>
-    <el-divider />
-    <el-row :gutter="20">
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <div slot="header" class="clearfix">
-            <span>联系信息</span>
-          </div>
-          <div class="body">
-            <p>
-              <i class="el-icon-s-promotion"></i> 官网:<el-link
-                href="http://www.ruoyi.vip"
-                target="_blank"
-                >http://www.ruoyi.vip</el-link
-              >
-            </p>
-            <p>
-              <i class="el-icon-user-solid"></i> QQ群:<s> 满937441 </s> <s> 满887144332 </s>
-              <s> 满180251782 </s> <s> 满104180207 </s> <s> 满186866453 </s> <s> 满201396349 </s>
-              <s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s> 
-              <s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s> 
-              <s> 满101046199 </s> <s> 满136919097 </s> <s> 满143961921 </s> <s> 满174951577 </s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Lj0nHRAPD5CZv1jTOciuxXVloBJLS2Lp&authKey=Q2RxC6%2Ffxney9yOGBY0sDJxFhX9b7o1FRY1bsESmkbcZ4PFt6Vx92FpVo9O1u9p4&noverify=0&group_code=161281055" target="_blank">161281055</a>
-            </p>
-            <p>
-              <i class="el-icon-chat-dot-round"></i> 微信:<a
-                href="javascript:;"
-                >/ *若依</a
-              >
-            </p>
-            <p>
-              <i class="el-icon-money"></i> 支付宝:<a
-                href="javascript:;"
-                class="支付宝信息"
-                >/ *若依</a
-              >
-            </p>
-          </div>
-        </el-card>
-      </el-col>
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <div slot="header" class="clearfix">
-            <span>更新日志</span>
-          </div>
-          <el-collapse accordion>
-            <el-collapse-item title="v3.8.7 - 2023-12-08">
-              <ol>
-                <li>操作日志记录部门名称</li>
-                <li>全局数据存储用户编号</li>
-                <li>新增编程式判断资源访问权限</li>
-                <li>操作日志列表新增IP地址查询</li>
-                <li>定时任务新增页去除状态选项</li>
-                <li>代码生成支持选择前端模板类型</li>
-                <li>显隐列组件支持复选框弹出类型</li>
-                <li>通用排序属性orderBy参数限制长度</li>
-                <li>Excel自定义数据处理器增加单元格/工作簿对象</li>
-                <li>升级oshi到最新版本6.4.8</li>
-                <li>升级druid到最新版本1.2.20</li>
-                <li>升级fastjson到最新版2.0.43</li>
-                <li>升级pagehelper到最新版1.4.7</li>
-                <li>升级commons.io到最新版本2.13.0</li>
-                <li>升级element-ui到最新版本2.15.14</li>
-                <li>修复五级路由缓存无效问题</li>
-                <li>修复外链带端口出现的异常</li>
-                <li>修复树模板父级编码变量错误</li>
-                <li>修复字典表详情页面搜索问题</li>
-                <li>修复内链iframe没有传递参数问题</li>
-                <li>修复自定义字典样式不生效的问题</li>
-                <li>修复字典缓存删除方法参数错误问题</li>
-                <li>修复Excel导入数据临时文件无法删除问题</li>
-                <li>修复未登录带参数访问成功后参数丢失问题</li>
-                <li>修复HeaderSearch组件跳转query参数丢失问题</li>
-                <li>修复代码生成导入后必填项与数据库不匹配问题</li>
-                <li>修复Excels导入时无法获取到dictType字典值问题</li>
-                <li>优化下载zip方法新增遮罩层</li>
-                <li>优化头像上传参数新增文件名称</li>
-                <li>优化字典标签支持自定义分隔符</li>
-                <li>优化菜单管理类型为按钮状态可选</li>
-                <li>优化前端防重复提交数据大小限制</li>
-                <li>优化TopNav菜单没有图标svg不显示</li>
-                <li>优化数字金额大写转换精度丢失问题</li>
-                <li>优化富文本Editor组件检验图片格式</li>
-                <li>优化页签在Firefox浏览器被遮挡的问题</li>
-                <li>优化个人中心/基本资料修改时数据显示问题</li>
-                <li>优化缓存监控图表支持跟随屏幕大小自适应调整</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.6 - 2023-06-30">
-              <ol>
-                <li>支持登录IP黑名单限制</li>
-                <li>新增监控页面图标显示</li>
-                <li>操作日志新增消耗时间属性</li>
-                <li>屏蔽定时任务bean违规的字符</li>
-                <li>日志管理使用索引提升查询性能</li>
-                <li>日志注解支持排除指定的请求参数</li>
-                <li>支持自定义隐藏属性列过滤子对象</li>
-                <li>升级oshi到最新版本6.4.3</li>
-                <li>升级druid到最新版本1.2.16</li>
-                <li>升级fastjson到最新版2.0.34</li>
-                <li>升级spring-boot到最新版本2.5.15</li>
-                <li>升级element-ui到最新版本2.15.13</li>
-                <li>移除apache/commons-fileupload依赖</li>
-                <li>修复页面切换时布局错乱的问题</li>
-                <li>修复匿名注解Anonymous空指针问题</li>
-                <li>修复路由跳转被阻止时内部产生报错信息问题</li>
-                <li>修复isMatchedIp的参数判断产生空指针的问题</li>
-                <li>修复用户多角色数据权限可能出现权限抬升的情况</li>
-                <li>修复开启TopNav后一级菜单路由参数设置无效问题</li>
-                <li>修复DictTag组件value没有匹配的值时则展示value</li>
-                <li>优化文件下载出现的异常</li>
-                <li>优化选择图标组件高亮回显</li>
-                <li>优化弹窗后导航栏偏移的问题</li>
-                <li>优化修改密码日志存储明文问题</li>
-                <li>优化页签栏关闭其他出现的异常问题</li>
-                <li>优化页签关闭左侧选项排除首页选项</li>
-                <li>优化关闭当前tab页跳转最右侧tab页</li>
-                <li>优化缓存列表清除操作提示不变的问题</li>
-                <li>优化字符未使用下划线不进行驼峰式处理</li>
-                <li>优化用户导入更新时需获取用户编号问题</li>
-                <li>优化侧边栏的平台标题与VUE_APP_TITLE保持同步</li>
-                <li>优化导出Excel时设置dictType属性重复查缓存问题</li>
-                <li>连接池Druid支持新的配置connectTimeout和socketTimeout</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.5 - 2023-01-01">
-              <ol>
-                <li>定时任务违规的字符</li>
-                <li>重置时取消部门选中</li>
-                <li>新增返回警告消息提示</li>
-                <li>忽略不必要的属性数据返回</li>
-                <li>修改参数键名时移除前缓存配置</li>
-                <li>导入更新用户数据前校验数据权限</li>
-                <li>兼容Excel下拉框内容过多无法显示的问题</li>
-                <li>升级echarts到最新版本5.4.0</li>
-                <li>升级core-js到最新版本3.25.3</li>
-                <li>升级oshi到最新版本6.4.0</li>
-                <li>升级kaptcha到最新版2.3.3</li>
-                <li>升级druid到最新版本1.2.15</li>
-                <li>升级fastjson到最新版2.0.20</li>
-                <li>升级pagehelper到最新版1.4.6</li>
-                <li>优化弹窗内容过多展示不全问题</li>
-                <li>优化swagger-ui静态资源使用缓存</li>
-                <li>开启TopNav没有子菜单隐藏侧边栏</li>
-                <li>删除fuse无效选项maxPatternLength</li>
-                <li>优化导出对象的子列表为空会出现[]问题</li>
-                <li>优化编辑头像时透明部分会变成黑色问题</li>
-                <li>优化小屏幕上修改头像界面布局错位的问题</li>
-                <li>修复代码生成勾选属性无效问题</li>
-                <li>修复文件上传组件格式验证问题</li>
-                <li>修复回显数据字典数组异常问题</li>
-                <li>修复sheet超出最大行数异常问题</li>
-                <li>修复Log注解GET请求记录不到参数问题</li>
-                <li>修复调度日志点击多次数据不变化的问题</li>
-                <li>修复主题颜色在Drawer组件不会加载问题</li>
-                <li>修复文件名包含特殊字符的文件无法下载问题</li>
-                <li>修复table中更多按钮切换主题色未生效修复问题</li>
-                <li>修复某些特性的环境生成代码变乱码TXT文件问题</li>
-                <li>修复代码生成图片/文件/单选时选择必填无法校验问题</li>
-                <li>修复某些特性的情况用户编辑对话框中角色和部门无法修改问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.4 - 2022-09-26">
-              <ol>
-                <li>数据逻辑删除不进行唯一验证</li>
-                <li>Excel注解支持导出对象的子列表方法</li>
-                <li>Excel注解支持自定义隐藏属性列</li>
-                <li>Excel注解支持backgroundColor属性设置背景色</li>
-                <li>支持配置密码最大错误次数/锁定时间</li>
-                <li>登录日志新增解锁账户功能</li>
-                <li>通用下载方法新增config配置选项</li>
-                <li>支持多权限字符匹配角色数据权限</li>
-                <li>页面内嵌iframe切换tab不刷新数据</li>
-                <li>操作日志记录支持排除敏感属性字段</li>
-                <li>修复多文件上传报错出现的异常问题</li>
-                <li>修复图片预览组件src属性为null值控制台报错问题</li>
-                <li>升级oshi到最新版本6.2.2</li>
-                <li>升级fastjson到最新版2.0.14</li>
-                <li>升级pagehelper到最新版1.4.3</li>
-                <li>升级core-js到最新版本3.25.2</li>
-                <li>升级element-ui到最新版本2.15.10</li>
-                <li>优化任务过期不执行调度</li>
-                <li>优化字典数据使用store存取</li>
-                <li>优化修改资料头像被覆盖的问题</li>
-                <li>优化修改用户登录账号重复验证</li>
-                <li>优化代码生成同步后值NULL问题</li>
-                <li>优化定时任务支持执行父类方法</li>
-                <li>优化用户个人信息接口防止修改部门</li>
-                <li>优化布局设置使用el-drawer抽屉显示</li>
-                <li>优化没有权限的用户编辑部门缺少数据</li>
-                <li>优化日志注解记录限制请求地址的长度</li>
-                <li>优化excel/scale属性导出单元格数值类型</li>
-                <li>优化日志操作中重置按钮时重复查询的问题</li>
-                <li>优化多个相同角色数据导致权限SQL重复问题</li>
-                <li>优化表格上右侧工具条(搜索按钮显隐&右侧样式凸出)</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.3 - 2022-06-27">
-              <ol>
-                <li>新增缓存列表菜单功能</li>
-                <li>代码生成树表新增(展开/折叠)</li>
-                <li>Excel注解支持color字体颜色</li>
-                <li>新增Anonymous匿名访问不鉴权注解</li>
-                <li>用户头像上传限制只能为图片格式</li>
-                <li>接口使用泛型使其看到响应属性字段</li>
-                <li>检查定时任务bean所在包名是否为白名单配置</li>
-                <li>添加页签openPage支持传递参数</li>
-                <li>用户缓存信息添加部门ancestors祖级列表</li>
-                <li>升级element-ui到最新版本2.15.8</li>
-                <li>升级oshi到最新版本6.1.6</li>
-                <li>升级druid到最新版本1.2.11</li>
-                <li>升级fastjson到最新版2.0.8</li>
-                <li>升级spring-boot到最新版本2.5.14</li>
-                <li>降级jsencrypt版本兼容IE浏览器</li>
-                <li>删除多余的salt字段</li>
-                <li>新增获取不带后缀文件名称方法</li>
-                <li>新增获取配置文件中的属性值方法</li>
-                <li>新增内容编码/解码方便插件集成使用</li>
-                <li>字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)</li>
-                <li>优化设置分页参数默认值</li>
-                <li>优化对空字符串参数处理的过滤</li>
-                <li>优化显示顺序orderNum类型为整型</li>
-                <li>优化表单构建按钮不显示正则校验</li>
-                <li>优化字典数据回显样式下拉框显示值</li>
-                <li>优化R响应成功状态码与全局保持一致</li>
-                <li>优化druid开启wall过滤器出现的异常问题</li>
-                <li>优化用户管理左侧树型组件增加选中高亮保持</li>
-                <li>优化新增用户与角色信息&用户与岗位信息逻辑</li>
-                <li>优化默认不启用压缩文件缓存防止node_modules过大</li>
-                <li>修复字典数据显示不全问题</li>
-                <li>修复操作日志查询类型条件为0时会查到所有数据</li>
-                <li>修复Excel注解prompt/combo同时使用不生效问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.2 - 2022-04-01">
-              <ol>
-                <li>前端支持设置是否需要防止数据重复提交</li>
-                <li>开启TopNav没有子菜单情况隐藏侧边栏</li>
-                <li>侧边栏菜单名称过长悬停显示标题</li>
-                <li>用户访问控制时校验数据权限,防止越权</li>
-                <li>导出Excel时屏蔽公式,防止CSV注入风险</li>
-                <li>组件ImagePreview支持多图预览显示</li>
-                <li>组件ImageUpload支持多图同时选择上传</li>
-                <li>组件FileUpload支持多文件同时选择上传</li>
-                <li>服务监控新增运行参数信息显示</li>
-                <li>定时任务目标字符串过滤特殊字符</li>
-                <li>定时任务目标字符串验证包名白名单</li>
-                <li>代码生成列表图片支持预览</li>
-                <li>代码生成编辑修改打开新页签</li>
-                <li>代码生成新增Java类型Boolean</li>
-                <li>代码生成子表支持日期/字典配置</li>
-                <li>代码生成同步保留必填/类型选项</li>
-                <li>升级oshi到最新版本6.1.2</li>
-                <li>升级fastjson到最新版1.2.80</li>
-                <li>升级pagehelper到最新版1.4.1</li>
-                <li>升级spring-boot到最新版本2.5.11</li>
-                <li>升级spring-boot-mybatis到最新版2.2.2</li>
-                <li>添加遗漏的分页参数合理化属性</li>
-                <li>修改npm即将过期的注册源地址</li>
-                <li>修复分页组件请求两次问题</li>
-                <li>修复通用文件下载接口跨域问题</li>
-                <li>修复Xss注解字段值为空时的异常问题</li>
-                <li>修复选项卡点击右键刷新丢失参数问题</li>
-                <li>修复表单清除元素位置未垂直居中问题</li>
-                <li>修复服务监控中运行参数显示条件错误</li>
-                <li>修复导入Excel时字典字段类型为Long转义为空问题</li>
-                <li>修复登录超时刷新页面跳转登录页面还提示重新登录问题</li>
-                <li>优化加载字典缓存数据</li>
-                <li>优化IP地址获取到多个的问题</li>
-                <li>优化任务队列满时任务拒绝策略</li>
-                <li>优化文件上传兼容Weblogic环境</li>
-                <li>优化定时任务默认保存到内存中执行</li>
-                <li>优化部门修改缩放后出现的错位问题</li>
-                <li>优化Excel格式化不同类型的日期对象</li>
-                <li>优化菜单表关键字导致的插件报错问题</li>
-                <li>优化Oracle用户头像列为空时不显示问题</li>
-                <li>优化页面若未匹配到字典标签则返回原字典值</li>
-                <li>优化修复登录失效后多次请求提示多次弹窗问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.1 - 2022-01-01">
-              <ol>
-                <li>新增Vue3前端代码生成模板</li>
-                <li>新增图片预览组件</li>
-                <li>新增压缩插件实现打包Gzip</li>
-                <li>自定义xss校验注解实现</li>
-                <li>自定义文字复制剪贴指令</li>
-                <li>代码生成预览支持复制内容</li>
-                <li>路由支持单独配置菜单或角色权限</li>
-                <li>用户管理部门查询选择节点后分页参数初始</li>
-                <li>修复用户分配角色属性错误</li>
-                <li>修复打包后字体图标偶现的乱码问题</li>
-                <li>修复菜单管理重置表单出现的错误</li>
-                <li>修复版本差异导致的懒加载报错问题</li>
-                <li>修复Cron组件中周回显问题</li>
-                <li>修复定时任务多参数逗号分隔的问题</li>
-                <li>修复根据ID查询列表可能出现的主键溢出问题</li>
-                <li>修复tomcat配置参数已过期问题</li>
-                <li>升级clipboard到最新版本2.0.8</li>
-                <li>升级oshi到最新版本v5.8.6</li>
-                <li>升级fastjson到最新版1.2.79</li>
-                <li>升级spring-boot到最新版本2.5.8</li>
-                <li>升级log4j2到2.17.1,防止漏洞风险</li>
-                <li>优化下载解析blob异常提示</li>
-                <li>优化代码生成字典组重复问题</li>
-                <li>优化查询用户的角色组&岗位组代码</li>
-                <li>优化定时任务cron表达式小时设置24</li>
-                <li>优化用户导入提示溢出则显示滚动条</li>
-                <li>优化防重复提交标识组合为(key+url+header)</li>
-                <li>优化分页方法设置成通用方便灵活调用</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.0 - 2021-12-01">
-              <ol>
-                <li>新增配套并同步的Vue3前端版本</li>
-                <li>新增通用方法简化模态/缓存/下载/权限/页签使用</li>
-                <li>优化导出数据/使用通用下载方法</li>
-                <li>Excel注解支持自定义数据处理器</li>
-                <li>Excel注解支持导入导出标题信息</li>
-                <li>Excel导入支持@Excels注解</li>
-                <li>新增组件data-dict,简化数据字典使用</li>
-                <li>新增Jaxb依赖,防止jdk8以上出现的兼容错误</li>
-                <li>生产环境使用路由懒加载提升页面响应速度</li>
-                <li>修复五级以上菜单出现的404问题</li>
-                <li>防重提交注解支持配置间隔时间/提示消息</li>
-                <li>日志注解新增是否保存响应参数</li>
-                <li>任务屏蔽违规字符&参数忽略双引号中的逗号</li>
-                <li>升级SpringBoot到最新版本2.5.6</li>
-                <li>升级pagehelper到最新版1.4.0</li>
-                <li>升级spring-boot-mybatis到最新版2.2.0</li>
-                <li>升级oshi到最新版本v5.8.2</li>
-                <li>升级druid到最新版1.2.8</li>
-                <li>升级velocity到最新版本2.3</li>
-                <li>升级fastjson到最新版1.2.78</li>
-                <li>升级axios到最新版本0.24.0</li>
-                <li>升级dart-sass到版本1.32.13</li>
-                <li>升级core-js到最新版本3.19.1</li>
-                <li>升级jsencrypt到最新版本3.2.1</li>
-                <li>升级js-cookie到最新版本3.0.1</li>
-                <li>升级file-saver到最新版本2.0.5</li>
-                <li>升级sass-loader到最新版本10.1.1</li>
-                <li>升级element-ui到最新版本2.15.6</li>
-                <li>新增sendGet无参请求方法</li>
-                <li>禁用el-tag组件的渐变动画</li>
-                <li>代码生成点击预览重置激活tab</li>
-                <li>AjaxResult重写put方法,以方便链式调用</li>
-                <li>优化登录/验证码请求headers不设置token</li>
-                <li>优化用户个人信息接口防止修改用户名</li>
-                <li>优化Cron表达式生成器关闭时销毁避免缓存</li>
-                <li>优化注册成功提示消息类型success</li>
-                <li>优化aop语法,使用spring自动注入注解</li>
-                <li>优化记录登录信息,移除不必要的修改</li>
-                <li>优化mybatis全局默认的执行器</li>
-                <li>优化Excel导入图片可能出现的异常</li>
-                <li>修复代码生成模板主子表删除缺少事务</li>
-                <li>修复日志记录可能出现的转换异常</li>
-                <li>修复代码生成复选框字典遗漏问题</li>
-                <li>修复关闭xss功能导致可重复读RepeatableFilter失效</li>
-                <li>修复字符串无法被反转义问题</li>
-                <li>修复后端主子表代码模板方法名生成错误问题</li>
-                <li>修复xss过滤后格式出现的异常</li>
-                <li>修复swagger没有指定dataTypeClass导致启动出现warn日志</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.7.0 - 2021-09-13">
-              <ol>
-                <li>参数管理支持配置验证码开关</li>
-                <li>新增是否开启用户注册功能</li>
-                <li>定时任务支持在线生成cron表达式</li>
-                <li>菜单管理支持配置路由参数</li>
-                <li>支持自定义注解实现接口限流</li>
-                <li>Excel注解支持Image图片导入</li>
-                <li>自定义弹层溢出滚动样式</li>
-                <li>自定义可拖动弹窗宽度指令</li>
-                <li>自定义可拖动弹窗高度指令</li>
-                <li>修复任意账户越权问题</li>
-                <li>修改时检查用户数据权限范围</li>
-                <li>修复保存配置主题颜色失效问题</li>
-                <li>新增暗色菜单风格主题</li>
-                <li>菜单&部门新增展开/折叠功能</li>
-                <li>页签新增关闭左侧&添加图标</li>
-                <li>顶部菜单排除隐藏的默认路由</li>
-                <li>顶部菜单同步系统主题样式</li>
-                <li>跳转路由高亮相对应的菜单栏</li>
-                <li>代码生成主子表多选行数据</li>
-                <li>日期范围支持添加多组</li>
-                <li>升级element-ui到最新版本2.15.5</li>
-                <li>升级oshi到最新版本v5.8.0</li>
-                <li>升级commons.io到最新版本v2.11.0</li>
-                <li>定时任务屏蔽ldap远程调用</li>
-                <li>定时任务屏蔽http(s)远程调用</li>
-                <li>补充定时任务表字段注释</li>
-                <li>定时任务对检查异常进行事务回滚</li>
-                <li>启用父部门状态排除顶级节点</li>
-                <li>富文本新增上传文件大小限制</li>
-                <li>默认首页使用keep-alive缓存</li>
-                <li>修改代码生成字典回显样式</li>
-                <li>自定义分页合理化传入参数</li>
-                <li>修复字典组件值为整形不显示问题</li>
-                <li>修复定时任务日志执行状态显示</li>
-                <li>角色&菜单新增字段属性提示信息</li>
-                <li>修复角色分配用户页面参数类型错误提醒</li>
-                <li>优化布局设置动画特效</li>
-                <li>优化异常处理信息</li>
-                <li>优化错误token导致的解析异常</li>
-                <li>密码框新增显示切换密码图标</li>
-                <li>定时任务新增更多操作</li>
-                <li>更多操作按钮添加权限控制</li>
-                <li>导入用户样式优化</li>
-                <li>提取通用方法到基类控制器</li>
-                <li>优化使用权限工具获取用户信息</li>
-                <li>优化用户不能删除自己</li>
-                <li>优化XSS跨站脚本过滤</li>
-                <li>优化代码生成模板</li>
-                <li>验证码默认20s超时</li>
-                <li>BLOB下载时清除URL对象引用</li>
-                <li>代码生成导入表按创建时间排序</li>
-                <li>修复代码生成页面数据编辑保存之后总是跳转第一页的问题</li>
-                <li>修复带safari浏览器无法格式化utc日期格式yyyy-MM-dd'T'HH:mm:ss.SSS问题</li>
-                <li>多图上传组件移除多余的api地址&验证失败导致图片删除问题&无法删除相应图片修复</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.6.0 - 2021-07-12">
-              <ol>
-                <li>角色管理新增分配用户功能</li>
-                <li>用户管理新增分配角色功能</li>
-                <li>日志列表支持排序操作</li>
-                <li>优化参数&字典缓存操作</li>
-                <li>系统布局配置支持动态标题开关</li>
-                <li>菜单路由配置支持内链访问</li>
-                <li>默认访问后端首页新增提示语</li>
-                <li>富文本默认上传返回url类型</li>
-                <li>新增自定义弹窗拖拽指令</li>
-                <li>全局注册常用通用组件</li>
-                <li>全局挂载字典标签组件</li>
-                <li>ImageUpload组件支持多图片上传</li>
-                <li>FileUpload组件支持多文件上传</li>
-                <li>文件上传组件添加数量限制属性</li>
-                <li>富文本编辑组件添加类型属性</li>
-                <li>富文本组件工具栏配置视频</li>
-                <li>封装通用iframe组件</li>
-                <li>限制超级管理员不允许操作</li>
-                <li>用户信息长度校验限制</li>
-                <li>分页组件新增pagerCount属性</li>
-                <li>添加bat脚本执行应用</li>
-                <li>升级oshi到最新版本v5.7.4</li>
-                <li>升级element-ui到最新版本2.15.2</li>
-                <li>升级pagehelper到最新版1.3.1</li>
-                <li>升级commons.io到最新版本v2.10.0</li>
-                <li>升级commons.fileupload到最新版本v1.4</li>
-                <li>升级swagger到最新版本v3.0.0</li>
-                <li>修复关闭confirm提示框控制台报错问题</li>
-                <li>修复存在的SQL注入漏洞问题</li>
-                <li>定时任务屏蔽rmi远程调用</li>
-                <li>修复用户搜索分页变量错误</li>
-                <li>修复导出角色数据范围翻译缺少仅本人</li>
-                <li>修复表单构建选择下拉选择控制台报错问题</li>
-                <li>优化图片工具类读取文件</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.5.0 - 2021-05-25">
-              <ol>
-                <li>新增菜单导航显示风格TopNav(false为左侧导航菜单,true为顶部导航菜单)</li>
-                <li>布局设置支持保存&重置配置</li>
-                <li>修复树表数据显示不全&加载慢问题</li>
-                <li>新增IE浏览器版本过低提示页面</li>
-                <li>用户登录后记录最后登录IP&时间</li>
-                <li>页面导出按钮点击之后添加遮罩</li>
-                <li>富文本编辑器支持自定义上传地址</li>
-                <li>富文本编辑组件新增readOnly属性</li>
-                <li>页签TagsView新增关闭右侧功能</li>
-                <li>显隐列组件加载初始默认隐藏列</li>
-                <li>关闭头像上传窗口还原默认图片</li>
-                <li>个人信息添加手机&邮箱重复验证</li>
-                <li>代码生成模板导出按钮点击后添加遮罩</li>
-                <li>代码生成模板树表操作列添加新增按钮</li>
-                <li>代码生成模板修复主子表字段重名问题</li>
-                <li>升级fastjson到最新版1.2.76</li>
-                <li>升级druid到最新版本v1.2.6</li>
-                <li>升级mybatis到最新版3.5.6 阻止远程代码执行漏洞</li>
-                <li>升级oshi到最新版本v5.6.0</li>
-                <li>velocity剔除commons-collections版本,防止3.2.1版本的反序列化漏洞</li>
-                <li>数据监控页默认账户密码防止越权访问</li>
-                <li>修复firefox下表单构建拖拽会新打卡一个选项卡</li>
-                <li>修正后端导入表权限标识</li>
-                <li>修正前端操作日志&登录日志权限标识</li>
-                <li>设置Redis配置HashKey序列化</li>
-                <li>删除操作日志记录信息</li>
-                <li>上传媒体类型添加视频格式</li>
-                <li>修复请求形参未传值记录日志异常问题</li>
-                <li>优化xss校验json请求条件</li>
-                <li>树级结构更新子节点使用replaceFirst</li>
-                <li>优化ExcelUtil空值处理</li>
-                <li>日志记录过滤BindingResult对象,防止异常</li>
-                <li>修改主题后mini类型按钮无效问题</li>
-                <li>优化通用下载完成后删除节点</li>
-                <li>通用Controller添加响应返回消息</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.4.0 - 2021-02-22">
-              <ol>
-                <li>代码生成模板支持主子表</li>
-                <li>表格右侧工具栏组件支持显隐列</li>
-                <li>图片组件添加预览&移除功能</li>
-                <li>Excel注解支持Image图片导出</li>
-                <li>操作按钮组调整为朴素按钮样式</li>
-                <li>代码生成支持文件上传组件</li>
-                <li>代码生成日期控件区分范围</li>
-                <li>代码生成数据库文本类型生成表单文本域</li>
-                <li>用户手机邮箱&菜单组件修改允许空字符串</li>
-                <li>升级SpringBoot到最新版本2.2.13 提升启动速度</li>
-                <li>升级druid到最新版本v1.2.4</li>
-                <li>升级fastjson到最新版1.2.75</li>
-                <li>升级element-ui到最新版本2.15.0</li>
-                <li>修复IE11浏览器报错问题</li>
-                <li>优化多级菜单之间切换无法缓存的问题</li>
-                <li>修复四级菜单无法显示问题</li>
-                <li>修正侧边栏静态路由丢失问题</li>
-                <li>修复角色管理-编辑角色-功能权限显示异常</li>
-                <li>配置文件新增redis数据库索引属性</li>
-                <li>权限工具类增加admin判断</li>
-                <li>角色非自定义权限范围清空选择值</li>
-                <li>修复导入数据为负浮点数时丢失精度问题</li>
-                <li>移除path-to-regexp正则匹配插件</li>
-                <li>修复生成树表代码异常</li>
-                <li>修改ip字段长度防止ipv6地址长度不够</li>
-                <li>防止get请求参数值为false或0等特殊值会导致无法正确的传参</li>
-                <li>登录后push添加catch防止出现检查错误</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.3.0 - 2020-12-14">
-              <ol>
-                <li>新增缓存监控功能</li>
-                <li>支持主题风格配置</li>
-                <li>修复多级菜单之间切换无法缓存的问题</li>
-                <li>多级菜单自动配置组件</li>
-                <li>代码生成预览支持高亮显示</li>
-                <li>支持Get请求映射Params参数</li>
-                <li>删除用户和角色解绑关联</li>
-                <li>去除用户手机邮箱部门必填验证</li>
-                <li>Excel支持注解align对齐方式</li>
-                <li>Excel支持导入Boolean型数据</li>
-                <li>优化头像样式,鼠标移入悬停遮罩</li>
-                <li>代码生成预览提供滚动机制</li>
-                <li>代码生成删除多余的数字float类型</li>
-                <li>修正转换字符串的目标字符集属性</li>
-                <li>回显数据字典防止空值报错</li>
-                <li>日志记录增加过滤多文件场景</li>
-                <li>修改缓存Set方法可能导致嵌套的问题</li>
-                <li>移除前端一些多余的依赖</li>
-                <li>防止安全扫描YUI出现的风险提示</li>
-                <li>修改node-sass为dart-sass</li>
-                <li>升级SpringBoot到最新版本2.1.18</li>
-                <li>升级poi到最新版本4.1.2</li>
-                <li>升级oshi到最新版本v5.3.6</li>
-                <li>升级bitwalker到最新版本1.21</li>
-                <li>升级axios到最新版本0.21.0</li>
-                <li>升级element-ui到最新版本2.14.1</li>
-                <li>升级vue到最新版本2.6.12</li>
-                <li>升级vuex到最新版本3.6.0</li>
-                <li>升级vue-cli到版本4.5.9</li>
-                <li>升级vue-router到最新版本3.4.9</li>
-                <li>升级vue-cli到最新版本4.4.6</li>
-                <li>升级vue-cropper到最新版本0.5.5</li>
-                <li>升级clipboard到最新版本2.0.6</li>
-                <li>升级core-js到最新版本3.8.1</li>
-                <li>升级echarts到最新版本4.9.0</li>
-                <li>升级file-saver到最新版本2.0.4</li>
-                <li>升级fuse.js到最新版本6.4.3</li>
-                <li>升级js-beautify到最新版本1.13.0</li>
-                <li>升级js-cookie到最新版本2.2.1</li>
-                <li>升级path-to-regexp到最新版本6.2.0</li>
-                <li>升级quill到最新版本1.3.7</li>
-                <li>升级screenfull到最新版本5.0.2</li>
-                <li>升级sortablejs到最新版本1.10.2</li>
-                <li>升级vuedraggable到最新版本2.24.3</li>
-                <li>升级chalk到最新版本4.1.0</li>
-                <li>升级eslint到最新版本7.15.0</li>
-                <li>升级eslint-plugin-vue到最新版本7.2.0</li>
-                <li>升级lint-staged到最新版本10.5.3</li>
-                <li>升级runjs到最新版本4.4.2</li>
-                <li>升级sass-loader到最新版本10.1.0</li>
-                <li>升级script-ext-html-webpack-plugin到最新版本2.1.5</li>
-                <li>升级svg-sprite-loader到最新版本5.1.1</li>
-                <li>升级vue-template-compiler到最新版本2.6.12</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.2.1 - 2020-11-18">
-              <ol>
-                <li>阻止任意文件下载漏洞</li>
-                <li>代码生成支持上传控件</li>
-                <li>新增图片上传组件</li>
-                <li>调整默认首页</li>
-                <li>升级druid到最新版本v1.2.2</li>
-                <li>mapperLocations配置支持分隔符</li>
-                <li>权限信息调整</li>
-                <li>调整sql默认时间</li>
-                <li>解决代码生成没有bit类型的问题</li>
-                <li>升级pagehelper到最新版1.3.0</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.2.0 - 2020-10-10">
-              <ol>
-                <li>升级springboot版本到2.1.17 提升安全性</li>
-                <li>升级oshi到最新版本v5.2.5</li>
-                <li>升级druid到最新版本v1.2.1</li>
-                <li>升级jjwt到版本0.9.1</li>
-                <li>升级fastjson到最新版1.2.74</li>
-                <li>修改sass为node-sass,避免el-icon图标乱码</li>
-                <li>代码生成支持同步数据库</li>
-                <li>代码生成支持富文本控件</li>
-                <li>代码生成页面时不忽略remark属性</li>
-                <li>代码生成添加select必填选项</li>
-                <li>Excel导出类型NUMERIC支持精度浮点类型</li>
-                <li>Excel导出targetAttr优化获取值,防止get方法不规范</li>
-                <li>Excel注解支持自动统计数据总和</li>
-                <li>Excel注解支持设置BigDecimal精度&舍入规则</li>
-                <li>菜单&数据权限新增(展开/折叠 全选/全不选 父子联动)</li>
-                <li>允许用户分配到部门父节点</li>
-                <li>菜单新增是否缓存keep-alive</li>
-                <li>表格操作列间距调整</li>
-                <li>限制系统内置参数不允许删除</li>
-                <li>富文本组件优化,支持自定义高度&图片冲突问题</li>
-                <li>富文本工具栏样式对齐</li>
-                <li>导入excel整形值校验优化</li>
-                <li>修复页签关闭所有时固定标签路由不刷新问题</li>
-                <li>表单构建布局型组件新增按钮</li>
-                <li>左侧菜单文字过长显示省略号</li>
-                <li>修正根节点为子部门时,树状结构显示问题</li>
-                <li>修正调用目标字符串最大长度</li>
-                <li>修正菜单提示信息错误</li>
-                <li>修正定时任务执行一次权限标识</li>
-                <li>修正数据库字符串类型nvarchar</li>
-                <li>优化递归子节点</li>
-                <li>优化数据权限判断</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v3.1.0 - 2020-08-13">
-              <ol>
-                <li>表格工具栏右侧添加刷新&显隐查询组件</li>
-                <li>后端支持CORS跨域请求</li>
-                <li>代码生成支持选择上级菜单</li>
-                <li>代码生成支持自定义路径</li>
-                <li>代码生成支持复选框</li>
-                <li>Excel导出导入支持dictType字典类型</li>
-                <li>Excel支持分割字符串组内容</li>
-                <li>验证码类型支持(数组计算、字符验证)</li>
-                <li>升级vue-cli版本到4.4.4</li>
-                <li>修改 node-sass 为 dart-sass</li>
-                <li>表单类型为Integer/Long设置整形默认值</li>
-                <li>代码生成器默认mapper路径与默认mapperScan路径不一致</li>
-                <li>优化防重复提交拦截器</li>
-                <li>优化上级菜单不能选择自己</li>
-                <li>修复角色的权限分配后,未实时生效问题</li>
-                <li>修复在线用户日志记录类型</li>
-                <li>修复富文本空格和缩进保存后不生效问题</li>
-                <li>修复在线用户判断逻辑</li>
-                <li>唯一限制条件只返回单条数据</li>
-                <li>添加获取当前的环境配置方法</li>
-                <li>超时登录后页面跳转到首页</li>
-                <li>全局异常状态汉化拦截处理</li>
-                <li>HTML过滤器改为将html转义</li>
-                <li>检查字符支持小数点&降级改成异常提醒</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v3.0.0 - 2020-07-20">
-              <ol>
-                <li>单应用调整为多模块项目</li>
-                <li>升级element-ui版本到2.13.2</li>
-                <li>删除babel,提高编译速度。</li>
-                <li>新增菜单默认主类目</li>
-                <li>编码文件名修改为uuid方式</li>
-                <li>定时任务cron表达式验证</li>
-                <li>角色权限修改时已有权限未自动勾选异常修复</li>
-                <li>防止切换权限用户后登录出现404</li>
-                <li>Excel支持sort导出排序</li>
-                <li>创建用户不允许选择超级管理员角色</li>
-                <li>修复代码生成导入表结构出现异常页面不提醒问题</li>
-                <li>修复代码生成点击多次表修改数据不变化的问题</li>
-                <li>修复头像上传成功二次打开无法改变裁剪框大小和位置问题</li>
-                <li>修复布局为small者mini用户表单显示错位问题</li>
-                <li>修复热部署导致的强换异常问题</li>
-                <li>修改用户管理复选框宽度,防止部分浏览器出现省略号</li>
-                <li>IpUtils工具,清除Xss特殊字符,防止Xff注入攻击</li>
-                <li>生成domain 如果是浮点型 统一用BigDecimal</li>
-                <li>定时任务调整label-width,防止部署出现错位</li>
-                <li>调整表头固定列默认样式</li>
-                <li>代码生成模板调整,字段为String并且必填则加空串条件</li>
-                <li>代码生成字典Integer/Long使用parseInt</li>
-                <li>
-                  修复dict_sort不可update为0的问题&查询返回增加dict_sort升序排序
-                </li>
-                <li>修正岗位导出权限注解</li>
-                <li>禁止加密密文返回前端</li>
-                <li>修复代码生成页面中的查询条件创建时间未生效的问题</li>
-                <li>修复首页搜索菜单外链无法点击跳转问题</li>
-                <li>修复菜单管理选择图标,backspace删除时不过滤数据</li>
-                <li>用户管理部门分支节点不可检查&显示计数</li>
-                <li>数据范围过滤属性调整</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.3.0 - 2020-06-01">
-              <ol>
-                <li>升级fastjson到最新版1.2.70 修复高危安全漏洞</li>
-                <li>dev启动默认打开浏览器</li>
-                <li>vue-cli使用默认source-map</li>
-                <li>slidebar eslint报错优化</li>
-                <li>当tags-view滚动关闭右键菜单</li>
-                <li>字典管理添加缓存读取</li>
-                <li>参数管理支持缓存操作</li>
-                <li>支持一级菜单(和主页同级)在main区域显示</li>
-                <li>限制外链地址必须以http(s)开头</li>
-                <li>tagview & sidebar 主题颜色与element ui(全局)同步</li>
-                <li>修改数据源类型优先级,先根据方法,再根据类</li>
-                <li>支持是否需要设置token属性,自定义返回码消息。</li>
-                <li>swagger请求前缀加入配置。</li>
-                <li>登录地点设置内容过长则隐藏显示</li>
-                <li>修复定时任务执行一次按钮后不提示消息问题</li>
-                <li>修改上级部门(选择项排除本身和下级)</li>
-                <li>通用http发送方法增加参数 contentType 编码类型</li>
-                <li>更换IP地址查询接口</li>
-                <li>修复页签变量undefined</li>
-                <li>添加校验部门包含未停用的子部门</li>
-                <li>修改定时任务详情下次执行时间日期显示错误</li>
-                <li>角色管理查询设置默认排序字段</li>
-                <li>swagger添加enable参数控制是否启用</li>
-                <li>只对json类型请求构建可重复读取inputStream的request</li>
-                <li>修改代码生成字典字段int类型没有自动选中问题</li>
-                <li>vuex用户名取值修正</li>
-                <li>表格树模板去掉多余的)</li>
-                <li>代码生成序号修正</li>
-                <li>全屏情况下不调整上外边距</li>
-                <li>代码生成Date字段添加默认格式</li>
-                <li>用户管理角色选择权限控制</li>
-                <li>修复路由懒加载报错问题</li>
-                <li>模板sql.vm添加菜单状态</li>
-                <li>设置用户名称不能修改</li>
-                <li>dialog添加append-to-body属性,防止ie遮罩</li>
-                <li>菜单区分状态和显示隐藏功能</li>
-                <li>升级fastjson到最新版1.2.68 修复安全加固</li>
-                <li>修复代码生成如果选择字典类型缺失逗号问题</li>
-                <li>登录请求params更换为data,防止暴露url</li>
-                <li>日志返回时间格式处理</li>
-                <li>添加handle控制允许拖动的元素</li>
-                <li>布局设置点击扩大范围</li>
-                <li>代码生成列属性排序查询</li>
-                <li>代码生成列支持拖动排序</li>
-                <li>修复时间格式不支持ios问题</li>
-                <li>表单构建添加父级class,防止冲突</li>
-                <li>定时任务并发属性修正</li>
-                <li>角色禁用&菜单隐藏不查询权限</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.2.0 - 2020-03-18">
-              <ol>
-                <li>系统监控新增定时任务功能</li>
-                <li>添加一个打包Web工程bat</li>
-                <li>修复页签鼠标滚轮按下的时候,可以关闭不可关闭的tag</li>
-                <li>修复点击退出登录有时会无提示问题</li>
-                <li>修复防重复提交注解无效问题</li>
-                <li>修复通知公告批量删除异常问题</li>
-                <li>添加菜单时路由地址必填限制</li>
-                <li>代码生成字段描述可编辑</li>
-                <li>修复用户修改个人信息导致缓存不过期问题</li>
-                <li>个人信息创建时间获取正确属性值</li>
-                <li>操作日志详细显示正确类型</li>
-                <li>导入表单击行数据时选中对应的复选框</li>
-                <li>批量替换表前缀逻辑调整</li>
-                <li>固定重定向路径表达式</li>
-                <li>升级element-ui版本到2.13.0</li>
-                <li>操作日志排序调整</li>
-                <li>修复charts切换侧边栏或者缩放窗口显示bug</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.1.0 - 2020-02-24">
-              <ol>
-                <li>新增表单构建</li>
-                <li>代码生成支持树表结构</li>
-                <li>新增用户导入</li>
-                <li>修复动态加载路由页面刷新问题</li>
-                <li>修复地址开关无效问题</li>
-                <li>汉化错误提示页面</li>
-                <li>代码生成已知问题修改</li>
-                <li>修复多数据源下配置关闭出现异常处理</li>
-                <li>添加HTML过滤器,用于去除XSS漏洞隐患</li>
-                <li>修复上传头像控制台出现异常</li>
-                <li>修改用户管理分页不正确的问题</li>
-                <li>修复验证码记录提示错误</li>
-                <li>修复request.js缺少Message引用</li>
-                <li>修复表格时间为空出现的异常</li>
-                <li>添加Jackson日期反序列化时区配置</li>
-                <li>调整根据用户权限加载菜单数据树形结构</li>
-                <li>调整成功登录不恢复按钮,防止多次点击</li>
-                <li>修改用户个人资料同步缓存信息</li>
-                <li>修复页面同时出现el-upload和Editor不显示处理</li>
-                <li>修复在角色管理页修改菜单权限偶尔未选中问题</li>
-                <li>配置文件新增redis密码属性</li>
-                <li>设置mybatis全局的配置文件</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
 
-            <el-collapse-item title="v2.0.0 - 2019-12-02">
-              <ol>
-                <li>新增代码生成</li>
-                <li>新增@RepeatSubmit注解,防止重复提交</li>
-                <li>新增菜单主目录添加/删除操作</li>
-                <li>日志记录过滤特殊对象,防止转换异常</li>
-                <li>修改代码生成路由脚本错误</li>
-                <li>用户上传头像实时同步缓存,无需重新登录</li>
-                <li>调整切换页签后不重新加载数据</li>
-                <li>添加jsencrypt实现参数的前端加密</li>
-                <li>系统退出删除用户缓存记录</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v1.1.0 - 2019-11-11">
-              <ol>
-                <li>新增在线用户管理</li>
-                <li>新增按钮组功能实现(批量删除、导出、清空)</li>
-                <li>新增查询条件重置按钮</li>
-                <li>新增Swagger全局Token配置</li>
-                <li>新增后端参数校验</li>
-                <li>修复字典管理页面的日期查询异常</li>
-                <li>修改时间函数命名防止冲突</li>
-                <li>去除菜单上级校验,默认为顶级</li>
-                <li>修复用户密码无法修改问题</li>
-                <li>修复菜单类型为按钮时不显示权限标识</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v1.0.0 - 2019-10-08">
-              <ol>
-                <li>若依前后端分离系统正式发布</li>
-              </ol>
-            </el-collapse-item>
-          </el-collapse>
-        </el-card>
+    <el-row :gutter="32">
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <raddar-chart />
+        </div>
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <div slot="header" class="clearfix">
-            <span>捐赠支持</span>
-          </div>
-          <div class="body">
-            <img
-              src="@/assets/images/pay.png"
-              alt="donate"
-              width="100%"
-            />
-            <span style="display: inline-block; height: 30px; line-height: 30px"
-              >你可以请作者喝杯咖啡表示鼓励</span
-            >
-          </div>
-        </el-card>
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <pie-chart />
+        </div>
+      </el-col>
+      <el-col :xs="24" :sm="24" :lg="8">
+        <div class="chart-wrapper">
+          <bar-chart />
+        </div>
       </el-col>
     </el-row>
+
+    
   </div>
 </template>
 
 <script>
+import PanelGroup from './dashboard/PanelGroup'
+import LineChart from './dashboard/LineChart'
+import RaddarChart from './dashboard/RaddarChart'
+import PieChart from './dashboard/PieChart'
+import BarChart from './dashboard/BarChart'
+
+const lineChartData = {
+  newVisitis: {
+    expectedData: [100, 120, 161, 134, 105, 160, 165],
+    actualData: [120, 82, 91, 154, 162, 140, 145]
+  },
+  messages: {
+    expectedData: [200, 192, 120, 144, 160, 130, 140],
+    actualData: [180, 160, 151, 106, 145, 150, 130]
+  },
+  purchases: {
+    expectedData: [80, 100, 121, 104, 105, 90, 100],
+    actualData: [120, 90, 100, 138, 142, 130, 130]
+  },
+  shoppings: {
+    expectedData: [130, 140, 141, 142, 145, 150, 160],
+    actualData: [120, 82, 91, 154, 162, 140, 130]
+  }
+}
+
 export default {
-  name: "Index",
+  name: 'Index',
+  components: {
+    PanelGroup,
+    LineChart,
+    RaddarChart,
+    PieChart,
+    BarChart
+  },
   data() {
     return {
-      // 版本号
-      version: "3.8.7"
-    };
+      lineChartData: lineChartData.newVisitis
+    }
   },
   methods: {
-    goTarget(href) {
-      window.open(href, "_blank");
+    handleSetLineChartData(type) {
+      this.lineChartData = lineChartData[type]
     }
   }
-};
+}
 </script>
 
-<style scoped lang="scss">
-.home {
-  blockquote {
-    padding: 10px 20px;
-    margin: 0 0 20px;
-    font-size: 17.5px;
-    border-left: 5px solid #eee;
-  }
-  hr {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    border: 0;
-    border-top: 1px solid #eee;
-  }
-  .col-item {
-    margin-bottom: 20px;
-  }
-
-  ul {
-    padding: 0;
-    margin: 0;
-  }
-
-  font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  color: #676a6c;
-  overflow-x: hidden;
-
-  ul {
-    list-style-type: none;
-  }
+<style lang="scss" scoped>
+.dashboard-editor-container {
+  padding: 32px;
+  background-color: rgb(240, 242, 245);
+  position: relative;
 
-  h4 {
-    margin-top: 0px;
-  }
-
-  h2 {
-    margin-top: 10px;
-    font-size: 26px;
-    font-weight: 100;
-  }
-
-  p {
-    margin-top: 10px;
-
-    b {
-      font-weight: 700;
-    }
+  .chart-wrapper {
+    background: #fff;
+    padding: 16px 16px 0;
+    margin-bottom: 32px;
   }
+}
 
-  .update-log {
-    ol {
-      display: block;
-      list-style-type: decimal;
-      margin-block-start: 1em;
-      margin-block-end: 1em;
-      margin-inline-start: 0;
-      margin-inline-end: 0;
-      padding-inline-start: 40px;
-    }
+@media (max-width:1024px) {
+  .chart-wrapper {
+    padding: 8px;
   }
 }
 </style>
-

+ 0 - 98
school-in-out-ui/src/views/index_v1.vue

@@ -1,98 +0,0 @@
-<template>
-  <div class="dashboard-editor-container">
-
-    <panel-group @handleSetLineChartData="handleSetLineChartData" />
-
-    <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
-      <line-chart :chart-data="lineChartData" />
-    </el-row>
-
-    <el-row :gutter="32">
-      <el-col :xs="24" :sm="24" :lg="8">
-        <div class="chart-wrapper">
-          <raddar-chart />
-        </div>
-      </el-col>
-      <el-col :xs="24" :sm="24" :lg="8">
-        <div class="chart-wrapper">
-          <pie-chart />
-        </div>
-      </el-col>
-      <el-col :xs="24" :sm="24" :lg="8">
-        <div class="chart-wrapper">
-          <bar-chart />
-        </div>
-      </el-col>
-    </el-row>
-
-    
-  </div>
-</template>
-
-<script>
-import PanelGroup from './dashboard/PanelGroup'
-import LineChart from './dashboard/LineChart'
-import RaddarChart from './dashboard/RaddarChart'
-import PieChart from './dashboard/PieChart'
-import BarChart from './dashboard/BarChart'
-
-const lineChartData = {
-  newVisitis: {
-    expectedData: [100, 120, 161, 134, 105, 160, 165],
-    actualData: [120, 82, 91, 154, 162, 140, 145]
-  },
-  messages: {
-    expectedData: [200, 192, 120, 144, 160, 130, 140],
-    actualData: [180, 160, 151, 106, 145, 150, 130]
-  },
-  purchases: {
-    expectedData: [80, 100, 121, 104, 105, 90, 100],
-    actualData: [120, 90, 100, 138, 142, 130, 130]
-  },
-  shoppings: {
-    expectedData: [130, 140, 141, 142, 145, 150, 160],
-    actualData: [120, 82, 91, 154, 162, 140, 130]
-  }
-}
-
-export default {
-  name: 'Index',
-  components: {
-    PanelGroup,
-    LineChart,
-    RaddarChart,
-    PieChart,
-    BarChart
-  },
-  data() {
-    return {
-      lineChartData: lineChartData.newVisitis
-    }
-  },
-  methods: {
-    handleSetLineChartData(type) {
-      this.lineChartData = lineChartData[type]
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.dashboard-editor-container {
-  padding: 32px;
-  background-color: rgb(240, 242, 245);
-  position: relative;
-
-  .chart-wrapper {
-    background: #fff;
-    padding: 16px 16px 0;
-    margin-bottom: 32px;
-  }
-}
-
-@media (max-width:1024px) {
-  .chart-wrapper {
-    padding: 8px;
-  }
-}
-</style>

+ 6 - 5
school-in-out-ui/src/views/login.vue

@@ -56,7 +56,7 @@
     </el-form>
     <!--  底部  -->
     <div class="el-login-footer">
-      <span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span>
+      <span>网站备案</span>
     </div>
   </div>
 </template>
@@ -72,8 +72,8 @@ export default {
     return {
       codeUrl: "",
       loginForm: {
-        username: "admin",
-        password: "admin123",
+        username: "",
+        password: "",
         rememberMe: false,
         code: "",
         uuid: ""
@@ -161,7 +161,8 @@ export default {
   justify-content: center;
   align-items: center;
   height: 100%;
-  background-image: url("../assets/images/login-background.jpg");
+  // background-image: url("../assets/images/login-background.jpg");
+  background-image: url("../assets/images/a.jpg");
   background-size: cover;
 }
 .title {
@@ -171,7 +172,7 @@ export default {
 }
 
 .login-form {
-  border-radius: 6px;
+  border-radius: 15px;
   background: #ffffff;
   width: 400px;
   padding: 25px 25px 5px 25px;

+ 379 - 0
school-in-out-ui/src/views/system/parent/index.vue

@@ -0,0 +1,379 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="家长姓名" prop="parentName">
+        <el-input
+          v-model="queryParams.parentName"
+          placeholder="请输入家长姓名"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="家长电话" prop="parentPhone">
+        <el-input
+          v-model="queryParams.parentPhone"
+          placeholder="请输入家长电话"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="关系" prop="relation">
+        <el-select v-model="queryParams.relation" placeholder="请选择与学生的关系" clearable>
+          <el-option
+            v-for="dict in dict.type.parent_relation"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:parent:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:parent:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:parent:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['system:parent:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="parentList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" type="index" />
+      <el-table-column label="孩子" align="center" prop="studentIds" >
+        <template slot-scope="scope">
+					<dict-tag
+						:options="dictTables.studentDict"
+						:value="scope.row.studentIds"
+					/>
+				</template>
+      </el-table-column>
+      <el-table-column label="家长姓名" align="center" prop="parentName" />
+      <el-table-column label="家长电话" align="center" prop="parentPhone" />
+      <el-table-column label="与学生的关系" align="center" prop="relation">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.parent_relation" :value="scope.row.relation"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['system:parent:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['system:parent:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改家长管理对话框 -->
+    <el-dialog 
+      v-loading="formLoading"  
+      element-loading-text="正在请求中..."
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+      :title="title" 
+      :visible.sync="open" 
+      width="500px" 
+      append-to-body
+    >
+      <el-form  ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="家长姓名" prop="parentName">
+          <el-input v-model="form.parentName" placeholder="请输入家长姓名" />
+        </el-form-item>
+        <el-form-item label="家长电话" prop="parentPhone">
+          <el-input v-model="form.parentPhone" placeholder="请输入家长电话" />
+        </el-form-item>
+        <el-form-item label="关联学生" prop="studentIds">
+          <el-select 
+            v-model="form.studentIds" 
+            multiple
+            filterable
+            remote
+            reserve-keyword
+            placeholder="请输入学号关键字"
+            :remote-method="studentRemoteMethod"
+            :loading="studentSelectLoading"
+            clearable 
+            style="width: 100%;"
+          >
+              <el-option
+                v-for="item in studentOptions"
+                :key="item.id"
+                :label="item.studentName"
+                :value="item.id"
+              >
+                <span style="float: left">学号:{{ item.studentNum }}</span>
+                <span style="float: right; color: #8492a6; font-size: 14px">姓名:{{ item.studentName }} </span>
+              </el-option>
+            </el-select>
+        </el-form-item>
+        <el-form-item label="与学生的关系" prop="relation">
+            <el-select v-model="form.relation" placeholder="请选择与学生的关系" clearable style="width: 100%;">
+              <el-option
+                v-for="dict in dict.type.parent_relation"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listParent, getParent, delParent, addParent, updateParent } from "@/api/system/parent";
+import { listStudentAll } from "@/api/system/student";
+import Textyixia from '@/mixin/Textyixia';
+import { Loading } from 'element-ui';
+export default {
+  name: "Parent",
+  mixins: [Textyixia],
+  dicts: ['parent_relation'],
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 家长管理表格数据
+      parentList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        parentName: null,
+        parentPhone: null,
+        relation: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        studentIds: [
+          { required: true, message: "学生不能为空", trigger: "change" }
+        ],
+        parentName: [
+          { required: true, message: "家长姓名不能为空", trigger: "blur" }
+        ],
+        parentPhone: [
+          { required: true, message: "家长电话不能为空", trigger: "blur" },
+          { pattern: /^1[34578]\d{9}$/, message: "手机号码格式错误", trigger: "blur" }
+        ],
+        relation: [
+          { required: true, message: "与学生的关系不能为空", trigger: "blur" }
+        ],
+      },
+      dictTables: {
+        studentDict: [],
+			},
+      studentList: [],
+      studentOptions: [],
+      studentSelectLoading: false,
+      formLoading: true,
+    };
+  },
+  created() {
+    this.getList();
+    this.dictTableData('tb_school_student,student_name,id').then(data => {
+			this.dictTables.studentDict = data;
+		});
+  },
+  methods: {
+    /** 查询家长管理列表 */
+    getList() {
+      this.loading = true;
+      listParent(this.queryParams).then(response => {
+        this.parentList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        studentId: null,
+        parentName: null,
+        parentPhone: null,
+        relation: null,
+        delFlag: null,
+        createBy: null,
+        createTime: null,
+        updateBy: null,
+        updateTime: null
+      };
+      this.formLoading = true;
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加家长";
+      listStudentAll().then(res => {
+        console.log(res);
+        this.studentList = res.data
+      }).finally(() => this.formLoading = false)
+      
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      let loadingInstance = Loading.service({ fullscreen: true, background: 'rgba(0, 0, 0, 0.8)' });
+      this.reset();
+      const id = row.id || this.ids
+      getParent(id).then(response => {
+        this.form = response.data;
+        console.log(this.form);
+        this.form.studentIds = this.form.studentIds.split(',').map(Number);
+        this.studentOptions = this.studentList.filter(item => response.data.studentIds.includes(item.id))
+        this.title = "修改家长";
+      }).finally(() => {
+        
+        setTimeout(() => {
+          loadingInstance.close()
+          this.open = true;
+        }, 500)
+      });
+      listStudentAll().then(res => {
+        console.log(res);
+        this.studentList = res.data
+      }).finally(() => {
+        this.formLoading = false;
+       
+      })
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          this.formLoading = true;
+          addParent(this.form).then(response => {
+              this.$modal.msgSuccess(this.form.id != null ? "修改成功" : '新增成功');
+              this.open = false;
+              this.getList();
+          }).finally(() => this.formLoading = false);
+          
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal.confirm('是否确认删除家长管理编号为"' + ids + '"的数据项?').then(function() {
+        return delParent(ids);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('system/parent/export', {
+        ...this.queryParams
+      }, `parent_${new Date().getTime()}.xlsx`)
+    },
+    studentRemoteMethod(keyword) {
+      this.studentOptions = this.studentList.filter(item => item.studentNum.includes(keyword))
+    },
+  }
+};
+</script>

+ 21 - 13
school-in-out-ui/src/views/system/student/module/StudentInoutLog.vue

@@ -12,17 +12,19 @@
 
 		<!-- 时间线 -->
 		<el-timeline v-loading="loading">
-			<el-timeline-item v-for="(item, index) in listData" :key="index" :timestamp="parseTime(item.day, '{y}-{m}-{d}')" placement="top">
-				<el-card>
-					<h4>进入学校时间</h4>
-					<p>{{ parseTime(item.inTime, '{y}-{m}-{d}') }}</p>
+				<el-timeline-item v-if="listData.length !== 0" v-for="(item, index) in listData" :key="index" :timestamp="parseTime(item.day, '{y}-{m}-{d}')" placement="top">
+					<el-card>
+						<h4>进入学校时间</h4>
+						<p>{{ parseTime(item.inTime, '{y}-{m}-{d}') }}</p>
 
-					<div v-if="item.outTime !== null">
-						<h4>离开学校时间</h4>
-						<p>{{ parseTime(item.outTime, '{y}-{m}-{d}') }}</p>
-					</div>
-				</el-card>
-			</el-timeline-item>
+						<div v-if="item.outTime !== null">
+							<h4>离开学校时间</h4>
+							<p>{{ parseTime(item.outTime, '{y}-{m}-{d}') }}</p>
+						</div>
+					</el-card>
+				</el-timeline-item>
+				<el-empty v-if="listData.length === 0" :image-size="200"></el-empty>
+		
 		</el-timeline>
 	</el-dialog>
 
@@ -48,10 +50,16 @@ export default {
 		getList() {
 			if (this.activeName === 'toDay') {
 				this.form.toDay = this.parseTime(new Date(), '{y}-{m}-{d}')
+				this.form.year = null
+				this.form.month = null
 			} else if (this.activeName === 'month') {
-				this.form.month = this.parseTime(new Date(), '{y}-{m}')
+				this.form.month = this.parseTime(new Date(), '{m}')
+				this.form.year = null
+				this.form.toDay = null;
 			} else if (this.activeName === 'year') {
 				this.form.year = this.parseTime(new Date(), '{y}');
+				this.form.toDay = null
+				this.form.month = null
 			}
 			this.loading = true
 			listStudentInOutLog(this.form).then(res => {
@@ -71,8 +79,8 @@ export default {
 			this.open = false;
 		},
 		handleClick(tab, event) {
-			console.log(tab);
-			console.log(this.activeName);
+			
+			this.getList();
 		},
 	},
 }

+ 25 - 3
school-in-out-ui/src/views/system/user/profile/resetPwd.vue

@@ -18,6 +18,8 @@
 
 <script>
 import { updateUserPwd } from "@/api/system/user";
+import { getPublicKey } from '@/api/login';
+import { encrypt } from '@/utils/jsencrypt';
 
 export default {
   data() {
@@ -51,12 +53,32 @@ export default {
     };
   },
   methods: {
+    getPublicKey() {
+      return new Promise((resolve, reject) => {
+        getPublicKey()
+          .then(res => {
+            resolve(res)
+          })
+          .catch(error => {
+            reject(error)
+          })
+      })
+    },
     submit() {
       this.$refs["form"].validate(valid => {
         if (valid) {
-          updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
-            this.$modal.msgSuccess("修改成功");
-          });
+          this.getPublicKey().then(res=>{
+            let publicKey = res.publicKey
+            console.log("res.publicKey",res.publicKey)
+            const oldPassword = encrypt(this.user.oldPassword, publicKey)
+            const newPassword = encrypt(this.user.newPassword, publicKey)
+            updateUserPwd(oldPassword, newPassword).then(
+              response => {
+                this.msgSuccess("修改成功");
+              }
+            );
+          })
+ 
         }
       });
     },

TEMPAT SAMPAH
uploadPath/upload/2024/01/08/1_20240108101638A001.jpg


TEMPAT SAMPAH
uploadPath/upload/2024/01/09/1_20240109130517A001.jpg