From c48df65d184ab79422b7870a709434fd1b99352e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E7=AC=83=E5=AE=9E?= <3388214266@qq.com> Date: Sat, 10 Jan 2026 21:55:01 +0800 Subject: [PATCH] init --- .idea/.gitignore | 8 + .idea/compiler.xml | 13 + .idea/inspectionProfiles/Project_Default.xml | 5 + .idea/misc.xml | 12 + .idea/vcs.xml | 7 + .../documents/Boss招聘系统全栈功能完善计划.md | 37 + .trae/documents/前端接口修复与流程对齐计划.md | 30 + .trae/documents/多角色招聘系统全栈开发计划.md | 50 + BOSSBackEnd/.gitattributes | 2 + BOSSBackEnd/.gitignore | 33 + .../.mvn/wrapper/maven-wrapper.properties | 3 + .../集成 generator_domain 并实现完整CRUD.md | 73 + BOSSBackEnd/mvnw | 295 + BOSSBackEnd/mvnw.cmd | 189 + BOSSBackEnd/pom.xml | 166 + BOSSBackEnd/sql/add_resume_address.sql | 10 + BOSSBackEnd/sql/new_structure.sql | 175 + BOSSBackEnd/sql/seed_bulk.sql | 67 + BOSSBackEnd/sql/seed_bulk_real_v1_fixed.sql | 578 ++ BOSSBackEnd/sql/sql.sql | 238 + .../java/com/zds/boss/BossApplication.java | 15 + .../com/zds/boss/annotation/AuthCheck.java | 21 + .../com/zds/boss/aop/AuthInterceptor.java | 83 + .../com/zds/boss/common/BaseResponse.java | 30 + .../com/zds/boss/common/DeleteRequest.java | 16 + .../java/com/zds/boss/common/PageRequest.java | 27 + .../java/com/zds/boss/common/ResultUtils.java | 48 + .../java/com/zds/boss/config/CorsConfig.java | 27 + .../com/zds/boss/config/MultipartConfig.java | 48 + .../zds/boss/config/MyBatisPlusConfig.java | 25 + .../java/com/zds/boss/config/WebConfig.java | 81 + .../com/zds/boss/constant/UserConstant.java | 24 + .../controller/ApplicationController.java | 103 + .../BossApplicationDecisionController.java | 81 + .../zds/boss/controller/BossController.java | 31 + .../boss/controller/CompanyController.java | 89 + .../boss/controller/InterviewController.java | 85 + .../boss/controller/JobPostingController.java | 83 + .../zds/boss/controller/ResumeController.java | 225 + .../zds/boss/controller/UserController.java | 189 + .../zds/boss/exception/BusinessException.java | 27 + .../com/zds/boss/exception/ErrorCode.java | 32 + .../exception/GlobalExceptionHandler.java | 26 + .../com/zds/boss/exception/ThrowUtils.java | 40 + .../zds/boss/mapper/ApplicationMapper.java | 8 + .../mapper/BossApplicationDecisionMapper.java | 8 + .../com/zds/boss/mapper/CompanyMapper.java | 18 + .../com/zds/boss/mapper/InterviewMapper.java | 8 + .../com/zds/boss/mapper/JobPostingMapper.java | 8 + .../zds/boss/mapper/ResumeAddressMapper.java | 7 + .../com/zds/boss/mapper/ResumeMapper.java | 14 + .../java/com/zds/boss/mapper/UserMapper.java | 18 + .../application/ApplicationAddRequest.java | 14 + .../application/ApplicationQueryRequest.java | 19 + .../application/ApplicationUpdateRequest.java | 13 + .../model/dto/company/CompanyAddRequest.java | 17 + .../dto/company/CompanyQueryRequest.java | 17 + .../dto/company/CompanyUpdateRequest.java | 18 + .../BossApplicationDecisionAddRequest.java | 17 + .../BossApplicationDecisionQueryRequest.java | 18 + .../BossApplicationDecisionUpdateRequest.java | 16 + .../dto/interview/InterviewAddRequest.java | 19 + .../dto/interview/InterviewQueryRequest.java | 18 + .../dto/interview/InterviewUpdateRequest.java | 17 + .../model/dto/job/JobPostingAddRequest.java | 20 + .../model/dto/job/JobPostingQueryRequest.java | 20 + .../dto/job/JobPostingUpdateRequest.java | 19 + .../model/dto/resume/ResumeAddRequest.java | 38 + .../model/dto/resume/ResumeQueryRequest.java | 37 + .../model/dto/resume/ResumeUpdateRequest.java | 43 + .../boss/model/dto/user/UserAddRequest.java | 32 + .../boss/model/dto/user/UserLoginRequest.java | 23 + .../boss/model/dto/user/UserQueryRequest.java | 35 + .../model/dto/user/UserRegisterRequest.java | 21 + .../model/dto/user/UserUpdatePageRequest.java | 23 + .../model/dto/user/UserUpdateRequest.java | 39 + .../zds/boss/model/entity/Application.java | 26 + .../model/entity/BossApplicationDecision.java | 26 + .../com/zds/boss/model/entity/Company.java | 133 + .../com/zds/boss/model/entity/Interview.java | 30 + .../com/zds/boss/model/entity/JobPosting.java | 33 + .../com/zds/boss/model/entity/Resume.java | 79 + .../zds/boss/model/entity/ResumeAddress.java | 38 + .../java/com/zds/boss/model/entity/User.java | 100 + .../zds/boss/model/enums/UserRoleEnum.java | 43 + .../com/zds/boss/model/vo/ApplicationVO.java | 19 + .../model/vo/BossApplicationDecisionVO.java | 19 + .../java/com/zds/boss/model/vo/CompanyVO.java | 21 + .../com/zds/boss/model/vo/InterviewVO.java | 22 + .../com/zds/boss/model/vo/JobPostingVO.java | 25 + .../com/zds/boss/model/vo/LoginUserVO.java | 66 + .../java/com/zds/boss/model/vo/ResumeVO.java | 58 + .../java/com/zds/boss/model/vo/UserVO.java | 69 + .../zds/boss/service/ApplicationService.java | 25 + .../BossApplicationDecisionService.java | 25 + .../com/zds/boss/service/CompanyService.java | 32 + .../com/zds/boss/service/FileService.java | 219 + .../zds/boss/service/InterviewService.java | 25 + .../zds/boss/service/JobPostingService.java | 25 + .../com/zds/boss/service/ResumeService.java | 79 + .../com/zds/boss/service/UserService.java | 96 + .../service/impl/ApplicationServiceImpl.java | 199 + .../BossApplicationDecisionServiceImpl.java | 174 + .../boss/service/impl/CompanyServiceImpl.java | 165 + .../service/impl/InterviewServiceImpl.java | 134 + .../service/impl/JobPostingServiceImpl.java | 166 + .../boss/service/impl/ResumeServiceImpl.java | 137 + .../boss/service/impl/UserServiceImpl.java | 265 + .../java/com/zds/boss/utils/UserUtils.java | 25 + .../java/generator/domain/Application.java | 117 + .../domain/BossApplicationDecision.java | 117 + .../main/java/generator/domain/Interview.java | 141 + .../java/generator/domain/JobPosting.java | 165 + .../generator/mapper/ApplicationMapper.java | 18 + .../mapper/BossApplicationDecisionMapper.java | 18 + .../generator/mapper/InterviewMapper.java | 18 + .../generator/mapper/JobPostingMapper.java | 18 + .../generator/service/ApplicationService.java | 13 + .../BossApplicationDecisionService.java | 13 + .../generator/service/InterviewService.java | 13 + .../generator/service/JobPostingService.java | 13 + .../service/impl/ApplicationServiceImpl.java | 22 + .../BossApplicationDecisionServiceImpl.java | 22 + .../service/impl/InterviewServiceImpl.java | 22 + .../service/impl/JobPostingServiceImpl.java | 22 + .../src/main/resources/application.yml | 73 + .../generator/mapper/ApplicationMapper.xml | 20 + .../mapper/BossApplicationDecisionMapper.xml | 20 + .../generator/mapper/CompanyMapper.xml | 24 + .../generator/mapper/InterviewMapper.xml | 23 + .../generator/mapper/JobPostingMapper.xml | 26 + .../resources/generator/mapper/userMapper.xml | 27 + .../com/zds/boss/BossApplicationTests.java | 39 + .../test/java/com/zds/boss/FullFlowTests.java | 116 + BOSSFrontEnd/.idea/.gitignore | 5 + BOSSFrontEnd/.idea/BOSSFrontEnd.iml | 12 + BOSSFrontEnd/.idea/modules.xml | 8 + BOSSFrontEnd/.idea/vcs.xml | 6 + BOSSFrontEnd/BOSS/.gitignore | 36 + BOSSFrontEnd/BOSS/.prettierrc.json | 6 + BOSSFrontEnd/BOSS/.vscode/extensions.json | 6 + BOSSFrontEnd/BOSS/README.md | 42 + BOSSFrontEnd/BOSS/env.d.ts | 1 + BOSSFrontEnd/BOSS/index.html | 13 + BOSSFrontEnd/BOSS/mock-api.json | 178 + BOSSFrontEnd/BOSS/openapi.config.ts | 18 + BOSSFrontEnd/BOSS/package-lock.json | 5188 +++++++++++++++++ BOSSFrontEnd/BOSS/package.json | 43 + BOSSFrontEnd/BOSS/public/favicon.svg | 1009 ++++ BOSSFrontEnd/BOSS/src/App.vue | 23 + .../BOSS/src/api/api/applicationController.ts | 90 + .../api/bossApplicationDecisionController.ts | 90 + .../BOSS/src/api/api/bossController.ts | 11 + .../BOSS/src/api/api/companyController.ts | 87 + BOSSFrontEnd/BOSS/src/api/api/index.ts | 22 + .../BOSS/src/api/api/interviewController.ts | 90 + .../BOSS/src/api/api/jobPostingController.ts | 87 + .../src/api/api/resumeAddressController.ts | 32 + .../BOSS/src/api/api/resumeController.ts | 84 + BOSSFrontEnd/BOSS/src/api/api/typings.d.ts | 715 +++ .../BOSS/src/api/api/userController.ts | 123 + BOSSFrontEnd/BOSS/src/components/NavBar.vue | 165 + BOSSFrontEnd/BOSS/src/libs/request.ts | 57 + BOSSFrontEnd/BOSS/src/main.ts | 15 + BOSSFrontEnd/BOSS/src/router/index.ts | 111 + BOSSFrontEnd/BOSS/src/services/api.ts | 43 + BOSSFrontEnd/BOSS/src/stores/counter.ts | 12 + BOSSFrontEnd/BOSS/src/stores/user.ts | 44 + .../BOSS/src/views/AdminApplications.vue | 140 + .../BOSS/src/views/BossApplications.vue | 209 + BOSSFrontEnd/BOSS/src/views/BossCompany.vue | 192 + BOSSFrontEnd/BOSS/src/views/Bosses.vue | 220 + BOSSFrontEnd/BOSS/src/views/HomeView.vue | 112 + BOSSFrontEnd/BOSS/src/views/JobEdit.vue | 138 + BOSSFrontEnd/BOSS/src/views/Jobs.vue | 308 + BOSSFrontEnd/BOSS/src/views/LoginView.vue | 194 + .../BOSS/src/views/MyApplications.vue | 134 + BOSSFrontEnd/BOSS/src/views/MyResumes.vue | 212 + BOSSFrontEnd/BOSS/src/views/Profile.vue | 114 + BOSSFrontEnd/BOSS/src/views/RegisterView.vue | 308 + BOSSFrontEnd/BOSS/src/views/ResumeEdit.vue | 193 + BOSSFrontEnd/BOSS/src/views/Users.vue | 290 + BOSSFrontEnd/BOSS/tsconfig.app.json | 12 + BOSSFrontEnd/BOSS/tsconfig.json | 11 + BOSSFrontEnd/BOSS/tsconfig.node.json | 19 + BOSSFrontEnd/BOSS/vite.config.ts | 27 + 186 files changed, 19112 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 .trae/documents/Boss招聘系统全栈功能完善计划.md create mode 100644 .trae/documents/前端接口修复与流程对齐计划.md create mode 100644 .trae/documents/多角色招聘系统全栈开发计划.md create mode 100644 BOSSBackEnd/.gitattributes create mode 100644 BOSSBackEnd/.gitignore create mode 100644 BOSSBackEnd/.mvn/wrapper/maven-wrapper.properties create mode 100644 BOSSBackEnd/.trae/documents/集成 generator_domain 并实现完整CRUD.md create mode 100644 BOSSBackEnd/mvnw create mode 100644 BOSSBackEnd/mvnw.cmd create mode 100644 BOSSBackEnd/pom.xml create mode 100644 BOSSBackEnd/sql/add_resume_address.sql create mode 100644 BOSSBackEnd/sql/new_structure.sql create mode 100644 BOSSBackEnd/sql/seed_bulk.sql create mode 100644 BOSSBackEnd/sql/seed_bulk_real_v1_fixed.sql create mode 100644 BOSSBackEnd/sql/sql.sql create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/BossApplication.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/annotation/AuthCheck.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/aop/AuthInterceptor.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/common/BaseResponse.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/common/DeleteRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/common/PageRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/common/ResultUtils.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/config/CorsConfig.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/config/MultipartConfig.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/config/MyBatisPlusConfig.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/config/WebConfig.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/constant/UserConstant.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/ApplicationController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/BossApplicationDecisionController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/BossController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/CompanyController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/InterviewController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/JobPostingController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/ResumeController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/controller/UserController.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/exception/BusinessException.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/exception/ErrorCode.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/exception/GlobalExceptionHandler.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/exception/ThrowUtils.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/ApplicationMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/BossApplicationDecisionMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/CompanyMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/InterviewMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/JobPostingMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeAddressMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/mapper/UserMapper.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserAddRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserLoginRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserQueryRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserRegisterRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdatePageRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdateRequest.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Application.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/BossApplicationDecision.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Company.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Interview.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/JobPosting.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Resume.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/ResumeAddress.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/entity/User.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/enums/UserRoleEnum.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ApplicationVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/BossApplicationDecisionVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/CompanyVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/InterviewVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/JobPostingVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/LoginUserVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ResumeVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/model/vo/UserVO.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/ApplicationService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/BossApplicationDecisionService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/CompanyService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/FileService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/InterviewService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/JobPostingService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/ResumeService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/UserService.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ApplicationServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/BossApplicationDecisionServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/CompanyServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/InterviewServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/JobPostingServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ResumeServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/service/impl/UserServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/com/zds/boss/utils/UserUtils.java create mode 100644 BOSSBackEnd/src/main/java/generator/domain/Application.java create mode 100644 BOSSBackEnd/src/main/java/generator/domain/BossApplicationDecision.java create mode 100644 BOSSBackEnd/src/main/java/generator/domain/Interview.java create mode 100644 BOSSBackEnd/src/main/java/generator/domain/JobPosting.java create mode 100644 BOSSBackEnd/src/main/java/generator/mapper/ApplicationMapper.java create mode 100644 BOSSBackEnd/src/main/java/generator/mapper/BossApplicationDecisionMapper.java create mode 100644 BOSSBackEnd/src/main/java/generator/mapper/InterviewMapper.java create mode 100644 BOSSBackEnd/src/main/java/generator/mapper/JobPostingMapper.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/ApplicationService.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/BossApplicationDecisionService.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/InterviewService.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/JobPostingService.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/impl/ApplicationServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/impl/BossApplicationDecisionServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/impl/InterviewServiceImpl.java create mode 100644 BOSSBackEnd/src/main/java/generator/service/impl/JobPostingServiceImpl.java create mode 100644 BOSSBackEnd/src/main/resources/application.yml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/ApplicationMapper.xml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/BossApplicationDecisionMapper.xml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/CompanyMapper.xml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/InterviewMapper.xml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/JobPostingMapper.xml create mode 100644 BOSSBackEnd/src/main/resources/generator/mapper/userMapper.xml create mode 100644 BOSSBackEnd/src/test/java/com/zds/boss/BossApplicationTests.java create mode 100644 BOSSBackEnd/src/test/java/com/zds/boss/FullFlowTests.java create mode 100644 BOSSFrontEnd/.idea/.gitignore create mode 100644 BOSSFrontEnd/.idea/BOSSFrontEnd.iml create mode 100644 BOSSFrontEnd/.idea/modules.xml create mode 100644 BOSSFrontEnd/.idea/vcs.xml create mode 100644 BOSSFrontEnd/BOSS/.gitignore create mode 100644 BOSSFrontEnd/BOSS/.prettierrc.json create mode 100644 BOSSFrontEnd/BOSS/.vscode/extensions.json create mode 100644 BOSSFrontEnd/BOSS/README.md create mode 100644 BOSSFrontEnd/BOSS/env.d.ts create mode 100644 BOSSFrontEnd/BOSS/index.html create mode 100644 BOSSFrontEnd/BOSS/mock-api.json create mode 100644 BOSSFrontEnd/BOSS/openapi.config.ts create mode 100644 BOSSFrontEnd/BOSS/package-lock.json create mode 100644 BOSSFrontEnd/BOSS/package.json create mode 100644 BOSSFrontEnd/BOSS/public/favicon.svg create mode 100644 BOSSFrontEnd/BOSS/src/App.vue create mode 100644 BOSSFrontEnd/BOSS/src/api/api/applicationController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/bossApplicationDecisionController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/bossController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/companyController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/index.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/interviewController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/jobPostingController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/resumeAddressController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/resumeController.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/typings.d.ts create mode 100644 BOSSFrontEnd/BOSS/src/api/api/userController.ts create mode 100644 BOSSFrontEnd/BOSS/src/components/NavBar.vue create mode 100644 BOSSFrontEnd/BOSS/src/libs/request.ts create mode 100644 BOSSFrontEnd/BOSS/src/main.ts create mode 100644 BOSSFrontEnd/BOSS/src/router/index.ts create mode 100644 BOSSFrontEnd/BOSS/src/services/api.ts create mode 100644 BOSSFrontEnd/BOSS/src/stores/counter.ts create mode 100644 BOSSFrontEnd/BOSS/src/stores/user.ts create mode 100644 BOSSFrontEnd/BOSS/src/views/AdminApplications.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/BossApplications.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/BossCompany.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/Bosses.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/HomeView.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/JobEdit.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/Jobs.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/LoginView.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/MyApplications.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/MyResumes.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/Profile.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/RegisterView.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/ResumeEdit.vue create mode 100644 BOSSFrontEnd/BOSS/src/views/Users.vue create mode 100644 BOSSFrontEnd/BOSS/tsconfig.app.json create mode 100644 BOSSFrontEnd/BOSS/tsconfig.json create mode 100644 BOSSFrontEnd/BOSS/tsconfig.node.json create mode 100644 BOSSFrontEnd/BOSS/vite.config.ts diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b47abf3 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..8d66637 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..c2f272f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..a8cb24f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.trae/documents/Boss招聘系统全栈功能完善计划.md b/.trae/documents/Boss招聘系统全栈功能完善计划.md new file mode 100644 index 0000000..6fac592 --- /dev/null +++ b/.trae/documents/Boss招聘系统全栈功能完善计划.md @@ -0,0 +1,37 @@ +# 系统功能完善与优化计划 + +## 1. 修复与优化 +- **修复登录跳转**: 检查 NavBar 中的“登录”按钮,确保使用 Vue Router 进行跳转,避免页面刷新。 +- **权限修正**: + - `CompanyController`: 放宽 `add` 和 `update` 权限,允许 **Boss** 创建和修改自己的公司。 + - `ApplicationController`: 为 `listApplicationVOByPage` 添加权限控制,允许 Admin 查看所有,但限制 User/Boss 只能看相关的。 + - `UserController`: 确认 `updateUser` 逻辑,确保 User/Boss 也能更新自己的信息(目前仅 Admin)。 + +## 2. 后端逻辑增强 +- **Boss 创建公司**: + - 修改 `addCompany`:允许 Boss 调用。创建成功后,自动将 Boss 的 `company_id` 更新为新公司的 ID。 + - 限制:如果 Boss 已有公司,禁止创建新公司(或提示只能创建一个)。 +- **管理员查询投递**: + - 修改 `listApplicationVOByPage`:如果是 Admin,允许无条件查询所有;如果是 User/Boss,强制追加 `userId`/`bossId` 过滤条件。 + +## 3. 前端新功能开发 +- **Boss 公司管理**: + - 在 Boss 工作台增加“我的公司”模块。 + - 如果未绑定公司,显示“创建公司”表单。 + - 如果已绑定,显示公司详情及“编辑”按钮。 +- **职位发布管理**: + - 在 Boss 工作台增加“发布职位”入口。 + - 创建 `JobEdit.vue`:用于发布新职位和编辑现有职位。 +- **管理员投递查询**: + - 创建 `AdminApplications.vue`:仅管理员可见,展示全站投递记录,支持筛选。 +- **个人信息管理**: + - 创建 `Profile.vue`:允许 User/Boss 修改昵称、密码、头像等信息。 + +## 4. 主页改版 +- 改造 `HomeView.vue`: + - 展示“最新职位”列表(复用 Job 列表逻辑,或取前 6-8 条)。 + - 增加“热门公司”板块(可选)。 + +## 执行步骤 +1. **后端**: 修改 `CompanyController` (Boss权限), `ApplicationController` (列表权限), `UserController` (更新权限)。 +2. **前端**: 修复登录链接 -> 开发 Boss 公司模块 -> 开发职位发布模块 -> 开发管理员投递查询 -> 改造主页 -> 开发个人中心。 \ No newline at end of file diff --git a/.trae/documents/前端接口修复与流程对齐计划.md b/.trae/documents/前端接口修复与流程对齐计划.md new file mode 100644 index 0000000..cd44c49 --- /dev/null +++ b/.trae/documents/前端接口修复与流程对齐计划.md @@ -0,0 +1,30 @@ +**目标**:修复前端接口调用报错,确保各角色(User/Boss/Admin)功能流程通畅。 +**原则**:不修改简历上传功能;密码统一为 11111111;修正不存在的后端接口调用。 + +### 1. 核心状态管理修复 (`stores/user.ts`) +- **问题**:当前代码尝试调用 `/admin/login`, `/boss/login` 等不存在的接口。 +- **修复**: + - 移除 `getLoginAdmin`, `getLoginBoss` 调用。 + - 统一使用 `getLoginUser` 获取用户信息。 + - 依靠返回的 `userRole` ('user', 'boss', 'admin') 区分身份。 + +### 2. 登录与注册流程修正 +- **登录页 (`views/LoginView.vue`)**: + - 保持仅保留“用户登录”入口(因为后端统一了登录接口)。 + - **新增**:登录成功后,根据 `userRole` 自动跳转到对应首页: + - Admin -> `/admin/applications` (或用户管理页) + - Boss -> `/boss/applications` + - User -> `/home` +- **注册页 (`views/RegisterView.vue`)**: + - **移除** "Boss注册" Tab,因为后端缺乏 `/boss/register` 接口。 + - 仅保留普通用户注册,避免前端报错。 + +### 3. 页面接口报错修复 +- **Boss 列表页 (`views/Bosses.vue`)**: + - 原调用 `/boss/list/page/vo` 不存在。 + - **修复**:改为调用 `/user/list/page/vo`(用户列表接口),如果在前端能过滤或后端支持筛选最好,否则暂时显示用户列表以避免报错。 +- **Boss 个人信息/公司页**: + - 确认依赖的 `companyId` 获取逻辑是否通过 `getLoginUser` 正常返回。 + +### 4. 验证 +- 启动开发服务器,模拟登录各角色账号(密码 11111111),验证页面加载与数据展示。 diff --git a/.trae/documents/多角色招聘系统全栈开发计划.md b/.trae/documents/多角色招聘系统全栈开发计划.md new file mode 100644 index 0000000..5645786 --- /dev/null +++ b/.trae/documents/多角色招聘系统全栈开发计划.md @@ -0,0 +1,50 @@ +# 全栈开发计划:多角色系统与简历投递功能 + +## 1. 后端权限修正与逻辑完善 +### 权限放宽与校验 +- **JobPostingController**: 移除 `add`, `update`, `delete` 的 `@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)` 限制,修改为允许 **Boss** 操作。在 Service 层添加逻辑,确保 Boss 只能操作自己发布的职位。 +- **BossApplicationDecisionController**: 移除 `@AuthCheck(ADMIN_ROLE)`,允许 **Boss** 提交决策。确保 Boss 只能处理投递给自己职位的申请。 +- **BossController**: 调整 `update`, `delete` 权限,允许 Admin 和 Boss 自己操作。 + +### 业务逻辑增强 +- **ApplicationController**: 确保 `add` 接口正确处理投递逻辑(检查是否已投递、关联简历等)。 +- **ResumeService**: 确认并确保 `delete` 和 `update` 操作校验了 `userId`,防止越权修改。 + +## 2. 前端架构升级 +### API 更新 +- 运行 `npm run openapi`,生成最新的后端接口定义(包含 `getLoginBoss` 等)。 + +### 状态管理 (Store) +- 改造 `src/stores/user.ts` 中的 `fetchLoginUser` 方法: + 1. 尝试 `getLoginUser` (User) + 2. 失败则尝试 `getLoginAdmin` (Admin) + 3. 失败则尝试 `getLoginBoss` (Boss) + 4. 统一设置 `loginUser` 状态,并附加 `role` 字段('user' | 'admin' | 'boss')。 + +## 3. 前端功能模块开发 +### 简历管理模块 (User & Admin) +- **我的简历 (`/user/resumes`)**: 展示当前用户的简历列表。 +- **简历编辑/创建 (`/user/resume/edit/:id?`)**: 表单页面,支持 Markdown 编辑。 +- **权限控制**: 列表页仅展示自己的简历;Admin 可在后台管理页查看所有。 + +### 职位与投递模块 (User) +- **投递功能**: 在职位详情页或列表页增加“投递”按钮。 + - 弹窗选择要使用的简历。 + - 调用 `/application/add` 接口。 +- **我的投递 (`/user/applications`)**: 列表展示已投递的职位、投递时间及当前状态(已投递/已拒绝/面试中等)。 + +### Boss 工作台 (Boss) +- **收到的投递 (`/boss/applications`)**: 展示投递给当前 Boss 的申请列表。 +- **决策操作**: 提供“接受”和“拒绝”按钮,调用 `/decision/add` 接口更新状态。 + +### Boss 列表管理 (Admin & Boss) +- **Boss 列表页 (`/bosses`)**: + - 所有人可见列表。 + - **修改/删除按钮**: 仅当 `loginUser.role === 'admin'` 或 `loginUser.id === item.id` (且角色为 Boss) 时显示。 + +## 4. 数据库完善 +- 确保 `f:\Code\BOSS\BOSSBackEnd\sql\sql.sql` 中的表结构与实体类一致(目前看来基本一致,主要关注索引和约束)。 + +## 执行顺序 +1. **后端**: 修改 Controllers 和 Services 权限逻辑。 +2. **前端**: 更新 API -> 修改 Store -> 开发简历页 -> 开发投递功能 -> 开发 Boss 工作台 -> 完善权限控制 UI。 \ No newline at end of file diff --git a/BOSSBackEnd/.gitattributes b/BOSSBackEnd/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/BOSSBackEnd/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/BOSSBackEnd/.gitignore b/BOSSBackEnd/.gitignore new file mode 100644 index 0000000..667aaef --- /dev/null +++ b/BOSSBackEnd/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/BOSSBackEnd/.mvn/wrapper/maven-wrapper.properties b/BOSSBackEnd/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..8dea6c2 --- /dev/null +++ b/BOSSBackEnd/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip diff --git a/BOSSBackEnd/.trae/documents/集成 generator_domain 并实现完整CRUD.md b/BOSSBackEnd/.trae/documents/集成 generator_domain 并实现完整CRUD.md new file mode 100644 index 0000000..35c3e15 --- /dev/null +++ b/BOSSBackEnd/.trae/documents/集成 generator_domain 并实现完整CRUD.md @@ -0,0 +1,73 @@ +## 目标 +- 将 f:\Code\BOSS\src\main\java\generator\domain 下的 5 个实体迁移到项目标准位置(com.zds.boss.model.entity),并为每个实体完成基础 CRUD 的 Controller、Service、ServiceImpl、Mapper(含 XML 根据需要)、DTO 与 VO。 +- 统一权限与风格:写操作使用 @AuthCheck(mustRole = "admin");分页查询与条件封装复用 PageRequest;逻辑删除字段与全局配置对齐。 + +## 待集成实体 +- 源文件: + - [Boss.java](file:///f:/Code/BOSS/src/main/java/generator/domain/Boss.java) + - [JobPosting.java](file:///f:/Code/BOSS/src/main/java/generator/domain/JobPosting.java) + - [Application.java](file:///f:/Code/BOSS/src/main/java/generator/domain/Application.java) + - [Interview.java](file:///f:/Code/BOSS/src/main/java/generator/domain/Interview.java) + - [BossApplicationDecision.java](file:///f:/Code/BOSS/src/main/java/generator/domain/BossApplicationDecision.java) +- 目标包:com.zds.boss.model.entity(命名规范与现有 Admin/User/Resume/Company 保持一致) +- 字段策略: + - 表名沿用 @TableName;字段默认开启 map-underscore-to-camel-case 映射。 + - 逻辑删除:如 Boss 包含 isDeleted/deletedAt,重命名为 isDelete 并添加 @TableLogic 以匹配全局配置(logic-delete-field: isDelete)。 + +## 每个实体的配套层次 +- Mapper:XxxMapper(BaseMapper),必要时生成 generator/mapper XML(BaseResultMap + Base_Column_List)。 +- Service:XxxService(IService + 扩展方法):add、update、delete、getVO、getVOList、getQueryWrapper、listVOByPage。 +- Impl:XxxServiceImpl(ServiceImpl + 业务校验与封装)。 +- DTO:XxxAddRequest、XxxUpdateRequest、XxxQueryRequest(继承 PageRequest)。 +- VO:XxxVO(仅展示与安全字段)。 +- Controller:XxxController,路径与风格与已有模块一致,写操作加 @AuthCheck(mustRole = "admin")。 + +## 控制器端点设计 +- Boss(招聘方账号) + - POST /boss/add、/boss/update、/boss/delete(需 admin) + - GET /boss/get、/boss/get/vo + - POST /boss/list/page/vo(分页查询) +- JobPosting(岗位) + - POST /job/add、/job/update、/job/delete(需 admin) + - GET /job/get、/job/get/vo + - POST /job/list/page/vo +- Application(投递记录) + - POST /application/add(登录用户提交) + - POST /application/update、/application/delete(本人或管理员) + - GET /application/get、/application/get/vo + - POST /application/list/page/vo(管理员查看;或限制仅本人) +- Interview(面试安排) + - POST /interview/add、/interview/update、/interview/delete(需 admin) + - GET /interview/get、/interview/get/vo + - POST /interview/list/page/vo +- BossApplicationDecision(投递处理) + - POST /decision/add、/decision/update、/decision/delete(需 admin) + - GET /decision/get、/decision/get/vo + - POST /decision/list/page/vo + +## 权限与校验 +- 写操作统一注解:@AuthCheck(mustRole = "admin")。 +- 针对 Application 的本人操作: + - add 时绑定 loginUser.id → userId; + - update/delete 时校验记录 userId 与当前用户一致或 isAdmin(loginUser)(复用 UserUtils)。 +- 被封禁用户(status==0)在 AOP 层直接拒绝(已在 AuthInterceptor)。 + +## 详细实施步骤 +1. 迁移与修正实体: + - 将 5 个实体移动到 com.zds.boss.model.entity 并修正包名。 + - Boss 增加 @TableLogic 并将 isDeleted → isDelete,保持 deletedAt 字段。 +2. 为每个实体创建 Mapper 接口与(按需)XML 映射,遵循 Company/Resume 的模式。 +3. 为每个实体新增 DTO(Add/Update/Query)与 VO。 +4. 编写 Service 接口与实现: + - 基础校验(空参、ID 合法性)、BeanUtil 复制、QueryWrapper 条件构造、分页封装。 +5. 编写 Controller: + - 统一 CORS、路径前缀与注解风格;写操作加 @AuthCheck;Application 的本人校验走 UserService + UserUtils。 +6. 编译与运行验证: + - mvn compile;启动后用简单请求验证 CRUD 通路与 AOP 权限。 +7. 文档与代码参考补充: + - 在 README 或接口注释中标注各字段语义与权限规则。 + +## 验收标准 +- 五个实体在标准包结构下具备可用的 CRUD 控制器与服务层,分页与条件查询可用。 +- 写操作权限正确,封禁用户在 AOP 层拒绝;Application 本人校验生效。 +- 编译与运行均通过;与现有模块无冲突(命名、包结构、风格统一)。 \ No newline at end of file diff --git a/BOSSBackEnd/mvnw b/BOSSBackEnd/mvnw new file mode 100644 index 0000000..bd8896b --- /dev/null +++ b/BOSSBackEnd/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/BOSSBackEnd/mvnw.cmd b/BOSSBackEnd/mvnw.cmd new file mode 100644 index 0000000..92450f9 --- /dev/null +++ b/BOSSBackEnd/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/BOSSBackEnd/pom.xml b/BOSSBackEnd/pom.xml new file mode 100644 index 0000000..5aa9c65 --- /dev/null +++ b/BOSSBackEnd/pom.xml @@ -0,0 +1,166 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + com.zds + BOSS + 0.0.1-SNAPSHOT + BOSS + BOSS + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.session + spring-session-data-redis + + + org.springframework.boot + spring-boot-starter-web + + + + com.mysql + mysql-connector-j + runtime + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + 4.4.0 + + + + cn.hutool + hutool-all + 5.8.38 + + + + org.springframework.boot + spring-boot-starter-aop + + + org.projectlombok + lombok + 1.18.32 + provided + true + + + + com.fasterxml.jackson.core + jackson-databind + 2.15.2 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + org.springframework.boot + spring-boot-starter-json + + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.9 + + + com.baomidou + mybatis-plus-jsqlparser + 3.5.9 + + + com.baomidou + mybatis-plus-generator + 3.5.9 + + + org.apache.velocity + velocity-engine-core + 2.3 + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-tomcat + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + 1.18.32 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.zds.boss.generator.MyBatisCodeGenerator + + + + + + diff --git a/BOSSBackEnd/sql/add_resume_address.sql b/BOSSBackEnd/sql/add_resume_address.sql new file mode 100644 index 0000000..2a60394 --- /dev/null +++ b/BOSSBackEnd/sql/add_resume_address.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS `resume_address` ( + `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + `user_id` BIGINT UNSIGNED NOT NULL, + `resume_id` BIGINT UNSIGNED NULL, + `address` VARCHAR(512) NOT NULL, + `file_key` VARCHAR(256) NOT NULL, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY `uk_user_resume_pdf` (`user_id`) +) ENGINE=InnoDB COMMENT='用户简历PDF地址表'; diff --git a/BOSSBackEnd/sql/new_structure.sql b/BOSSBackEnd/sql/new_structure.sql new file mode 100644 index 0000000..7d6532e --- /dev/null +++ b/BOSSBackEnd/sql/new_structure.sql @@ -0,0 +1,175 @@ +/* ========================= + Boss 招聘系统 - 重构后全量建表SQL + MySQL 8.x / InnoDB / utf8mb4 + ========================= */ + +CREATE DATABASE IF NOT EXISTS boss + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_0900_ai_ci; + +USE boss; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- 2) 清理 +DROP TABLE IF EXISTS `interview`; +DROP TABLE IF EXISTS `boss_application_decision`; +DROP TABLE IF EXISTS `application`; +DROP TABLE IF EXISTS `job_posting`; +DROP TABLE IF EXISTS `resume`; +DROP TABLE IF EXISTS `company`; +DROP TABLE IF EXISTS `boss`; +DROP TABLE IF EXISTS `admin`; +DROP TABLE IF EXISTS `user`; + +SET FOREIGN_KEY_CHECKS = 1; + +-- ========================= +-- user 用户表 (整合了求职者、Boss、Admin) +-- ========================= +CREATE TABLE `user` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '用户ID', + `user_account` VARCHAR(64) NOT NULL COMMENT '登录名(唯一)', + `password` VARCHAR(255) NOT NULL COMMENT '密码哈希', + `phone` VARCHAR(32) NULL COMMENT '手机号', + `email` VARCHAR(128) NULL COMMENT '邮箱', + `username` VARCHAR(64) NULL COMMENT '昵称/姓名', + `user_role` VARCHAR(20) DEFAULT 'user' NOT NULL COMMENT '用户角色:user-求职者, boss-Boss, admin-管理员', + `company_id` BIGINT UNSIGNED NULL COMMENT '公司ID(仅Boss角色有效)', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `profile` TINYTEXT NULL COMMENT '简介', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL COMMENT '软删:0否 1是', + `deleted_at` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_account` (`user_account`) +) ENGINE=InnoDB COMMENT '用户表'; + +CREATE INDEX `idx_user_role` ON `user` (`user_role`); +CREATE INDEX `idx_user_email` ON `user` (`email`); +CREATE INDEX `idx_user_phone` ON `user` (`phone`); + +-- ========================= +-- company 公司表 +-- ========================= +CREATE TABLE `company` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '公司ID', + `name` VARCHAR(128) NOT NULL COMMENT '公司名', + `industry` VARCHAR(128) NULL COMMENT '行业', + `size_range` VARCHAR(64) NULL COMMENT '规模(如1-50/50-200)', + `website` VARCHAR(255) NULL COMMENT '官网', + `address` VARCHAR(255) NULL COMMENT '地址', + `intro` TEXT NULL COMMENT '公司介绍', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_company_name` (`name`) +) ENGINE=InnoDB COMMENT '公司表'; + +-- ========================= +-- job_posting 岗位表 +-- ========================= +CREATE TABLE `job_posting` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '岗位ID', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT '发布者ID (User ID)', + `company_id` BIGINT UNSIGNED NOT NULL COMMENT '公司ID', + `title` VARCHAR(128) NOT NULL COMMENT '岗位名称', + `location` VARCHAR(128) NULL COMMENT '地点', + `job_type` VARCHAR(64) NULL COMMENT '类型:全职/实习', + `salary_min` INT NULL, + `salary_max` INT NULL, + `description` TEXT NULL COMMENT '描述', + `requirement` TEXT NULL COMMENT '要求', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0草稿 1发布 2关闭', + `publish_at` DATETIME NULL, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT '岗位表'; + +CREATE INDEX `idx_job_boss` ON `job_posting` (`boss_id`); +CREATE INDEX `idx_job_company` ON `job_posting` (`company_id`); + +-- ========================= +-- resume 简历表 +-- ========================= +CREATE TABLE `resume` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '简历ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `resume_title` VARCHAR(128) DEFAULT '默认简历' NOT NULL COMMENT '简历标题', + `is_default` TINYINT DEFAULT 0 NOT NULL COMMENT '是否默认:0否 1是', + `summary` TEXT NULL COMMENT '摘要', + `content` LONGTEXT NULL COMMENT '正文', + `attachment_url` VARCHAR(512) NULL COMMENT '附件URL', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT '简历表'; + +CREATE INDEX `idx_resume_user` ON `resume` (`user_id`); + +-- ========================= +-- application 用户投递记录表 +-- ========================= +CREATE TABLE `application` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '投递ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '求职者ID', + `resume_id` BIGINT UNSIGNED NULL COMMENT '简历ID', + `job_id` BIGINT UNSIGNED NOT NULL COMMENT '岗位ID', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT '招聘者ID (冗余)', + `status` TINYINT DEFAULT 0 NOT NULL COMMENT '状态:0已投递 1已撤回 2已过期 3面试中 4已录用 5已拒绝', + `applied_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '投递时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_apply_user_job` (`user_id`, `job_id`) +) ENGINE=InnoDB COMMENT '用户投递记录表'; + +-- ========================= +-- boss_application_decision Boss处理投递表 +-- ========================= +CREATE TABLE `boss_application_decision` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT 'ID', + `application_id` BIGINT UNSIGNED NOT NULL COMMENT '投递ID', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT '招聘者ID', + `decision` TINYINT NOT NULL COMMENT '处理结果:1接受/进入流程 2拒绝 3待定', + `stage` TINYINT DEFAULT 0 NOT NULL COMMENT '阶段:0筛选 1邀面 2面试 3Offer 4结束', + `note` VARCHAR(512) NULL COMMENT '备注', + `decided_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '处理时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_decision_application` (`application_id`) +) ENGINE=InnoDB COMMENT 'Boss处理投递表'; + +-- ========================= +-- interview 面试安排表 +-- ========================= +CREATE TABLE `interview` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '面试ID', + `application_id` BIGINT UNSIGNED NOT NULL COMMENT '投递ID', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT '招聘者ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '求职者ID', + `interview_time` DATETIME NOT NULL COMMENT '面试时间', + `mode` TINYINT DEFAULT 0 NOT NULL COMMENT '方式:0线上 1线下', + `location` VARCHAR(255) NULL COMMENT '地点/会议链接', + `status` TINYINT DEFAULT 0 NOT NULL COMMENT '状态:0待确认 1已确认 2已完成 3取消 4拒绝', + `note` VARCHAR(512) NULL, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT '面试安排表'; diff --git a/BOSSBackEnd/sql/seed_bulk.sql b/BOSSBackEnd/sql/seed_bulk.sql new file mode 100644 index 0000000..aca395e --- /dev/null +++ b/BOSSBackEnd/sql/seed_bulk.sql @@ -0,0 +1,67 @@ +USE boss; + +-- 批量插入 300 个用户(user_account: bulkuser_001 ~ bulkuser_300),密码均为 11111111(加盐MD5) +SET @n := 0; +INSERT IGNORE INTO `user` (user_account, password, phone, email, username, user_role, company_id, status, profile) +SELECT + CONCAT('bulkuser_', LPAD(@n := @n + 1, 3, '0')) AS user_account, + '9e7b74dc1da0327f18e3a7861929b9bc' AS password, + CONCAT('139', LPAD(@n, 8, '0')) AS phone, + CONCAT('bulkuser_', LPAD(@n, 3, '0'), '@example.com') AS email, + CONCAT('用户', LPAD(@n, 3, '0')) AS username, + 'user' AS user_role, + NULL AS company_id, + 1 AS status, + CONCAT('批量用户', @n, ',用于联调与压力测试') AS profile +FROM information_schema.columns +LIMIT 300; + +-- 为上述 300 个用户各创建 1 份默认简历 +INSERT INTO `resume` (user_id, resume_title, is_default, summary, content, attachment_url) +SELECT u.id, + CONCAT(u.username, '-默认简历') AS resume_title, + 1 AS is_default, + CONCAT(u.username, ':通用技能概述') AS summary, + CONCAT('项目经历:', u.username, ' 参与电商/IM/内容平台等系统开发,具备良好工程实践。') AS content, + '' AS attachment_url +FROM `user` u +WHERE u.user_account LIKE 'bulkuser_%' + AND NOT EXISTS (SELECT 1 FROM resume r WHERE r.user_id = u.id); + +-- 批量为每个用户创建 1 条投递记录,均匀分布到现有岗位 +-- 均匀分布到现有岗位,避免重复键:每个用户选择 (user_id % 岗位数) 对应的职位 +DROP TEMPORARY TABLE IF EXISTS job_index; +CREATE TEMPORARY TABLE job_index (id BIGINT, rn INT); +SET @rn := -1; +INSERT INTO job_index +SELECT jp.id, (@rn := @rn + 1) AS rn +FROM job_posting jp ORDER BY jp.id; +SET @job_cnt := (SELECT COUNT(*) FROM job_index); + +INSERT INTO `application` (user_id, resume_id, job_id, boss_id, status, applied_at) +SELECT + u.id AS user_id, + (SELECT r.id FROM resume r WHERE r.user_id = u.id LIMIT 1) AS resume_id, + ji.id AS job_id, + (SELECT jp.boss_id FROM job_posting jp WHERE jp.id = ji.id) AS boss_id, + 0 AS status, + NOW() AS applied_at +FROM `user` u +JOIN job_index ji ON ji.rn = (u.id % @job_cnt) +WHERE u.user_account LIKE 'bulkuser_%' + AND NOT EXISTS (SELECT 1 FROM application a WHERE a.user_id = u.id); + +-- 可选:为前 50 条批量投递添加 Boss 决策(初筛通过) +-- 为前 50 条批量投递添加 Boss 决策(初筛通过) +INSERT INTO `boss_application_decision` (application_id, boss_id, decision, stage, note, decided_at) +SELECT a.id, + (SELECT jp.boss_id FROM job_posting jp WHERE jp.id = a.job_id) AS boss_id, + 1 AS decision, + 1 AS stage, + '批量初筛通过' AS note, + NOW() AS decided_at +FROM `application` a +JOIN (SELECT id FROM `user` WHERE user_account LIKE 'bulkuser_%' ORDER BY id LIMIT 50) u50 + ON a.user_id = u50.id +WHERE NOT EXISTS (SELECT 1 FROM boss_application_decision d WHERE d.application_id = a.id); + diff --git a/BOSSBackEnd/sql/seed_bulk_real_v1_fixed.sql b/BOSSBackEnd/sql/seed_bulk_real_v1_fixed.sql new file mode 100644 index 0000000..84cebce --- /dev/null +++ b/BOSSBackEnd/sql/seed_bulk_real_v1_fixed.sql @@ -0,0 +1,578 @@ +-- ========================================================== +-- Boss 招聘系统:高真实度种子数据(可重复执行)bulk_real_v1 +-- 说明: +-- 1) 不硬编码任何主键ID;全部通过自然键/查询获取 +-- 2) 幂等:对唯一键用 INSERT IGNORE;对非唯一用 NOT EXISTS +-- 3) utf8mb4:避免中文/emoji 乱码 +-- 4) 数据规模:1000 个求职者 + 20 公司 + 40 Boss + 200 岗位 + 1000 投递 + 部分决策/面试 +-- ========================================================== + +USE boss; +SET NAMES utf8mb4; + +START TRANSACTION; + +-- 种子标记(用于识别/清理:只删带该标记的数据) +SET @SEED_TAG := 'SEED_TAG:bulk_real_v1'; + +-- ---------------------------------------------------------- +-- 1) 构造 1..1000 序列(不使用窗口函数/递归,兼容性更好) +-- ---------------------------------------------------------- +-- ---------------------------------------------------------- +-- 1) 构造 1..1000 序列(兼容“Can't reopen table”环境) +-- 说明:不再多次引用临时表 seed_digits,改用内联 digits +-- ---------------------------------------------------------- +CREATE TEMPORARY TABLE IF NOT EXISTS seed_seq (n INT NOT NULL PRIMARY KEY) ENGINE=MEMORY; +TRUNCATE TABLE seed_seq; + +INSERT INTO seed_seq(n) +SELECT (a.d + b.d*10 + c.d*100 + d4.d*1000) + 1 AS n +FROM + (SELECT 0 d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 + UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a +CROSS JOIN + (SELECT 0 d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 + UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b +CROSS JOIN + (SELECT 0 d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 + UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c +CROSS JOIN + (SELECT 0 d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 + UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) d4 +WHERE (a.d + b.d*10 + c.d*100 + d4.d*1000) < 1000; + + +-- ---------------------------------------------------------- +-- 2) 基础字典:城市/姓名/方向(让数据“像真的”) +-- ---------------------------------------------------------- +CREATE TEMPORARY TABLE IF NOT EXISTS seed_city ( + rn INT PRIMARY KEY, + city VARCHAR(64), + district VARCHAR(64) +) ENGINE=InnoDB; +TRUNCATE TABLE seed_city; +INSERT INTO seed_city(rn, city, district) VALUES +(0,'北京','海淀'),(1,'上海','浦东'),(2,'深圳','南山'),(3,'杭州','滨江'),(4,'广州','天河'), +(5,'成都','高新'),(6,'南京','建邺'),(7,'武汉','光谷'),(8,'西安','高新'),(9,'苏州','工业园'), +(10,'重庆','渝中'),(11,'天津','滨海'),(12,'长沙','岳麓'),(13,'合肥','高新'),(14,'厦门','思明'), +(15,'青岛','崂山'),(16,'宁波','鄞州'),(17,'济南','历下'),(18,'郑州','金水'),(19,'福州','鼓楼'); + +CREATE TEMPORARY TABLE IF NOT EXISTS seed_surname (rn INT PRIMARY KEY, v VARCHAR(16)) ENGINE=InnoDB; +TRUNCATE TABLE seed_surname; +INSERT INTO seed_surname(rn,v) VALUES +(0,'王'),(1,'李'),(2,'张'),(3,'刘'),(4,'陈'),(5,'杨'),(6,'黄'),(7,'赵'),(8,'周'),(9,'吴'), +(10,'徐'),(11,'孙'),(12,'胡'),(13,'朱'),(14,'高'),(15,'林'),(16,'何'),(17,'郭'),(18,'马'),(19,'罗'), +(20,'梁'),(21,'宋'),(22,'郑'),(23,'谢'),(24,'韩'),(25,'唐'),(26,'冯'),(27,'于'),(28,'董'),(29,'萧'); + +CREATE TEMPORARY TABLE IF NOT EXISTS seed_given (rn INT PRIMARY KEY, v VARCHAR(16)) ENGINE=InnoDB; +TRUNCATE TABLE seed_given; +INSERT INTO seed_given(rn,v) VALUES +(0,'子涵'),(1,'雨桐'),(2,'浩然'),(3,'嘉怡'),(4,'宇轩'),(5,'欣怡'),(6,'俊杰'),(7,'梓萱'),(8,'思琪'),(9,'泽宇'), +(10,'晨曦'),(11,'若曦'),(12,'明轩'),(13,'芷晴'),(14,'一凡'),(15,'可欣'),(16,'天宇'),(17,'语嫣'),(18,'书豪'),(19,'梦瑶'), +(20,'佳宁'),(21,'思源'),(22,'安然'),(23,'梓睿'),(24,'昕妍'),(25,'奕辰'),(26,'沐辰'),(27,'心怡'),(28,'知远'),(29,'嘉航'); + +CREATE TEMPORARY TABLE IF NOT EXISTS seed_track ( + rn INT PRIMARY KEY, + track VARCHAR(64), + keywords VARCHAR(255) +) ENGINE=InnoDB; +TRUNCATE TABLE seed_track; +INSERT INTO seed_track(rn,track,keywords) VALUES +(0,'Java后端','Java, Spring Boot, MySQL, Redis, 微服务, MQ'), +(1,'前端工程化','Vue/React, TypeScript, Webpack/Vite, 性能优化'), +(2,'数据分析','SQL, Python, 可视化, 指标体系, A/B Test'), +(3,'测试开发','自动化测试, Java/Python, CI/CD, 性能测试'), +(4,'算法/推荐','Python, 机器学习, 特征工程, 推荐/排序, TensorFlow'), +(5,'产品经理','需求分析, PRD, 数据驱动, 版本迭代, 协作推进'), +(6,'运维/DevOps','Linux, Docker, Kubernetes, 监控告警, 自动化'), +(7,'Android','Kotlin/Java, Jetpack, 性能优化, 组件化'), +(8,'iOS','Swift, UIKit/SwiftUI, 性能优化, 组件化'), +(9,'安全工程','Web安全, 渗透测试, 风控, 安全审计'); + +SET @sn_cnt := (SELECT COUNT(*) FROM seed_surname); +SET @gn_cnt := (SELECT COUNT(*) FROM seed_given); +SET @ct_cnt := (SELECT COUNT(*) FROM seed_city); +SET @tk_cnt := (SELECT COUNT(*) FROM seed_track); + +-- ---------------------------------------------------------- +-- 3) 公司(20家,真实感:行业/规模/官网/地址/介绍) +-- ---------------------------------------------------------- +CREATE TEMPORARY TABLE IF NOT EXISTS seed_company ( + rn INT PRIMARY KEY, + name VARCHAR(128), + industry VARCHAR(128), + size_range VARCHAR(64), + website VARCHAR(255), + city_rn INT, + intro TEXT +) ENGINE=InnoDB; +TRUNCATE TABLE seed_company; + +INSERT INTO seed_company(rn,name,industry,size_range,website,city_rn,intro) VALUES +(0,'星环数据','企业服务','500-2000','https://www.transwarp.cn',1,'面向企业的数据平台与数智化解决方案,覆盖数据治理、湖仓一体与实时分析,强调工程落地与长期交付。'), +(1,'云帆科技','互联网','200-500','https://www.yunfan-tech.example',3,'聚焦电商与内容平台的中台能力建设,提供高可用服务、实时计算与增长工具,注重用户体验与效率。'), +(2,'极光智联','物联网','500-2000','https://www.jiguang-iot.example',2,'服务智慧城市与工业互联网,打造设备接入、边缘计算与安全运维体系,项目覆盖多地政企客户。'), +(3,'海豚互娱','游戏','1000+','https://www.haitun-game.example',1,'移动游戏与互动娱乐公司,重视玩法创新与数据驱动运营,持续投入研发与美术制作管线。'), +(4,'清风医疗','医疗健康','200-500','https://www.qingfeng-med.example',0,'医疗信息化与互联网医院解决方案提供商,围绕诊疗流程、运营管理与数据合规持续迭代。'), +(5,'墨迹物流','物流供应链','500-2000','https://www.moji-logistics.example',18,'专注仓配一体与配送调度优化,建设订单、库存、路径规划与司机端系统,强调稳定与成本效率。'), +(6,'智图视觉','人工智能','200-500','https://www.zhitu-vision.example',8,'计算机视觉与多模态应用团队,落地安防、质检与内容理解,强调算法工程化与模型迭代效率。'), +(7,'蓝鲸金融科技','金融科技','2000-10000','https://www.lanjin-fintech.example',6,'面向银行/保险的数字化产品与风控系统,重视审计合规、可追溯与高可用架构。'), +(8,'微光教育','教育','200-500','https://www.weiguang-edu.example',12,'提供在线学习与教务管理平台,关注课程体验、学习数据与教学运营工具,持续快速迭代。'), +(9,'风筝出行','出行','500-2000','https://www.fengzheng-mobility.example',4,'覆盖打车与同城出行业务,建设订单/计价/派单系统与司机生态,强调实时性与风控。'), +(10,'北斗云安','安全','200-500','https://www.beidou-sec.example',0,'企业安全与风控平台,覆盖账号安全、漏洞治理与安全运营,强调攻防思维与工程落地。'), +(11,'青岚内容','内容社区','500-2000','https://www.qinglan-content.example',7,'内容分发与社区平台,重视推荐、审核与增长实验体系,追求体验与效率的平衡。'), +(12,'橙子零售','新零售','200-500','https://www.chengzi-retail.example',5,'围绕门店数字化、会员体系与供应链协同,构建全渠道交易与运营平台。'), +(13,'图灵硬件','智能硬件','200-500','https://www.turing-hw.example',2,'硬件与软件协同研发团队,覆盖设备固件、App与云端平台,强调质量体系与交付节奏。'), +(14,'森海能源','能源','500-2000','https://www.senhai-energy.example',10,'能源企业数字化团队,建设生产运营系统与数据平台,重视稳定性与安全规范。'), +(15,'远望制造','智能制造','2000-10000','https://www.yuanwang-mfg.example',15,'面向工厂的MES/APS与数据采集平台,强调现场落地与跨部门协作能力。'), +(16,'澜星文旅','文旅','200-500','https://www.lanxing-travel.example',14,'文旅平台与票务系统,覆盖商家入驻、履约与客服体系,注重体验与稳定运营。'), +(17,'沐风房产科技','房产','500-2000','https://www.mufang-prop.example',9,'房产交易与经纪人工具平台,重视搜索推荐、交易安全与服务质量。'), +(18,'鲸准招聘','企业服务','200-500','https://www.jingzhun-hr.example',17,'招聘与组织管理SaaS,覆盖简历、面试、入职与组织协作,强调易用性与数据闭环。'), +(19,'旭日科研','科研服务','50-200','https://www.xuri-research.example',13,'科研数据管理与实验流程平台,服务高校与科研机构,注重权限、合规与可追溯。'); + +-- 插入公司(name 唯一:uk_company_name) +INSERT INTO company(name, industry, size_range, website, address, intro, status, created_at, updated_at, is_deleted) +SELECT sc.name, + sc.industry, + sc.size_range, + sc.website, + CONCAT(ct.city,'·',ct.district), + CONCAT(sc.intro, '(', @SEED_TAG, ')'), + 1, + DATE_SUB(NOW(), INTERVAL (100 + sc.rn*3) DAY), + DATE_SUB(NOW(), INTERVAL (10 + sc.rn) DAY), + 0 +FROM seed_company sc +JOIN seed_city ct ON ct.rn = sc.city_rn +ON DUPLICATE KEY UPDATE updated_at = updated_at; + +-- ---------------------------------------------------------- +-- 4) Boss 用户(40个,均匀绑定公司;不硬编码 company_id) +-- ---------------------------------------------------------- +INSERT IGNORE INTO `user`( + user_account, password, phone, email, username, + user_role, company_id, status, profile, created_at, updated_at, is_deleted +) +SELECT + CONCAT('boss_seed_', LPAD(s.n,3,'0')) AS user_account, + '9e7b74dc1da0327f18e3a7861929b9bc' AS password, + CONCAT('13', LPAD(800000000 + s.n, 9, '0')) AS phone, + CONCAT('boss', LPAD(s.n,3,'0'), '@corp-mail.cn') AS email, + CONCAT(sn.v, gn.v) AS username, + 'boss' AS user_role, + NULL AS company_id, + 1 AS status, + CONCAT( + '负责团队招聘与面试评估,关注候选人基础功与工程习惯;', + '日常会参与需求评审与技术方案讨论,强调沟通效率与结果交付;', + '偏好有项目闭环经验、能快速定位问题并持续学习的同学。 ', + @SEED_TAG + ) AS profile, + DATE_SUB(NOW(), INTERVAL (500 + (s.n % 180)) DAY) AS created_at, + DATE_SUB(NOW(), INTERVAL (60 + (s.n % 30)) DAY) AS updated_at, + 0 AS is_deleted +FROM seed_seq s +JOIN seed_surname sn ON sn.rn = MOD(s.n, @sn_cnt) +JOIN seed_given gn ON gn.rn = MOD(s.n*7, @gn_cnt) +WHERE s.n <= 40; + +-- 绑定 Boss 到公司(通过 company.name,自然键) +UPDATE `user` u +JOIN ( + SELECT + CONCAT('boss_seed_', LPAD(s.n,3,'0')) AS boss_account, + sc.name AS company_name + FROM seed_seq s + JOIN seed_company sc ON sc.rn = MOD(((s.n-1) DIV 2), 20) + WHERE s.n <= 40 +) bm ON bm.boss_account = u.user_account +JOIN company c ON c.name = bm.company_name +SET u.company_id = c.id +WHERE u.user_role='boss' AND (u.company_id IS NULL OR u.company_id=0); + +-- ---------------------------------------------------------- +-- 5) 岗位模板(10类) -> 每家公司 10 个岗位,共 200 +-- ---------------------------------------------------------- +CREATE TEMPORARY TABLE IF NOT EXISTS seed_job_tpl( + rn INT PRIMARY KEY, + title VARCHAR(128), + job_type VARCHAR(64), + salary_min INT, + salary_max INT, + job_desc TEXT, + req TEXT +) ENGINE=InnoDB; +TRUNCATE TABLE seed_job_tpl; + +INSERT INTO seed_job_tpl(rn,title,job_type,salary_min,salary_max,job_desc,req) VALUES +(0,'Java后端工程师','全职',20000,42000, +'你将参与核心业务服务的设计与开发,负责接口设计、数据建模与性能优化;与产品、测试协作推进版本交付,保障线上稳定性与可观测性;有机会参与中台建设与治理体系落地。', +'熟悉Java与常用框架(Spring Boot等),理解HTTP/SQL基础;具备MySQL索引/事务/慢SQL优化经验;了解Redis/消息队列/微服务基本理念,能写出可维护的代码并进行单元测试。'), +(1,'前端工程师(Web)','全职',18000,38000, +'负责Web端功能迭代与工程化建设,推进组件化、性能优化与可用性提升;与后端联调并落地埋点、监控与灰度发布;参与页面体验优化与跨端适配。', +'熟悉Vue/React任一技术栈,掌握TypeScript与常见构建工具;理解浏览器渲染与性能指标,有定位线上问题经验;具备良好代码规范与组件设计能力,能编写单元测试更佳。'), +(2,'数据分析师','全职',16000,32000, +'围绕业务目标搭建指标体系与数据看板,进行专题分析并输出可执行建议;参与A/B实验设计、效果评估与用户行为洞察;与产品/运营协作推动策略落地与复盘。', +'熟练使用SQL进行数据抽取与建模,掌握Python进行分析与可视化;理解常见统计概念与实验方法;具备结构化表达与沟通能力,能够将结论转化为行动方案。'), +(3,'测试开发工程师','全职',16000,30000, +'建设自动化测试与质量平台,完善用例体系、回归流程与持续集成;负责关键链路的稳定性保障、性能压测与缺陷分析;推动研发流程优化与质量度量。', +'熟悉Java/Python任一语言,了解常见测试框架与CI/CD;理解接口/性能/安全基础测试方法;具备问题定位能力与良好沟通推动能力,能持续输出可复用工具。'), +(4,'算法工程师(推荐/排序)','全职',30000,60000, +'参与推荐/搜索相关模型训练与效果迭代,负责特征工程、样本构建与线上服务部署;与业务一起定义指标并进行实验验证;推动模型工程化与成本优化。', +'熟悉机器学习基础与常用算法,掌握Python与至少一种深度学习框架;了解特征工程、评估指标与线上A/B;有大规模数据处理或模型线上化经验更佳。'), +(5,'产品经理','全职',18000,35000, +'负责需求调研、PRD撰写与版本规划,推动研发/设计/测试协作交付;跟踪数据与用户反馈,持续迭代产品体验;参与跨部门沟通协调与目标拆解。', +'具备清晰的结构化思维与沟通能力,能把复杂问题拆解为可执行需求;理解数据分析与基本技术概念;有互联网产品经验或B端协作经验更佳。'), +(6,'DevOps工程师','全职',20000,40000, +'负责服务部署、监控告警与自动化运维,完善发布流程与故障应急预案;推进容器化与基础设施规范化;提升系统可用性、可观测性与发布效率。', +'熟悉Linux与网络基础,掌握Docker/K8s或相关工具;了解监控日志体系(Prometheus/ELK等);具备脚本能力与故障排查经验,安全意识强。'), +(7,'运营专员','全职',12000,22000, +'负责内容/活动/社群运营,制定节奏并跟踪效果;参与用户增长与留存策略设计,沉淀运营方法论;与产品协作推动功能优化与活动落地。', +'具备较强的数据敏感度与执行力,能独立推进活动方案与复盘;熟悉常见运营工具与渠道;沟通协作好,能在不确定中快速迭代。'), +(8,'后端实习生(Java)','实习',3000,8000, +'参与业务模块开发与Bug修复,学习工程规范与协作流程;在导师指导下完成接口开发、单测与文档;有机会参与小型性能优化与工具建设。', +'计算机相关专业优先,具备Java/SQL基础;能使用Git并理解基本开发流程;学习能力强,愿意写文档和单元测试,有项目/竞赛经历更佳。'), +(9,'前端实习生(Web)','实习',3000,8000, +'参与页面功能开发与样式优化,完善组件与工程化配置;在导师指导下完成需求拆解与联调;沉淀可复用的组件/工具。', +'具备HTML/CSS/JavaScript基础,了解Vue/React任一框架;愿意在代码规范与工程化上投入;具备沟通协作意识与持续学习能力。'); + +-- 插入岗位(非唯一表:用 NOT EXISTS 防重复) +INSERT INTO job_posting( + boss_id, company_id, title, location, job_type, + salary_min, salary_max, description, requirement, + status, publish_at, created_at, updated_at, is_deleted +) +SELECT + (SELECT ub.id + FROM `user` ub + WHERE ub.user_role='boss' AND ub.company_id=c.id + ORDER BY ub.id + LIMIT 1) AS boss_id, + c.id AS company_id, + jt.title, + ct.city AS location, + jt.job_type, + jt.salary_min, + jt.salary_max, + CONCAT( + jt.job_desc, + '\n\n福利:五险一金、年度体检、弹性办公、技术分享、带薪年假;', + '\n团队:代码评审+文档规范,强调稳定性与可维护性。', + '\n(', @SEED_TAG, '|COMPANY=', c.name, '|TPL=', LPAD(jt.rn+1,2,'0'), ')' + ) AS description, + CONCAT( + jt.req, + '\n\n加分项:开源贡献/竞赛经历/英文技术文档能力/具备从0到1的项目闭环。' + ) AS requirement, + 1 AS status, + DATE_SUB(NOW(), INTERVAL (MOD((sc.rn*7 + jt.rn*3), 56) + 5) DAY) AS publish_at, + DATE_SUB(NOW(), INTERVAL (MOD((sc.rn*7 + jt.rn*3), 56) + 5) DAY) AS created_at, + DATE_ADD( + DATE_SUB(NOW(), INTERVAL (MOD((sc.rn*7 + jt.rn*3), 56) + 5) DAY), + INTERVAL MOD(jt.rn, 5) DAY + ) AS updated_at, + 0 AS is_deleted +FROM company c +JOIN seed_company sc ON sc.name = c.name +JOIN seed_city ct ON ct.rn = sc.city_rn +JOIN seed_job_tpl jt +WHERE NOT EXISTS ( + SELECT 1 + FROM job_posting j + WHERE j.company_id = c.id + AND j.title = jt.title + AND j.location = ct.city + AND j.job_type = jt.job_type + AND j.salary_min = jt.salary_min + AND j.salary_max = jt.salary_max + AND j.is_deleted = 0 +); + +-- ---------------------------------------------------------- +-- 6) 求职者用户(1000个):bulkuser_0001 ~ bulkuser_1000 +-- ---------------------------------------------------------- +INSERT IGNORE INTO `user`( + user_account, password, phone, email, username, + user_role, company_id, status, profile, created_at, updated_at, is_deleted +) +SELECT + CONCAT('bulkuser_', LPAD(s.n,4,'0')) AS user_account, + '9e7b74dc1da0327f18e3a7861929b9bc' AS password, + CONCAT('13', LPAD(100000000 + s.n, 9, '0')) AS phone, + CONCAT('u', LPAD(s.n,4,'0'), '@mailbox.cn') AS email, + CONCAT(sn.v, gn.v) AS username, + 'user' AS user_role, + NULL AS company_id, + 1 AS status, + CONCAT( + '(', @SEED_TAG, ')', + ' 求职意向:', tk.track, ';', + '技术关键词:', tk.keywords, ';', + '期望城市:', ct.city, ';', + '经验:', CASE + WHEN MOD(s.n,10)=0 THEN '应届/实习经历' + WHEN MOD(s.n,10)=1 THEN '1-3年' + WHEN MOD(s.n,10)=2 THEN '3-5年' + ELSE '2-4年' + END, ';', + '个人特点:学习快、沟通清晰、能把问题拆解并推进到落地,重视代码规范与复盘。 ', + @SEED_TAG + ) AS profile, + DATE_SUB(NOW(), INTERVAL (120 + MOD(s.n, 720)) DAY) AS created_at, + DATE_SUB(NOW(), INTERVAL (5 + MOD(s.n, 60)) DAY) AS updated_at, + 0 AS is_deleted +FROM seed_seq s +JOIN seed_surname sn ON sn.rn = MOD(s.n*3, @sn_cnt) +JOIN seed_given gn ON gn.rn = MOD(s.n*11, @gn_cnt) +JOIN seed_track tk ON tk.rn = MOD(s.n, @tk_cnt) +JOIN seed_city ct ON ct.rn = MOD(s.n*5, @ct_cnt); + +-- ---------------------------------------------------------- +-- 7) 简历:每个求职者至少 1 份默认简历(summary>=50, content>=200) +-- ---------------------------------------------------------- +INSERT INTO resume( + user_id, resume_title, is_default, summary, content, attachment_url, + created_at, updated_at, is_deleted +) +SELECT + u.id, + CONCAT(u.username, ' - 默认简历') AS resume_title, + 1 AS is_default, + CONCAT( + '候选人概述:', u.username, ',目标方向为', tk.track, + ',具备', CASE WHEN MOD(u.id,4)=0 THEN '扎实的基础与良好工程意识' + WHEN MOD(u.id,4)=1 THEN '较强的数据分析与问题拆解能力' + WHEN MOD(u.id,4)=2 THEN '前后端协作经验与交付意识' + ELSE '快速学习与持续复盘习惯' END, + ';期望在', ct.city, '长期发展,重视团队协作与技术成长。 ', @SEED_TAG + ) AS summary, + CONCAT( + '教育背景:\n', + '- 本科:计算机/软件/信息相关专业(2019-2023),核心课程:数据结构、数据库、操作系统、计算机网络。\n\n', + '工作/实习经历:\n', + '- 参与业务需求评审、接口对齐与版本迭代,能在不确定中快速定位关键问题并推动落地。\n', + '- 熟悉基础开发流程:需求->开发->自测->联调->灰度->上线->复盘,重视文档与可维护性。\n\n', + '项目经历:\n', + '- 项目A:订单/内容/会员模块(负责接口设计、数据建模、缓存与慢SQL优化;支持高峰期稳定运行)。\n', + '- 项目B:数据分析/指标看板(使用SQL+Python完成指标体系搭建与自动化报表,支持业务决策)。\n', + '- 项目C:质量与自动化(补齐单测、接口自动化、CI流水线,提升回归效率与稳定性)。\n\n', + '技能清单:\n', + '- ', tk.keywords, ';\n', + '- 通用能力:沟通协作、问题定位、复盘总结、文档表达。\n\n', + '自我评价:\n', + '对结果负责,愿意把事情做“闭环”;遇到问题先定位根因再优化方案;能接受节奏与压力,持续学习新技术并落地到项目中。\n', + '(', @SEED_TAG, ')' + ) AS content, + CASE + WHEN MOD(u.id,10)=0 THEN CONCAT('https://cdn.example.com/resume/', u.user_account, '.pdf') + ELSE NULL + END AS attachment_url, + u.created_at AS created_at, + u.updated_at AS updated_at, + 0 AS is_deleted +FROM `user` u +JOIN seed_track tk ON tk.rn = MOD(u.id, @tk_cnt) +JOIN seed_city ct ON ct.rn = MOD(u.id*3, @ct_cnt) +WHERE u.user_role='user' + AND u.user_account LIKE 'bulkuser_%' + AND NOT EXISTS ( + SELECT 1 FROM resume r + WHERE r.user_id = u.id AND r.is_default=1 AND r.is_deleted=0 + ); + +-- 额外简历(约 30% 用户多一份非默认) +INSERT INTO resume( + user_id, resume_title, is_default, summary, content, attachment_url, + created_at, updated_at, is_deleted +) +SELECT + u.id, + CONCAT(u.username, ' - 投递版简历') AS resume_title, + 0 AS is_default, + CONCAT('投递版摘要:突出与岗位匹配的关键经验与项目闭环,强调可量化结果与协作推进能力。 ', @SEED_TAG) AS summary, + CONCAT( + '核心亮点:\n', + '- 负责过关键模块交付,能独立完成需求拆解、接口设计与联调上线。\n', + '- 有性能与稳定性优化经验:慢SQL分析、缓存策略、监控告警与故障复盘。\n', + '- 注重工程质量:代码规范、单元测试、文档与可维护性。\n\n', + '项目补充:\n', + '- 需求背景、方案选择、数据指标与上线效果复盘,能用数据证明价值。\n', + '- 跨团队沟通:产品/测试/运营协作推进,能对齐目标并落地执行。\n', + '(', @SEED_TAG, ')' + ) AS content, + NULL AS attachment_url, + DATE_SUB(u.created_at, INTERVAL 5 DAY) AS created_at, + u.created_at AS updated_at, + 0 AS is_deleted +FROM `user` u +WHERE u.user_role='user' + AND u.user_account LIKE 'bulkuser_%' + AND MOD(u.id, 10) IN (1,2,3) + AND NOT EXISTS ( + SELECT 1 FROM resume r + WHERE r.user_id = u.id AND r.is_default=0 AND r.is_deleted=0 + AND r.resume_title LIKE '%投递版%' + ); + +-- ---------------------------------------------------------- +-- 8) 投递:1000 条(每个 bulkuser_0001..1000 各投 1 个岗位) +-- - boss_id 必须等于岗位的 boss_id +-- - resume_id 必须属于该 user +-- - applied_at:近 30~45 天分布;updated_at >= applied_at +-- ---------------------------------------------------------- +CREATE TEMPORARY TABLE IF NOT EXISTS job_index ( + id BIGINT UNSIGNED NOT NULL PRIMARY KEY, + rn INT NOT NULL +) ENGINE=MEMORY; +TRUNCATE TABLE job_index; + +SET @rn := -1; +INSERT INTO job_index(id, rn) +SELECT id, (@rn := @rn + 1) AS rn +FROM job_posting +WHERE is_deleted=0 +ORDER BY id; + +SET @job_cnt := (SELECT COUNT(*) FROM job_index); + +-- 若岗位为空则不插入投递(保护) +INSERT IGNORE INTO application( + user_id, resume_id, job_id, boss_id, status, applied_at, updated_at, is_deleted +) +SELECT + u.id AS user_id, + (SELECT r.id + FROM resume r + WHERE r.user_id=u.id AND r.is_deleted=0 + ORDER BY r.is_default DESC, r.id ASC + LIMIT 1) AS resume_id, + j.id AS job_id, + j.boss_id AS boss_id, + CASE + WHEN MOD(s.n, 20)=0 THEN 1 -- 撤回 + WHEN MOD(s.n, 17)=0 THEN 2 -- 过期 + WHEN MOD(s.n, 9)=0 THEN 3 -- 面试中 + WHEN MOD(s.n, 33)=0 THEN 4 -- 已录用 + WHEN MOD(s.n, 25)=0 THEN 5 -- 已拒绝 + ELSE 0 -- 已投递 + END AS status, + DATE_ADD( + DATE_SUB(NOW(), INTERVAL (MOD(s.n*7,16) + 30) DAY), + INTERVAL MOD(s.n*13, 600) MINUTE + ) AS applied_at, + DATE_ADD( + DATE_ADD( + DATE_SUB(NOW(), INTERVAL (MOD(s.n*7,16) + 30) DAY), + INTERVAL MOD(s.n*13, 600) MINUTE + ), + INTERVAL MOD(s.n, 6) DAY + ) AS updated_at, + 0 AS is_deleted +FROM seed_seq s +JOIN `user` u + ON u.user_account = CONCAT('bulkuser_', LPAD(s.n,4,'0')) + AND u.user_account LIKE 'bulkuser_%' +JOIN job_index ji + ON ji.rn = MOD(s.n-1, @job_cnt) +JOIN job_posting j + ON j.id = ji.id +WHERE @job_cnt > 0; + +-- ---------------------------------------------------------- +-- 9) Boss 处理:对约 80% 的投递生成决策(每投递最多 1 条) +-- - decided_at 在 applied_at 后 0~7 天 +-- ---------------------------------------------------------- +INSERT INTO boss_application_decision( + application_id, boss_id, decision, stage, note, decided_at, updated_at, is_deleted +) +SELECT + a.id AS application_id, + a.boss_id, + CASE + WHEN a.status IN (5) THEN 2 -- 已拒绝 + WHEN a.status IN (1,2) THEN 3 -- 撤回/过期 -> 待定 + WHEN MOD(a.id, 9)=0 THEN 3 -- 少量待定 + ELSE 1 -- 进入流程 + END AS decision, + CASE + WHEN a.status=4 THEN 3 -- Offer + WHEN a.status=3 THEN 2 -- 面试 + WHEN MOD(a.id, 6)=0 THEN 1 -- 邀面 + WHEN MOD(a.id, 5)=0 THEN 0 -- 筛选 + ELSE 1 + END AS stage, + CONCAT( + '处理备注:', + CASE + WHEN a.status=5 THEN '匹配度不足,建议后续补齐项目深度与量化结果。' + WHEN a.status=4 THEN '综合表现优秀,进入Offer流程并沟通入职时间。' + WHEN a.status=3 THEN '安排面试流程,重点考察基础、项目细节与协作能力。' + WHEN a.status IN (1,2) THEN '候选人状态变化,暂挂起并记录。' + ELSE '初筛通过,进入下一阶段跟进。' + END, + '(', @SEED_TAG, ')' + ) AS note, + DATE_ADD(a.applied_at, INTERVAL MOD(a.id, 8) DAY) AS decided_at, + DATE_ADD(a.applied_at, INTERVAL MOD(a.id, 8) DAY) AS updated_at, + 0 AS is_deleted +FROM application a +JOIN `user` u ON u.id = a.user_id AND u.user_account LIKE 'bulkuser_%' +WHERE MOD(a.id, 5) <> 0 -- 约 80% 生成决策 + AND NOT EXISTS ( + SELECT 1 FROM boss_application_decision d + WHERE d.application_id = a.id + ); + +-- ---------------------------------------------------------- +-- 10) 面试安排:对部分“邀面/面试阶段”的投递生成面试(未来 2~10 天) +-- ---------------------------------------------------------- +INSERT INTO interview( + application_id, boss_id, user_id, + interview_time, mode, location, status, note, + created_at, updated_at, is_deleted +) +SELECT + a.id AS application_id, + a.boss_id, + a.user_id, + DATE_ADD( + DATE_ADD(NOW(), INTERVAL (MOD(a.id, 9) + 2) DAY), + INTERVAL (MOD(a.id, 8) + 9) HOUR + ) AS interview_time, + CASE WHEN MOD(a.id, 3)=0 THEN 1 ELSE 0 END AS mode, + CASE + WHEN MOD(a.id, 3)=0 THEN CONCAT(c.address, ' ', '(', c.name, ')') + ELSE CONCAT('https://meeting.example.com/', a.id, '?pwd=', LPAD(MOD(a.id*97,10000),4,'0')) + END AS location, + CASE WHEN MOD(a.id, 4)=0 THEN 0 ELSE 1 END AS status, + CONCAT( + '面试说明:请准备自我介绍与最近项目的架构、难点与取舍;', + '线上请提前 10 分钟入会并测试网络设备。 ', + '(', @SEED_TAG, ')' + ) AS note, + NOW() AS created_at, + NOW() AS updated_at, + 0 AS is_deleted +FROM boss_application_decision d +JOIN application a ON a.id = d.application_id +JOIN job_posting j ON j.id = a.job_id +JOIN company c ON c.id = j.company_id +JOIN `user` u ON u.id = a.user_id AND u.user_account LIKE 'bulkuser_%' +WHERE d.decision = 1 + AND d.stage >= 1 + AND MOD(a.id, 2)=0 -- 约 50% 生成面试 + AND NOT EXISTS ( + SELECT 1 FROM interview i + WHERE i.application_id = a.id AND i.is_deleted=0 + ); + +COMMIT; + +-- 可选:快速检查(执行后你也可以手动跑) +-- SELECT COUNT(*) FROM `user` WHERE profile LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM company WHERE intro LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM job_posting WHERE description LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM resume WHERE content LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM application a JOIN `user` u ON u.id=a.user_id WHERE u.profile LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM boss_application_decision d JOIN application a ON a.id=d.application_id JOIN `user` u ON u.id=a.user_id WHERE u.profile LIKE '%SEED_TAG:bulk_real_v1%'; +-- SELECT COUNT(*) FROM interview i JOIN application a ON a.id=i.application_id JOIN `user` u ON u.id=a.user_id WHERE u.profile LIKE '%SEED_TAG:bulk_real_v1%'; diff --git a/BOSSBackEnd/sql/sql.sql b/BOSSBackEnd/sql/sql.sql new file mode 100644 index 0000000..f6dc936 --- /dev/null +++ b/BOSSBackEnd/sql/sql.sql @@ -0,0 +1,238 @@ +/* ========================= + Boss 招聘系统 - 全量建表SQL(无外键) + MySQL 8.x / InnoDB / utf8mb4 + ========================= */ + +-- 1) 建库(可选:你已有库就注释掉) +CREATE DATABASE IF NOT EXISTS boss + DEFAULT CHARACTER SET utf8mb4 + DEFAULT COLLATE utf8mb4_0900_ai_ci; + +USE boss; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- 2) 清理(按依赖大致逆序,避免报错) +DROP TABLE IF EXISTS `interview`; +DROP TABLE IF EXISTS `boss_application_decision`; +DROP TABLE IF EXISTS `application`; +DROP TABLE IF EXISTS `job_posting`; +DROP TABLE IF EXISTS `resume`; +DROP TABLE IF EXISTS `company`; +DROP TABLE IF EXISTS `boss`; +DROP TABLE IF EXISTS `admin`; +DROP TABLE IF EXISTS `user`; + +SET FOREIGN_KEY_CHECKS = 1; + +-- ========================= +-- admin 管理员表 +-- ========================= +CREATE TABLE `admin` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '管理员ID', + `username` VARCHAR(64) NOT NULL COMMENT '登录名(唯一)', + `password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希', + `admin_name` VARCHAR(64) NULL COMMENT '管理员姓名', + `phone` VARCHAR(32) NULL, + `email` VARCHAR(128) NULL, + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + `deleted_at` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_admin_username` (`username`) +) ENGINE=InnoDB COMMENT '管理员表'; + +CREATE INDEX `idx_admin_status` ON `admin` (`status`, `created_at`); + +-- ========================= +-- user 候选人用户表(注意:user 用反引号) +-- ========================= +CREATE TABLE `user` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '用户ID', + `user_account` VARCHAR(64) NOT NULL COMMENT '登录名(唯一)', + `password` VARCHAR(255) NOT NULL COMMENT '密码哈希', + `phone` VARCHAR(32) NULL COMMENT '手机号', + `email` VARCHAR(128) NULL COMMENT '邮箱', + `username` VARCHAR(64) NULL COMMENT '昵称', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL COMMENT '软删:0否 1是', + `deleted_at` DATETIME NULL, + `profile` TINYTEXT NULL COMMENT '简介', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_username` (`user_account`) +) ENGINE=InnoDB COMMENT '候选人用户表'; + +CREATE INDEX `idx_user_email` ON `user` (`email`); +CREATE INDEX `idx_user_phone` ON `user` (`phone`); +CREATE INDEX `idx_user_status` ON `user` (`status`, `created_at`); + +-- ========================= +-- company 公司表 +-- ========================= +CREATE TABLE `company` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '公司ID', + `name` VARCHAR(128) NOT NULL COMMENT '公司名', + `industry` VARCHAR(128) NULL COMMENT '行业', + `size_range` VARCHAR(64) NULL COMMENT '规模(如1-50/50-200)', + `website` VARCHAR(255) NULL COMMENT '官网', + `address` VARCHAR(255) NULL COMMENT '地址', + `intro` TEXT NULL COMMENT '公司介绍', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_company_name` (`name`) +) ENGINE=InnoDB COMMENT '公司表'; + +CREATE INDEX `idx_company_industry` ON `company` (`industry`); +CREATE INDEX `idx_company_status` ON `company` (`status`, `created_at`); + +-- ========================= +-- boss 招聘方账号表 +-- ========================= +CREATE TABLE `boss` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT 'BossID', + `username` VARCHAR(64) NOT NULL COMMENT '登录名(唯一)', + `password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希', + `boss_name` VARCHAR(64) NULL COMMENT '负责人姓名', + `phone` VARCHAR(32) NULL COMMENT '手机号', + `email` VARCHAR(128) NULL COMMENT '邮箱', + `company_id` BIGINT UNSIGNED NULL COMMENT '公司ID(无外键,建议配公司表)', + `company_name` VARCHAR(128) NULL COMMENT '公司名(冗余字段,方便展示)', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0禁用 1正常', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + `deleted_at` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_boss_username` (`username`) +) ENGINE=InnoDB COMMENT 'Boss招聘方账号表'; + +CREATE INDEX `idx_boss_company` ON `boss` (`company_id`); +CREATE INDEX `idx_boss_email` ON `boss` (`email`); +CREATE INDEX `idx_boss_phone` ON `boss` (`phone`); + +-- ========================= +-- job_posting 岗位表 +-- ========================= +CREATE TABLE `job_posting` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '岗位ID', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT 'BossID(无外键)', + `company_id` BIGINT UNSIGNED NULL COMMENT '公司ID(无外键)', + `title` VARCHAR(128) NOT NULL COMMENT '岗位名称', + `location` VARCHAR(128) NULL COMMENT '地点', + `job_type` VARCHAR(64) NULL COMMENT '类型:全职/实习', + `salary_min` INT NULL, + `salary_max` INT NULL, + `description` TEXT NULL COMMENT '描述', + `requirement` TEXT NULL COMMENT '要求', + `status` TINYINT DEFAULT 1 NOT NULL COMMENT '状态:0草稿 1发布 2关闭', + `publish_at` DATETIME NULL, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT '岗位表'; + +CREATE INDEX `idx_job_boss` ON `job_posting` (`boss_id`, `status`, `publish_at`); +CREATE INDEX `idx_job_company` ON `job_posting` (`company_id`, `status`, `publish_at`); +CREATE INDEX `idx_job_status_time` ON `job_posting` (`status`, `publish_at`); +CREATE INDEX `idx_job_title` ON `job_posting` (`title`); + +-- ========================= +-- resume 简历表 +-- ========================= +CREATE TABLE `resume` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '简历ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID(无外键)', + `resume_title` VARCHAR(128) DEFAULT '默认简历' NOT NULL COMMENT '简历标题', + `is_default` TINYINT DEFAULT 0 NOT NULL COMMENT '是否默认:0否 1是', + `summary` TEXT NULL COMMENT '摘要', + `content` LONGTEXT NULL COMMENT '正文(可存Markdown/JSON/HTML)', + `attachment_url` VARCHAR(512) NULL COMMENT '附件URL(PDF/Word)', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `is_deleted` TINYINT DEFAULT 0 NOT NULL, + `deleted_at` DATETIME NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT '简历表'; + +CREATE INDEX `idx_resume_user` ON `resume` (`user_id`, `created_at`); +CREATE INDEX `idx_resume_user_default` ON `resume` (`user_id`, `is_default`); + +-- ========================= +-- application 用户投递记录表 +-- ========================= +CREATE TABLE `application` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '投递ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID(无外键)', + `resume_id` BIGINT UNSIGNED NULL COMMENT '简历ID(无外键,可为空)', + `job_id` BIGINT UNSIGNED NULL COMMENT '岗位ID(无外键,建议配岗位表)', + `boss_id` BIGINT UNSIGNED NULL COMMENT 'BossID(无外键,冗余字段便于查)', + `status` TINYINT DEFAULT 0 NOT NULL COMMENT '状态:0已投递 1已撤回 2已过期', + `applied_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '投递时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_apply_user_job` (`user_id`, `job_id`) +) ENGINE=InnoDB COMMENT '用户投递记录表'; + +CREATE INDEX `idx_apply_boss_time` ON `application` (`boss_id`, `applied_at`); +CREATE INDEX `idx_apply_job_time` ON `application` (`job_id`, `applied_at`); +CREATE INDEX `idx_apply_status` ON `application` (`status`, `applied_at`); +CREATE INDEX `idx_apply_user_time` ON `application` (`user_id`, `applied_at`); + +-- ========================= +-- boss_application_decision Boss处理投递表 +-- ========================= +CREATE TABLE `boss_application_decision` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT 'ID', + `application_id` BIGINT UNSIGNED NOT NULL COMMENT '投递ID(无外键)', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT 'BossID(无外键)', + `decision` TINYINT NOT NULL COMMENT '处理结果:1接受/进入流程 2拒绝 3待定', + `stage` TINYINT DEFAULT 0 NOT NULL COMMENT '阶段:0筛选 1邀面 2面试 3Offer 4结束', + `note` VARCHAR(512) NULL COMMENT '备注', + `decided_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '处理时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_decision_application` (`application_id`) +) ENGINE=InnoDB COMMENT 'Boss处理投递(接受/拒绝)表'; + +CREATE INDEX `idx_decision_boss_time` ON `boss_application_decision` (`boss_id`, `decided_at`); +CREATE INDEX `idx_decision_decision` ON `boss_application_decision` (`decision`, `decided_at`); +CREATE INDEX `idx_decision_stage` ON `boss_application_decision` (`stage`, `decided_at`); + +-- ========================= +-- interview 面试安排表 +-- ========================= +CREATE TABLE `interview` +( + `id` BIGINT UNSIGNED AUTO_INCREMENT COMMENT '面试ID', + `application_id` BIGINT UNSIGNED NOT NULL COMMENT '投递ID(无外键)', + `boss_id` BIGINT UNSIGNED NOT NULL COMMENT 'BossID(无外键)', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID(无外键)', + `interview_time` DATETIME NOT NULL COMMENT '面试时间', + `mode` TINYINT DEFAULT 0 NOT NULL COMMENT '方式:0线上 1线下', + `location` VARCHAR(255) NULL COMMENT '地点/会议链接', + `status` TINYINT DEFAULT 0 NOT NULL COMMENT '状态:0待确认 1已确认 2已完成 3取消', + `note` VARCHAR(512) NULL, + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_interview_app` (`application_id`) +) ENGINE=InnoDB COMMENT '面试安排表'; + +CREATE INDEX `idx_interview_boss_time` ON `interview` (`boss_id`, `interview_time`); +CREATE INDEX `idx_interview_status` ON `interview` (`status`, `interview_time`); +CREATE INDEX `idx_interview_user_time` ON `interview` (`user_id`, `interview_time`); diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/BossApplication.java b/BOSSBackEnd/src/main/java/com/zds/boss/BossApplication.java new file mode 100644 index 0000000..d4fa088 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/BossApplication.java @@ -0,0 +1,15 @@ +package com.zds.boss; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.zds.boss.mapper") +public class BossApplication { + + public static void main(String[] args) { + SpringApplication.run(BossApplication.class, args); + } + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/annotation/AuthCheck.java b/BOSSBackEnd/src/main/java/com/zds/boss/annotation/AuthCheck.java new file mode 100644 index 0000000..9c3f420 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/annotation/AuthCheck.java @@ -0,0 +1,21 @@ +package com.zds.boss.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 权限校验注解 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthCheck { + + /** + * 必须具有哪个角色 + * + * @return + */ + String mustRole() default ""; +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/aop/AuthInterceptor.java b/BOSSBackEnd/src/main/java/com/zds/boss/aop/AuthInterceptor.java new file mode 100644 index 0000000..518c71d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/aop/AuthInterceptor.java @@ -0,0 +1,83 @@ +package com.zds.boss.aop; + +import com.zds.boss.annotation.AuthCheck; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.service.UserService; +import com.zds.boss.utils.UserUtils; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 权限校验 AOP + */ +@Aspect +@Component +public class AuthInterceptor { + + @Resource + private UserService userService; + + /** + * 执行拦截 + * + * @param joinPoint + * @param authCheck + * @return + */ + @Around("@annotation(authCheck)") + public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable { + String mustRole = authCheck.mustRole(); + RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); + HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); + + // 当前登录用户 + User loginUser = userService.getLoginUser(request); + + // 必须有该权限才通过 + if (mustRole != null && !mustRole.isEmpty()) { + UserRoleEnum mustUserRoleEnum = UserRoleEnum.getEnumByValue(mustRole); + if (mustUserRoleEnum == null) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 状态:0禁用 1正常 + Integer status = loginUser.getStatus(); + // 如果被封号,直接拒绝 + if (status != null && status == 0) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + + String userRole = loginUser.getUserRole(); + + // 如果是管理员,直接放行 + if (UserRoleEnum.ADMIN.getValue().equals(userRole)) { + return joinPoint.proceed(); + } + + // 如果需要管理员权限 + if (UserRoleEnum.ADMIN.equals(mustUserRoleEnum)) { + if (!UserRoleEnum.ADMIN.getValue().equals(userRole)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + + // 如果需要 Boss 权限 + if (UserRoleEnum.BOSS.equals(mustUserRoleEnum)) { + if (!UserRoleEnum.BOSS.getValue().equals(userRole)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + } + // 通过权限校验,放行 + return joinPoint.proceed(); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/common/BaseResponse.java b/BOSSBackEnd/src/main/java/com/zds/boss/common/BaseResponse.java new file mode 100644 index 0000000..a92c739 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/common/BaseResponse.java @@ -0,0 +1,30 @@ +package com.zds.boss.common; + +import com.zds.boss.exception.ErrorCode; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class BaseResponse implements Serializable { + + private int code; + + private T data; + + private String message; + + public BaseResponse(int code, T data, String message) { + this.code = code; + this.data = data; + this.message = message; + } + + public BaseResponse(int code, T data) { + this(code, data, ""); + } + + public BaseResponse(ErrorCode errorCode) { + this(errorCode.getCode(), null, errorCode.getMessage()); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/common/DeleteRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/common/DeleteRequest.java new file mode 100644 index 0000000..26cbe0d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/common/DeleteRequest.java @@ -0,0 +1,16 @@ +package com.zds.boss.common; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class DeleteRequest implements Serializable { + + /** + * id + */ + private Long id; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/common/PageRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/common/PageRequest.java new file mode 100644 index 0000000..880a4bc --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/common/PageRequest.java @@ -0,0 +1,27 @@ +package com.zds.boss.common; + +import lombok.Data; + +@Data +public class PageRequest { + + /** + * 当前页号 + */ + private int current = 1; + + /** + * 页面大小 + */ + private int pageSize = 10; + + /** + * 排序字段 + */ + private String sortField; + + /** + * 排序顺序(默认降序) + */ + private String sortOrder = "descend"; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/common/ResultUtils.java b/BOSSBackEnd/src/main/java/com/zds/boss/common/ResultUtils.java new file mode 100644 index 0000000..f8efa87 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/common/ResultUtils.java @@ -0,0 +1,48 @@ +package com.zds.boss.common; + +import com.zds.boss.exception.ErrorCode; + +public class ResultUtils { + + /** + * 成功 + * + * @param data 数据 + * @param 数据类型 + * @return 响应 + */ + public static BaseResponse success(T data) { + return new BaseResponse<>(0, data, "ok"); + } + + /** + * 失败 + * + * @param errorCode 错误码 + * @return 响应 + */ + public static BaseResponse error(ErrorCode errorCode) { + return new BaseResponse<>(errorCode); + } + + /** + * 失败 + * + * @param code 错误码 + * @param message 错误信息 + * @return 响应 + */ + public static BaseResponse error(int code, String message) { + return new BaseResponse<>(code, null, message); + } + + /** + * 失败 + * + * @param errorCode 错误码 + * @return 响应 + */ + public static BaseResponse error(ErrorCode errorCode, String message) { + return new BaseResponse<>(errorCode.getCode(), null, message); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/config/CorsConfig.java b/BOSSBackEnd/src/main/java/com/zds/boss/config/CorsConfig.java new file mode 100644 index 0000000..fc7ca39 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/config/CorsConfig.java @@ -0,0 +1,27 @@ +package com.zds.boss.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +public class CorsConfig { + + @Bean + public CorsFilter corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + config.addAllowedOrigin("http://localhost:5174"); + config.addAllowedOrigin("http://localhost:5173"); + config.setAllowCredentials(true); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + config.setMaxAge(3600L); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/config/MultipartConfig.java b/BOSSBackEnd/src/main/java/com/zds/boss/config/MultipartConfig.java new file mode 100644 index 0000000..958cf87 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/config/MultipartConfig.java @@ -0,0 +1,48 @@ +package com.zds.boss.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.unit.DataSize; +import org.springframework.web.multipart.support.StandardServletMultipartResolver; + +import jakarta.servlet.MultipartConfigElement; + +@Configuration +@Slf4j +public class MultipartConfig { + + /** + * 配置 multipart 解析器 + * 解决 "no multipart boundary was found" 错误 + * 延迟解析可以避免在请求处理前就尝试解析,从而避免 boundary 错误 + */ + @Bean(name = "multipartResolver") + public StandardServletMultipartResolver multipartResolver() { + StandardServletMultipartResolver resolver = new StandardServletMultipartResolver(); + resolver.setResolveLazily(true); // 延迟解析,避免在请求处理前就解析 + log.info("配置 StandardServletMultipartResolver,启用延迟解析"); + return resolver; + } + + /** + * 配置 multipart 文件上传参数 + * 这个配置会被 Spring Boot 自动应用 + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + // 单个文件最大大小 + factory.setMaxFileSize(DataSize.ofMegabytes(10)); + // 总请求大小 + factory.setMaxRequestSize(DataSize.ofMegabytes(10)); + // 文件写入磁盘的阈值(超过此大小会写入临时文件) + factory.setFileSizeThreshold(DataSize.ofMegabytes(1)); + + MultipartConfigElement config = factory.createMultipartConfig(); + log.info("配置 MultipartConfigElement,最大文件大小: 10MB,最大请求大小: 10MB,文件大小阈值: 1MB"); + return config; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/config/MyBatisPlusConfig.java b/BOSSBackEnd/src/main/java/com/zds/boss/config/MyBatisPlusConfig.java new file mode 100644 index 0000000..caa515f --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/config/MyBatisPlusConfig.java @@ -0,0 +1,25 @@ +package com.zds.boss.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * MyBatis-Plus 配置类 + */ +@Configuration +public class MyBatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/config/WebConfig.java b/BOSSBackEnd/src/main/java/com/zds/boss/config/WebConfig.java new file mode 100644 index 0000000..cef28b4 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/config/WebConfig.java @@ -0,0 +1,81 @@ +package com.zds.boss.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import jakarta.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; + +/** + * Web配置类 + * 配置静态资源访问 + */ +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Value("${file.storage.path:src/main/resources/static}") + private String fileStoragePath; + + @Autowired + private ResourceLoader resourceLoader; + + private String staticResourcePath; + + /** + * 初始化静态资源路径 + */ + @PostConstruct + public void init() { + try { + // 尝试获取classpath下的static目录 + Resource resource = resourceLoader.getResource("classpath:/static/"); + try { + File staticDir = resource.getFile(); + staticResourcePath = staticDir.getAbsolutePath(); + } catch (IOException e) { + // 如果在jar包中,使用项目根目录 + String projectRoot = System.getProperty("user.dir"); + File staticDir = new File(projectRoot, "src/main/resources/static"); + if (!staticDir.exists()) { + staticDir = new File(projectRoot, "target/classes/static"); + } + staticResourcePath = staticDir.getAbsolutePath(); + } + } catch (Exception e) { + // 降级方案:使用项目根目录 + String projectRoot = System.getProperty("user.dir"); + staticResourcePath = new File(projectRoot, "src/main/resources/static").getAbsolutePath(); + } + } + + /** + * 配置静态资源访问 + * 使 src/main/resources/static 目录下的文件可以通过 HTTP 访问 + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 配置 /static/** 映射到 src/main/resources/static 目录 + // 优先使用文件系统路径,如果不存在则使用classpath + if (staticResourcePath != null) { + String absolutePath = staticResourcePath.replace("\\", "/"); + if (!absolutePath.endsWith("/")) { + absolutePath += "/"; + } + registry.addResourceHandler("/static/**") + .addResourceLocations("file:" + absolutePath) + .setCachePeriod(3600); // 缓存1小时 + } + + // 同时支持 classpath 下的 static 目录(作为备用) + registry.addResourceHandler("/static/**") + .addResourceLocations("classpath:/static/") + .setCachePeriod(3600); + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/constant/UserConstant.java b/BOSSBackEnd/src/main/java/com/zds/boss/constant/UserConstant.java new file mode 100644 index 0000000..4e1ae2d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/constant/UserConstant.java @@ -0,0 +1,24 @@ +package com.zds.boss.constant; + + +public interface UserConstant { + + /** + * 用户登录态键 + */ + String USER_LOGIN_STATE = "user_login"; + + // region 权限 + + /** + * 默认角色 + */ + String DEFAULT_ROLE = "user"; + + /** + * 管理员角色 + */ + String ADMIN_ROLE = "admin"; + + // endregion +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/ApplicationController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/ApplicationController.java new file mode 100644 index 0000000..4613fe5 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/ApplicationController.java @@ -0,0 +1,103 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.dto.application.ApplicationAddRequest; +import com.zds.boss.model.dto.application.ApplicationQueryRequest; +import com.zds.boss.model.dto.application.ApplicationUpdateRequest; +import com.zds.boss.model.entity.Application; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.ApplicationVO; +import com.zds.boss.service.ApplicationService; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/application") +@Slf4j +public class ApplicationController { + + @Resource + private ApplicationService applicationService; + + @Resource + private UserService userService; + + @PostMapping("/add") + public BaseResponse addApplication(@RequestBody ApplicationAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + long id = applicationService.addApplication(addRequest, loginUser); + return ResultUtils.success(id); + } + + @PostMapping("/delete") + public BaseResponse deleteApplication(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + boolean res = applicationService.deleteApplication(deleteRequest.getId(), loginUser); + return ResultUtils.success(res); + } + + @PostMapping("/update") + public BaseResponse updateApplication(@RequestBody ApplicationUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + boolean res = applicationService.updateApplication(updateRequest, loginUser); + return ResultUtils.success(res); + } + + @GetMapping("/get") + public BaseResponse getApplicationById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Application app = applicationService.getById(id); + return ResultUtils.success(app); + } + + @GetMapping("/get/vo") + public BaseResponse getApplicationVOById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Application app = applicationService.getById(id); + return ResultUtils.success(applicationService.getApplicationVO(app)); + } + + @PostMapping("/list/page/vo") + public BaseResponse> listApplicationVOByPage(@RequestBody ApplicationQueryRequest queryRequest, HttpServletRequest request) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + + if (!isAdmin) { + if (UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole())) { + queryRequest.setBossId(loginUser.getId()); + } else { + queryRequest.setUserId(loginUser.getId()); + } + } + + Page page = applicationService.listApplicationVOByPage(queryRequest); + return ResultUtils.success(page); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossApplicationDecisionController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossApplicationDecisionController.java new file mode 100644 index 0000000..29465b4 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossApplicationDecisionController.java @@ -0,0 +1,81 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.dto.decision.BossApplicationDecisionAddRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionQueryRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionUpdateRequest; +import com.zds.boss.model.entity.BossApplicationDecision; +import com.zds.boss.model.vo.BossApplicationDecisionVO; +import com.zds.boss.service.BossApplicationDecisionService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; +import jakarta.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("/decision") +@Slf4j +public class BossApplicationDecisionController { + + @Resource + private BossApplicationDecisionService decisionService; + + @PostMapping("/add") + public BaseResponse addDecision(@RequestBody BossApplicationDecisionAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long id = decisionService.addDecision(addRequest, request); + return ResultUtils.success(id); + } + + @PostMapping("/delete") + public BaseResponse deleteDecision(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = decisionService.deleteDecision(deleteRequest.getId(), request); + return ResultUtils.success(res); + } + + @PostMapping("/update") + public BaseResponse updateDecision(@RequestBody BossApplicationDecisionUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = decisionService.updateDecision(updateRequest, request); + return ResultUtils.success(res); + } + + @GetMapping("/get") + public BaseResponse getDecisionById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + BossApplicationDecision decision = decisionService.getById(id); + return ResultUtils.success(decision); + } + + @GetMapping("/get/vo") + public BaseResponse getDecisionVOById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + BossApplicationDecision decision = decisionService.getById(id); + return ResultUtils.success(decisionService.getDecisionVO(decision)); + } + + @PostMapping("/list/page/vo") + public BaseResponse> listDecisionVOByPage(@RequestBody BossApplicationDecisionQueryRequest queryRequest) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Page page = decisionService.listDecisionVOByPage(queryRequest); + return ResultUtils.success(page); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossController.java new file mode 100644 index 0000000..b655bc7 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/BossController.java @@ -0,0 +1,31 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.UserVO; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/boss") +public class BossController { + + @Resource + private UserService userService; + + @GetMapping("/list") + public BaseResponse> listBoss() { + List userList = userService.list(new QueryWrapper<>(new User()).eq("user_role", UserRoleEnum.BOSS.getValue())); + List userVOList = userService.getUserVOList(userList); + return ResultUtils.success(userVOList); + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/CompanyController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/CompanyController.java new file mode 100644 index 0000000..00fa3f3 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/CompanyController.java @@ -0,0 +1,89 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.annotation.AuthCheck; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.dto.company.CompanyAddRequest; +import com.zds.boss.model.dto.company.CompanyQueryRequest; +import com.zds.boss.model.dto.company.CompanyUpdateRequest; +import com.zds.boss.model.entity.Company; +import com.zds.boss.model.vo.CompanyVO; +import com.zds.boss.service.CompanyService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import jakarta.servlet.http.HttpServletRequest; + +@RestController +@RequestMapping("/company") +@Slf4j +public class CompanyController { + + @Resource + private CompanyService companyService; + + @PostMapping("/add") + public BaseResponse addCompany(@RequestBody CompanyAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long id = companyService.addCompany(addRequest, request); + return ResultUtils.success(id); + } + + @PostMapping("/delete") + public BaseResponse deleteCompany(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = companyService.deleteCompany(deleteRequest.getId(), request); + return ResultUtils.success(res); + } + + @PostMapping("/update") + public BaseResponse updateCompany(@RequestBody CompanyUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = companyService.updateCompany(updateRequest, request); + return ResultUtils.success(res); + } + + @GetMapping("/get") + public BaseResponse getCompanyById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Company company = companyService.getById(id); + return ResultUtils.success(company); + } + + @GetMapping("/get/vo") + public BaseResponse getCompanyVOById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Company company = companyService.getById(id); + return ResultUtils.success(companyService.getCompanyVO(company)); + } + + @PostMapping("/list/page/vo") + public BaseResponse> listCompanyVOByPage(@RequestBody CompanyQueryRequest queryRequest) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long size = queryRequest.getPageSize(); + if (size > 50) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "分页大小过大"); + } + Page page = companyService.listCompanyVOByPage(queryRequest); + return ResultUtils.success(page); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/InterviewController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/InterviewController.java new file mode 100644 index 0000000..be44811 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/InterviewController.java @@ -0,0 +1,85 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.annotation.AuthCheck; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.dto.interview.InterviewAddRequest; +import com.zds.boss.model.dto.interview.InterviewQueryRequest; +import com.zds.boss.model.dto.interview.InterviewUpdateRequest; +import com.zds.boss.model.entity.Interview; +import com.zds.boss.model.vo.InterviewVO; +import com.zds.boss.service.InterviewService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/interview") +@Slf4j +public class InterviewController { + + @Resource + private InterviewService interviewService; + + @PostMapping("/add") + public BaseResponse addInterview(@RequestBody InterviewAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long id = interviewService.addInterview(addRequest, request); + return ResultUtils.success(id); + } + + @PostMapping("/delete") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse deleteInterview(@RequestBody DeleteRequest deleteRequest) { + if (deleteRequest == null || deleteRequest.getId() == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = interviewService.deleteInterview(deleteRequest.getId()); + return ResultUtils.success(res); + } + + @PostMapping("/update") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse updateInterview(@RequestBody InterviewUpdateRequest updateRequest) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = interviewService.updateInterview(updateRequest); + return ResultUtils.success(res); + } + + @GetMapping("/get") + public BaseResponse getInterviewById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Interview e = interviewService.getById(id); + return ResultUtils.success(e); + } + + @GetMapping("/get/vo") + public BaseResponse getInterviewVOById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Interview e = interviewService.getById(id); + return ResultUtils.success(interviewService.getInterviewVO(e)); + } + + @PostMapping("/list/page/vo") + public BaseResponse> listInterviewVOByPage(@RequestBody InterviewQueryRequest queryRequest) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Page page = interviewService.listInterviewVOByPage(queryRequest); + return ResultUtils.success(page); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/JobPostingController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/JobPostingController.java new file mode 100644 index 0000000..57d8e35 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/JobPostingController.java @@ -0,0 +1,83 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.annotation.AuthCheck; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.model.dto.job.JobPostingAddRequest; +import com.zds.boss.model.dto.job.JobPostingQueryRequest; +import com.zds.boss.model.dto.job.JobPostingUpdateRequest; +import com.zds.boss.model.entity.JobPosting; +import com.zds.boss.model.vo.JobPostingVO; +import com.zds.boss.service.JobPostingService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/job") +@Slf4j +public class JobPostingController { + + @Resource + private JobPostingService jobPostingService; + + @PostMapping("/add") + public BaseResponse addJob(@RequestBody JobPostingAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long id = jobPostingService.addJobPosting(addRequest, request); + return ResultUtils.success(id); + } + + @PostMapping("/delete") + public BaseResponse deleteJob(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = jobPostingService.deleteJobPosting(deleteRequest.getId(), request); + return ResultUtils.success(res); + } + + @PostMapping("/update") + public BaseResponse updateJob(@RequestBody JobPostingUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean res = jobPostingService.updateJobPosting(updateRequest, request); + return ResultUtils.success(res); + } + + @GetMapping("/get") + public BaseResponse getJobById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + JobPosting job = jobPostingService.getById(id); + return ResultUtils.success(job); + } + + @GetMapping("/get/vo") + public BaseResponse getJobVOById(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + JobPosting job = jobPostingService.getById(id); + return ResultUtils.success(jobPostingService.getJobPostingVO(job)); + } + + @PostMapping("/list/page/vo") + public BaseResponse> listJobVOByPage(@RequestBody JobPostingQueryRequest queryRequest) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Page page = jobPostingService.listJobPostingVOByPage(queryRequest); + return ResultUtils.success(page); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/ResumeController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/ResumeController.java new file mode 100644 index 0000000..4b10316 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/ResumeController.java @@ -0,0 +1,225 @@ +package com.zds.boss.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.exception.ThrowUtils; +import com.zds.boss.model.dto.resume.ResumeAddRequest; +import com.zds.boss.model.dto.resume.ResumeQueryRequest; +import com.zds.boss.model.dto.resume.ResumeUpdateRequest; +import com.zds.boss.model.entity.Resume; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.ResumeVO; +import com.zds.boss.service.FileService; +import com.zds.boss.service.ResumeService; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.UUID; + +/** + * 简历接口 + */ +@RestController +@RequestMapping("/resume") +@Slf4j +public class ResumeController { + + @Resource + private ResumeService resumeService; + + @Resource + private UserService userService; + + @Resource + private FileService fileService; + + @Value("${file.max-size-mb:10}") + private long maxSizeMb; + + /** + * 创建简历 + * + * @param resumeAddRequest + * @param request + * @return + */ + @PostMapping("/add") + public BaseResponse addResume(@RequestBody ResumeAddRequest resumeAddRequest, HttpServletRequest request) { + if (resumeAddRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + long newResumeId = resumeService.addResume(resumeAddRequest, loginUser); + return ResultUtils.success(newResumeId); + } + + /** + * 删除简历 + * + * @param deleteRequest + * @param request + * @return + */ + @PostMapping("/delete") + public BaseResponse deleteResume(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + boolean result = resumeService.deleteResume(deleteRequest.getId(), loginUser); + return ResultUtils.success(result); + } + + /** + * 更新简历 + * + * @param resumeUpdateRequest + * @param request + * @return + */ + @PostMapping("/update") + public BaseResponse updateResume(@RequestBody ResumeUpdateRequest resumeUpdateRequest, HttpServletRequest request) { + if (resumeUpdateRequest == null || resumeUpdateRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + boolean result = resumeService.updateResume(resumeUpdateRequest, loginUser); + return ResultUtils.success(result); + } + + /** + * 根据 id 获取简历(封装类) + * + * @param id + * @param request + * @return + */ + @GetMapping("/get/vo") + public BaseResponse getResumeVOById(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + Resume resume = resumeService.getById(id); + if (resume == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + // 权限检查: 管理员、Boss、本人可查看 + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + boolean isBoss = UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole()); + boolean isOwner = resume.getUserId().equals(loginUser.getId()); + + if (!isAdmin && !isBoss && !isOwner) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权查看该简历"); + } + + return ResultUtils.success(resumeService.getResumeVO(resume)); + } + + /** + * 分页获取简历列表(封装类) + * + * @param resumeQueryRequest + * @param request + * @return + */ + @PostMapping("/list/page/vo") + public BaseResponse> listResumeVOByPage(@RequestBody ResumeQueryRequest resumeQueryRequest, HttpServletRequest request) { + if (resumeQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + boolean isBoss = UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole()); + + // 如果不是管理员也不是Boss,只能看自己的 + if (!isAdmin && !isBoss) { + resumeQueryRequest.setUserId(loginUser.getId()); + } + + long size = resumeQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page resumeVOPage = resumeService.listResumeVOByPage(resumeQueryRequest); + return ResultUtils.success(resumeVOPage); + } + + /** + * 上传简历附件文件 + * + * @param file 文件 + * @param request HTTP请求 + * @return 文件访问URL + */ + @PostMapping("/upload") + public BaseResponse uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) { + if (file == null || file.isEmpty()) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件不能为空"); + } + + User loginUser = userService.getLoginUser(request); + + // 检查文件大小 + long fileSize = file.getSize(); + long maxSize = maxSizeMb * 1024 * 1024; // 转换为字节 + if (fileSize > maxSize) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, String.format("文件大小不能超过%dMB", maxSizeMb)); + } + + // 获取原始文件名 + String originalFilename = file.getOriginalFilename(); + if (originalFilename == null || originalFilename.trim().isEmpty()) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件名不能为空"); + } + + // 获取文件扩展名 + String extension = ""; + int lastDotIndex = originalFilename.lastIndexOf("."); + if (lastDotIndex > 0) { + extension = originalFilename.substring(lastDotIndex); + } + + // 验证文件类型(允许PDF和Word文档) + String contentType = file.getContentType(); + if (contentType != null && !contentType.equals("application/pdf") + && !contentType.equals("application/msword") + && !contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "仅支持PDF和Word文档格式"); + } + + try { + // 生成唯一文件名:用户ID_时间戳_UUID.扩展名 + String timestamp = String.valueOf(System.currentTimeMillis()); + String uniqueFileName = String.format("%d_%s_%s%s", + loginUser.getId(), timestamp, UUID.randomUUID().toString().replace("-", ""), extension); + + // 构建相对路径:resume/{userId}/{filename} + String relativePath = String.format("resume/%d/%s", loginUser.getId(), uniqueFileName); + + // 上传文件 + fileService.upload(relativePath, file); + + // 构建文件访问URL + String fileUrl = fileService.buildUrl(relativePath); + + log.info("用户 {} 上传文件成功: {}, URL: {}", loginUser.getId(), originalFilename, fileUrl); + return ResultUtils.success(fileUrl); + } catch (IOException e) { + log.error("文件上传失败: {}", e.getMessage(), e); + throw new BusinessException(ErrorCode.OPERATION_ERROR, "文件上传失败: " + e.getMessage()); + } + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/controller/UserController.java b/BOSSBackEnd/src/main/java/com/zds/boss/controller/UserController.java new file mode 100644 index 0000000..ab3a51a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/controller/UserController.java @@ -0,0 +1,189 @@ +package com.zds.boss.controller;/* + *@auther 郑笃实 + *@version 1.0 + * + */ + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.annotation.AuthCheck; +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.DeleteRequest; +import com.zds.boss.common.ResultUtils; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.exception.ThrowUtils; +import com.zds.boss.model.dto.user.UserLoginRequest; +import com.zds.boss.model.dto.user.UserQueryRequest; +import com.zds.boss.model.dto.user.UserRegisterRequest; +import com.zds.boss.model.dto.user.UserUpdateRequest; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.LoginUserVO; +import com.zds.boss.model.vo.UserVO; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequestMapping("/user")//标记这个类中的所有方法都处理根路径下的请求 +@Slf4j +@RestController//标记这个类是一个控制器 ,并且返回的数据会直接写入HTTP响应体中 +public class UserController { + + @Resource + private UserService userService; + /** + * 用户注册 + * + * @param userRegisterRequest + * @return + */ + @PostMapping("/register")//标记这个方法处理根路径下的GET请求 + public BaseResponse userRegister(@RequestBody UserRegisterRequest userRegisterRequest) { + ThrowUtils.throwIf(userRegisterRequest == null, ErrorCode.PARAMS_ERROR); + String usrAccount = userRegisterRequest.getUsrAccount(); + String userPassword = userRegisterRequest.getUserPassword(); + String checkPassword = userRegisterRequest.getCheckPassword(); + String userRole = userRegisterRequest.getUserRole(); + long result = userService.userRegister(usrAccount, userPassword, checkPassword, userRole); + return ResultUtils.success(result); + } + /** + * 用户登录 + * + * @param userLoginRequest + * @return + */ + @PostMapping("/login") + public BaseResponse userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) { + ThrowUtils.throwIf(userLoginRequest == null, ErrorCode.PARAMS_ERROR); + String usrAccount = userLoginRequest.getUsrAccount(); + String userPassword = userLoginRequest.getUserPassword(); + LoginUserVO loginUserVO = userService.userLogin(usrAccount, userPassword, request); + return ResultUtils.success(loginUserVO); + } + + /** + * 获取当前登录用户 + * + * @param request + * @return + */ + @GetMapping("/get/login") + public BaseResponse getLoginUser(HttpServletRequest request) { + User user = userService.getLoginUser(request); + return ResultUtils.success(userService.getLoginUserVO(user)); + } + + /** + * 用户登出 + * + * @param request + * @return + */ + @PostMapping("/logout") + public BaseResponse userLogout(HttpServletRequest request) { + ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR); + boolean result = userService.userLogOut(request); + return ResultUtils.success(result); + } + + /** + * 根据 id 获取用户 + */ + @GetMapping("/get") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse getUserById(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = userService.getById(id); + ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR); + return ResultUtils.success(user); + } + + /** + * 根据 id 获取包装类 + */ + @GetMapping("/get/vo") + public BaseResponse getUserVOById(long id, HttpServletRequest request) { + BaseResponse response = getUserById(id, request); + User user = response.getData(); + return ResultUtils.success(userService.getUserVO(user)); + } + + /** + * 删除用户 + */ + @PostMapping("/delete") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse deleteUser(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean b = userService.removeById(deleteRequest.getId()); + return ResultUtils.success(b); + } + + /** + * 更新用户 + */ + @PostMapping("/update") + public BaseResponse updateUser(@RequestBody UserUpdateRequest userUpdateRequest, HttpServletRequest request) { + if (userUpdateRequest == null || userUpdateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + // 权限控制:Admin 或 User自己 + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + if (!isAdmin) { + if (!loginUser.getId().equals(userUpdateRequest.getId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + + User user = new User(); + BeanUtils.copyProperties(userUpdateRequest, user); + boolean result = userService.updateById(user); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } + + /** + * 分页获取用户封装列表 + * + * @param userQueryRequest 查询请求参数 + */ + @PostMapping("/list/page/vo") + public BaseResponse> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest, HttpServletRequest request) { + if (userQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long current = userQueryRequest.getCurrent(); + long size = userQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page userPage = userService.page(new Page<>(current, size), userService.getQueryWrapper(userQueryRequest)); + Page userVOPage = new Page<>(current, size, userPage.getTotal()); + List userVOList = userService.getUserVOList(userPage.getRecords()); + userVOPage.setRecords(userVOList); + return ResultUtils.success(userVOPage); + } + + /** + * 获取当前用户 BOSS + */ + @GetMapping("/boss/list") + public BaseResponse> listBoss(HttpServletRequest request) { + List userList = userService.list(new QueryWrapper<>(new User()).eq("userRole", UserRoleEnum.BOSS.getValue())); + List userVOList = userService.getUserVOList(userList); + return ResultUtils.success(userVOList); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/exception/BusinessException.java b/BOSSBackEnd/src/main/java/com/zds/boss/exception/BusinessException.java new file mode 100644 index 0000000..86217ff --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/exception/BusinessException.java @@ -0,0 +1,27 @@ +package com.zds.boss.exception; + +import lombok.Getter; + +@Getter +public class BusinessException extends RuntimeException { + + /** + * 错误码 + */ + private final int code; + + public BusinessException(int code, String message) { + super(message); + this.code = code; + } + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.code = errorCode.getCode(); + } + + public BusinessException(ErrorCode errorCode, String message) { + super(message); + this.code = errorCode.getCode(); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/exception/ErrorCode.java b/BOSSBackEnd/src/main/java/com/zds/boss/exception/ErrorCode.java new file mode 100644 index 0000000..72a760b --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/exception/ErrorCode.java @@ -0,0 +1,32 @@ +package com.zds.boss.exception; + +import lombok.Getter; + +@Getter +public enum ErrorCode { + + SUCCESS(0, "ok"), + PARAMS_ERROR(40000, "请求参数错误"), + NOT_LOGIN_ERROR(40100, "未登录"), + NO_AUTH_ERROR(40101, "无权限"), + NOT_FOUND_ERROR(40400, "请求数据不存在"), + FORBIDDEN_ERROR(40300, "禁止访问"), + SYSTEM_ERROR(50000, "系统内部异常"), + OPERATION_ERROR(50001, "操作失败"); + + /** + * 状态码 + */ + private final int code; + + /** + * 信息 + */ + private final String message; + + ErrorCode(int code, String message) { + this.code = code; + this.message = message; + } + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/exception/GlobalExceptionHandler.java b/BOSSBackEnd/src/main/java/com/zds/boss/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..e6242ee --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/exception/GlobalExceptionHandler.java @@ -0,0 +1,26 @@ +package com.zds.boss.exception; + +import com.zds.boss.common.BaseResponse; +import com.zds.boss.common.ResultUtils; +import io.swagger.v3.oas.annotations.Hidden; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Hidden +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + @ExceptionHandler(BusinessException.class) + public BaseResponse businessExceptionHandler(BusinessException e) { + log.error("BusinessException", e); + return ResultUtils.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(RuntimeException.class) + public BaseResponse runtimeExceptionHandler(RuntimeException e) { + log.error("RuntimeException", e); + return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/exception/ThrowUtils.java b/BOSSBackEnd/src/main/java/com/zds/boss/exception/ThrowUtils.java new file mode 100644 index 0000000..44f9d64 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/exception/ThrowUtils.java @@ -0,0 +1,40 @@ +package com.zds.boss.exception; + +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; + +public class ThrowUtils { + + /** + * 条件成立则抛异常 + * + * @param condition 条件 + * @param runtimeException 异常 + */ + public static void throwIf(boolean condition, RuntimeException runtimeException) { + if (condition) { + throw runtimeException; + } + } + + /** + * 条件成立则抛异常 + * + * @param condition 条件 + * @param errorCode 错误码 + */ + public static void throwIf(boolean condition, ErrorCode errorCode) { + throwIf(condition, new BusinessException(errorCode)); + } + + /** + * 条件成立则抛异常 + * + * @param condition 条件 + * @param errorCode 错误码 + * @param message 错误信息 + */ + public static void throwIf(boolean condition, ErrorCode errorCode, String message) { + throwIf(condition, new BusinessException(errorCode, message)); + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ApplicationMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ApplicationMapper.java new file mode 100644 index 0000000..4745d6d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ApplicationMapper.java @@ -0,0 +1,8 @@ +package com.zds.boss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zds.boss.model.entity.Application; + +public interface ApplicationMapper extends BaseMapper { +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/BossApplicationDecisionMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/BossApplicationDecisionMapper.java new file mode 100644 index 0000000..72cf39e --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/BossApplicationDecisionMapper.java @@ -0,0 +1,8 @@ +package com.zds.boss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zds.boss.model.entity.BossApplicationDecision; + +public interface BossApplicationDecisionMapper extends BaseMapper { +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/CompanyMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/CompanyMapper.java new file mode 100644 index 0000000..6c9c495 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/CompanyMapper.java @@ -0,0 +1,18 @@ +package com.zds.boss.mapper; + +import com.zds.boss.model.entity.Company; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【company(公司表)】的数据库操作Mapper +* @createDate 2025-12-31 23:47:37 +* @Entity com.zds.boss.model.entity.Company +*/ +public interface CompanyMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/InterviewMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/InterviewMapper.java new file mode 100644 index 0000000..ead3ee6 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/InterviewMapper.java @@ -0,0 +1,8 @@ +package com.zds.boss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zds.boss.model.entity.Interview; + +public interface InterviewMapper extends BaseMapper { +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/JobPostingMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/JobPostingMapper.java new file mode 100644 index 0000000..b7d07ec --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/JobPostingMapper.java @@ -0,0 +1,8 @@ +package com.zds.boss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zds.boss.model.entity.JobPosting; + +public interface JobPostingMapper extends BaseMapper { +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeAddressMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeAddressMapper.java new file mode 100644 index 0000000..8ff97e8 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeAddressMapper.java @@ -0,0 +1,7 @@ +package com.zds.boss.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zds.boss.model.entity.ResumeAddress; + +public interface ResumeAddressMapper extends BaseMapper { +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeMapper.java new file mode 100644 index 0000000..a91e0a9 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/ResumeMapper.java @@ -0,0 +1,14 @@ +package com.zds.boss.mapper; + +import com.zds.boss.model.entity.Resume; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【resume(简历表)】的数据库操作Mapper +* @createDate 2025-12-31 23:30:00 +* @Entity com.zds.boss.model.entity.Resume +*/ +public interface ResumeMapper extends BaseMapper { + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/mapper/UserMapper.java b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/UserMapper.java new file mode 100644 index 0000000..f6fd264 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/mapper/UserMapper.java @@ -0,0 +1,18 @@ +package com.zds.boss.mapper; + +import com.zds.boss.model.entity.User; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【user(候选人用户表)】的数据库操作Mapper +* @createDate 2025-12-31 08:25:35 +* @Entity com.zds.boss.model.entity.User +*/ +public interface UserMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationAddRequest.java new file mode 100644 index 0000000..03f29ba --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationAddRequest.java @@ -0,0 +1,14 @@ +package com.zds.boss.model.dto.application; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class ApplicationAddRequest implements Serializable { + private Long resumeId; + private Long jobId; + private Long bossId; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationQueryRequest.java new file mode 100644 index 0000000..c647060 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationQueryRequest.java @@ -0,0 +1,19 @@ +package com.zds.boss.model.dto.application; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ApplicationQueryRequest extends PageRequest implements Serializable { + private Long id; + private Long userId; + private Long resumeId; + private Long jobId; + private Long bossId; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationUpdateRequest.java new file mode 100644 index 0000000..b860f9f --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/application/ApplicationUpdateRequest.java @@ -0,0 +1,13 @@ +package com.zds.boss.model.dto.application; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class ApplicationUpdateRequest implements Serializable { + private Long id; + private Long resumeId; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyAddRequest.java new file mode 100644 index 0000000..e2ff753 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyAddRequest.java @@ -0,0 +1,17 @@ +package com.zds.boss.model.dto.company; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class CompanyAddRequest implements Serializable { + private String name; + private String industry; + private String sizeRange; + private String website; + private String address; + private String intro; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyQueryRequest.java new file mode 100644 index 0000000..189f9da --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyQueryRequest.java @@ -0,0 +1,17 @@ +package com.zds.boss.model.dto.company; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class CompanyQueryRequest extends PageRequest implements Serializable { + private Long id; + private String name; + private String industry; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyUpdateRequest.java new file mode 100644 index 0000000..d864296 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/company/CompanyUpdateRequest.java @@ -0,0 +1,18 @@ +package com.zds.boss.model.dto.company; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class CompanyUpdateRequest implements Serializable { + private Long id; + private String name; + private String industry; + private String sizeRange; + private String website; + private String address; + private String intro; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionAddRequest.java new file mode 100644 index 0000000..fe8712e --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionAddRequest.java @@ -0,0 +1,17 @@ +package com.zds.boss.model.dto.decision; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class BossApplicationDecisionAddRequest implements Serializable { + private Long applicationId; + private Long bossId; + private Integer decision; + private Integer stage; + private String note; + private Date decidedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionQueryRequest.java new file mode 100644 index 0000000..395c942 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionQueryRequest.java @@ -0,0 +1,18 @@ +package com.zds.boss.model.dto.decision; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class BossApplicationDecisionQueryRequest extends PageRequest implements Serializable { + private Long id; + private Long applicationId; + private Long bossId; + private Integer decision; + private Integer stage; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionUpdateRequest.java new file mode 100644 index 0000000..13d696e --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/decision/BossApplicationDecisionUpdateRequest.java @@ -0,0 +1,16 @@ +package com.zds.boss.model.dto.decision; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class BossApplicationDecisionUpdateRequest implements Serializable { + private Long id; + private Integer decision; + private Integer stage; + private String note; + private Date decidedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewAddRequest.java new file mode 100644 index 0000000..aa042d4 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewAddRequest.java @@ -0,0 +1,19 @@ +package com.zds.boss.model.dto.interview; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class InterviewAddRequest implements Serializable { + private Long applicationId; + private Long bossId; + private Long userId; + private Date interviewTime; + private Integer mode; + private String location; + private Integer status; + private String note; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewQueryRequest.java new file mode 100644 index 0000000..40ae740 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewQueryRequest.java @@ -0,0 +1,18 @@ +package com.zds.boss.model.dto.interview; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class InterviewQueryRequest extends PageRequest implements Serializable { + private Long id; + private Long applicationId; + private Long bossId; + private Long userId; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewUpdateRequest.java new file mode 100644 index 0000000..7756a65 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/interview/InterviewUpdateRequest.java @@ -0,0 +1,17 @@ +package com.zds.boss.model.dto.interview; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class InterviewUpdateRequest implements Serializable { + private Long id; + private Date interviewTime; + private Integer mode; + private String location; + private Integer status; + private String note; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingAddRequest.java new file mode 100644 index 0000000..f95fbb5 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingAddRequest.java @@ -0,0 +1,20 @@ +package com.zds.boss.model.dto.job; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class JobPostingAddRequest implements Serializable { + private Long bossId; + private Long companyId; + private String title; + private String location; + private String jobType; + private Integer salaryMin; + private Integer salaryMax; + private String description; + private String requirement; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingQueryRequest.java new file mode 100644 index 0000000..8b0f773 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingQueryRequest.java @@ -0,0 +1,20 @@ +package com.zds.boss.model.dto.job; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class JobPostingQueryRequest extends PageRequest implements Serializable { + private Long id; + private Long bossId; + private Long companyId; + private String title; + private String location; + private String jobType; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingUpdateRequest.java new file mode 100644 index 0000000..8235b75 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/job/JobPostingUpdateRequest.java @@ -0,0 +1,19 @@ +package com.zds.boss.model.dto.job; + +import lombok.Data; +import java.io.Serializable; + +@Data +public class JobPostingUpdateRequest implements Serializable { + private Long id; + private String title; + private String location; + private String jobType; + private Integer salaryMin; + private Integer salaryMax; + private String description; + private String requirement; + private Integer status; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeAddRequest.java new file mode 100644 index 0000000..a9b50ed --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeAddRequest.java @@ -0,0 +1,38 @@ +package com.zds.boss.model.dto.resume; + +import lombok.Data; +import java.io.Serializable; + +/** + * 创建简历请求 + */ +@Data +public class ResumeAddRequest implements Serializable { + + /** + * 简历标题 + */ + private String resumeTitle; + + /** + * 是否默认:0否 1是 + */ + private Integer isDefault; + + /** + * 摘要 + */ + private String summary; + + /** + * 正文(可存Markdown/JSON/HTML) + */ + private String content; + + /** + * 附件URL(PDF/Word) + */ + private String attachmentUrl; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeQueryRequest.java new file mode 100644 index 0000000..7147c5a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeQueryRequest.java @@ -0,0 +1,37 @@ +package com.zds.boss.model.dto.resume; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * 查询简历请求 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ResumeQueryRequest extends PageRequest implements Serializable { + + /** + * 简历ID + */ + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 简历标题 + */ + private String resumeTitle; + + /** + * 是否默认:0否 1是 + */ + private Integer isDefault; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeUpdateRequest.java new file mode 100644 index 0000000..dcf4367 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/resume/ResumeUpdateRequest.java @@ -0,0 +1,43 @@ +package com.zds.boss.model.dto.resume; + +import lombok.Data; +import java.io.Serializable; + +/** + * 更新简历请求 + */ +@Data +public class ResumeUpdateRequest implements Serializable { + + /** + * 简历ID + */ + private Long id; + + /** + * 简历标题 + */ + private String resumeTitle; + + /** + * 是否默认:0否 1是 + */ + private Integer isDefault; + + /** + * 摘要 + */ + private String summary; + + /** + * 正文(可存Markdown/JSON/HTML) + */ + private String content; + + /** + * 附件URL(PDF/Word) + */ + private String attachmentUrl; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserAddRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserAddRequest.java new file mode 100644 index 0000000..d89edf5 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserAddRequest.java @@ -0,0 +1,32 @@ +package com.zds.boss.model.dto.user; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UserAddRequest implements Serializable { + + /** + * 用户昵称 + */ + private String userName; + + /** + * 账号 + */ + private String userNickname; + + /** + * 用户手机 + */ + private String userPhone; + + /** + * 用户邮箱 + */ + private String userEmail; + + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserLoginRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserLoginRequest.java new file mode 100644 index 0000000..24d8200 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserLoginRequest.java @@ -0,0 +1,23 @@ +package com.zds.boss.model.dto.user;/* + *@auther 郑笃实 + *@version 1.0 + * + */ + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 用户登录请求 + */ +@Data +public class UserLoginRequest implements Serializable { + + @Serial + private static final long serialVersionUID = -1999618084091901791L; + private String usrAccount; + private String userPassword; + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserQueryRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserQueryRequest.java new file mode 100644 index 0000000..a46b682 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserQueryRequest.java @@ -0,0 +1,35 @@ +package com.zds.boss.model.dto.user; + +import com.zds.boss.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +@EqualsAndHashCode(callSuper = true) +@Data +public class UserQueryRequest extends PageRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 用户账号 + */ + private String userAccount; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户简介 + */ + private String userProfile; + + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserRegisterRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserRegisterRequest.java new file mode 100644 index 0000000..620dea2 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserRegisterRequest.java @@ -0,0 +1,21 @@ +package com.zds.boss.model.dto.user;/* + *@auther 郑笃实 + *@version 1.0 + * + */ + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class UserRegisterRequest implements Serializable { + + @Serial + private static final long serialVersionUID = -1999618084091901791L; + private String usrAccount; + private String userPassword; + private String checkPassword; + private String userRole; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdatePageRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdatePageRequest.java new file mode 100644 index 0000000..19b5094 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdatePageRequest.java @@ -0,0 +1,23 @@ +package com.zds.boss.model.dto.user; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class UserUpdatePageRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 用户昵称 + */ + private String userName; + + + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdateRequest.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdateRequest.java new file mode 100644 index 0000000..c54c487 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/dto/user/UserUpdateRequest.java @@ -0,0 +1,39 @@ +package com.zds.boss.model.dto.user; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户更新请求 + */ +@Data +public class UserUpdateRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Application.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Application.java new file mode 100644 index 0000000..0e48422 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Application.java @@ -0,0 +1,26 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "application") +@Data +public class Application implements Serializable { + @TableId(type = IdType.AUTO) + private Long id; + private Long userId; + private Long resumeId; + private Long jobId; + private Long bossId; + private Integer status; + @TableField("applied_at") + private Date appliedAt; + @TableField("updated_at") + private Date updatedAt; + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/BossApplicationDecision.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/BossApplicationDecision.java new file mode 100644 index 0000000..da8b61b --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/BossApplicationDecision.java @@ -0,0 +1,26 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "boss_application_decision") +@Data +public class BossApplicationDecision implements Serializable { + @TableId(type = IdType.AUTO) + private Long id; + private Long applicationId; + private Long bossId; + private Integer decision; + private Integer stage; + private String note; + @TableField("decided_at") + private Date decidedAt; + @TableField("updated_at") + private Date updatedAt; + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Company.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Company.java new file mode 100644 index 0000000..bd8a660 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Company.java @@ -0,0 +1,133 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 公司表 + * @TableName company + */ +@TableName(value ="company") +@Data +public class Company implements Serializable { + /** + * 公司ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 公司名 + */ + private String name; + + /** + * 行业 + */ + private String industry; + + /** + * 规模(如1-50/50-200) + */ + private String sizeRange; + + /** + * 官网 + */ + private String website; + + /** + * 地址 + */ + private String address; + + /** + * 公司介绍 + */ + private String intro; + + /** + * 状态:0禁用 1正常 + */ + private Integer status; + + /** + * + */ + private Date createdAt; + + /** + * + */ + private Date updatedAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + Company other = (Company) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) + && (this.getIndustry() == null ? other.getIndustry() == null : this.getIndustry().equals(other.getIndustry())) + && (this.getSizeRange() == null ? other.getSizeRange() == null : this.getSizeRange().equals(other.getSizeRange())) + && (this.getWebsite() == null ? other.getWebsite() == null : this.getWebsite().equals(other.getWebsite())) + && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress())) + && (this.getIntro() == null ? other.getIntro() == null : this.getIntro().equals(other.getIntro())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getName() == null) ? 0 : getName().hashCode()); + result = prime * result + ((getIndustry() == null) ? 0 : getIndustry().hashCode()); + result = prime * result + ((getSizeRange() == null) ? 0 : getSizeRange().hashCode()); + result = prime * result + ((getWebsite() == null) ? 0 : getWebsite().hashCode()); + result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode()); + result = prime * result + ((getIntro() == null) ? 0 : getIntro().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", name=").append(name); + sb.append(", industry=").append(industry); + sb.append(", sizeRange=").append(sizeRange); + sb.append(", website=").append(website); + sb.append(", address=").append(address); + sb.append(", intro=").append(intro); + sb.append(", status=").append(status); + sb.append(", createdAt=").append(createdAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Interview.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Interview.java new file mode 100644 index 0000000..6bb33de --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Interview.java @@ -0,0 +1,30 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "interview") +@Data +public class Interview implements Serializable { + @TableId(type = IdType.AUTO) + private Long id; + private Long applicationId; + private Long bossId; + private Long userId; + @TableField("interview_time") + private Date interviewTime; + private Integer mode; + private String location; + private Integer status; + private String note; + @TableField("created_at") + private Date createdAt; + @TableField("updated_at") + private Date updatedAt; + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/JobPosting.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/JobPosting.java new file mode 100644 index 0000000..53c3672 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/JobPosting.java @@ -0,0 +1,33 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName(value = "job_posting") +@Data +public class JobPosting implements Serializable { + @TableId(type = IdType.AUTO) + private Long id; + private Long bossId; + private Long companyId; + private String title; + private String location; + private String jobType; + private Integer salaryMin; + private Integer salaryMax; + private String description; + private String requirement; + private Integer status; + @TableField("publish_at") + private Date publishAt; + @TableField("created_at") + private Date createdAt; + @TableField("updated_at") + private Date updatedAt; + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Resume.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Resume.java new file mode 100644 index 0000000..270bd8a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/Resume.java @@ -0,0 +1,79 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 简历表 + * @TableName resume + */ +@TableName(value ="resume") +@Data +public class Resume implements Serializable { + /** + * 简历ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID(无外键) + */ + @TableField("user_id") + private Long userId; + + /** + * 简历标题 + */ + @TableField("resume_title") + private String resumeTitle; + + /** + * 是否默认:0否 1是 + */ + @TableField("is_default") + private Integer isDefault; + + /** + * 摘要 + */ + @TableField("summary") + private String summary; + + /** + * 正文(可存Markdown/JSON/HTML) + */ + @TableField("content") + private String content; + + /** + * 附件URL(PDF/Word) + */ + @TableField("attachment_url") + private String attachmentUrl; + + /** + * + */ + @TableField("updated_at") + private Date updatedAt; + + /** + * + */ + @TableField("created_at") + private Date createdAt; + + /** + * + */ + @TableLogic + @TableField("is_deleted") + private Integer isDeleted; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/ResumeAddress.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/ResumeAddress.java new file mode 100644 index 0000000..60282b8 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/ResumeAddress.java @@ -0,0 +1,38 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@TableName("resume_address") +@Data +public class ResumeAddress implements Serializable { + + @TableId(type = IdType.AUTO) + private Long id; + + @TableField("user_id") + private Long userId; + + @TableField("resume_id") + private Long resumeId; + + @TableField("address") + private String address; + + @TableField("file_key") + private String fileKey; + + @TableField("created_at") + private Date createdAt; + + @TableField("updated_at") + private Date updatedAt; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/User.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/User.java new file mode 100644 index 0000000..9689e4f --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/entity/User.java @@ -0,0 +1,100 @@ +package com.zds.boss.model.entity; + +import com.baomidou.mybatisplus.annotation.*; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 候选人用户表 + * @TableName user + */ +@TableName(value ="user") +@Data +public class User implements Serializable { + /** + * 用户ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 登录名(唯一) + */ + @TableField("user_account") + private String userAccount; + + /** + * 密码哈希 + */ + @TableField("password") + private String userPassword; + + /** + * 手机号 + */ + private String phone; + + /** + * 邮箱 + */ + private String email; + + /** + * 昵称 + */ + @TableField("username") + private String userName; + + /** + * 用户角色:user-求职者, boss-Boss, admin-管理员 + */ + @TableField("user_role") + private String userRole; + + /** + * 公司ID(仅Boss角色有效) + */ + @TableField("company_id") + private Long companyId; + + /** + * 状态:0禁用 1正常 + */ + private Integer status; + + + /** + * + */ + @TableField("created_at") + private Date createdAt; + + /** + * + */ + @TableField("updated_at") + private Date updatedAt; + + /** + * 软删:0否 1是 + */ + @TableLogic + @TableField("is_deleted") + private Integer isDelete; + + /** + * + */ + @TableField("deleted_at") + private Date deletedAt; + + /** + * 简介 + */ + @TableField("profile") + private String userProfile; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/enums/UserRoleEnum.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/enums/UserRoleEnum.java new file mode 100644 index 0000000..c616a0a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/enums/UserRoleEnum.java @@ -0,0 +1,43 @@ +package com.zds.boss.model.enums; + +import cn.hutool.core.util.ObjUtil; +import lombok.Getter; + +/** + * 用户角色枚举 + */ +@Getter +public enum UserRoleEnum { + + USER("用户", "user"), + BOSS("招聘者", "boss"), + ADMIN("管理员", "admin"), + BAN("被封号", "ban"); + + private final String text; + + private final String value; + + UserRoleEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 根据 value 获取枚举 + * + * @param value + * @return + */ + public static UserRoleEnum getEnumByValue(String value) { + if (ObjUtil.isEmpty(value)) { + return null; + } + for (UserRoleEnum anEnum : UserRoleEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ApplicationVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ApplicationVO.java new file mode 100644 index 0000000..b3362cb --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ApplicationVO.java @@ -0,0 +1,19 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class ApplicationVO implements Serializable { + private Long id; + private Long userId; + private Long resumeId; + private Long jobId; + private Long bossId; + private Integer status; + private Date appliedAt; + private Date updatedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/BossApplicationDecisionVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/BossApplicationDecisionVO.java new file mode 100644 index 0000000..25a2df4 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/BossApplicationDecisionVO.java @@ -0,0 +1,19 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class BossApplicationDecisionVO implements Serializable { + private Long id; + private Long applicationId; + private Long bossId; + private Integer decision; + private Integer stage; + private String note; + private Date decidedAt; + private Date updatedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/CompanyVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/CompanyVO.java new file mode 100644 index 0000000..dc7c04e --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/CompanyVO.java @@ -0,0 +1,21 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class CompanyVO implements Serializable { + private Long id; + private String name; + private String industry; + private String sizeRange; + private String website; + private String address; + private String intro; + private Integer status; + private Date createdAt; + private Date updatedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/InterviewVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/InterviewVO.java new file mode 100644 index 0000000..e212049 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/InterviewVO.java @@ -0,0 +1,22 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class InterviewVO implements Serializable { + private Long id; + private Long applicationId; + private Long bossId; + private Long userId; + private Date interviewTime; + private Integer mode; + private String location; + private Integer status; + private String note; + private Date createdAt; + private Date updatedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/JobPostingVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/JobPostingVO.java new file mode 100644 index 0000000..5d9712d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/JobPostingVO.java @@ -0,0 +1,25 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +public class JobPostingVO implements Serializable { + private Long id; + private Long bossId; + private Long companyId; + private String title; + private String location; + private String jobType; + private Integer salaryMin; + private Integer salaryMax; + private String description; + private String requirement; + private Integer status; + private Date publishAt; + private Date createdAt; + private Date updatedAt; + private static final long serialVersionUID = 1L; +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/LoginUserVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/LoginUserVO.java new file mode 100644 index 0000000..8a0c21d --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/LoginUserVO.java @@ -0,0 +1,66 @@ +package com.zds.boss.model.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * 脱敏用户 + * + * @TableName user + */ +@Data +public class LoginUserVO { + /** + * id + */ + private Long id; + + /** + * 账号 + */ + private String userAccount; + + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 用户简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin + */ + private String userRole; + + /** + * 公司ID(仅Boss角色有效) + */ + private Long companyId; + + /** + * 编辑时间 + */ + private Date editTime; + + /** + * 创建时间 + */ + private Date createdAt; + + /** + * 更新时间 + */ + private Date updatedAt; + + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ResumeVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ResumeVO.java new file mode 100644 index 0000000..c28585c --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/ResumeVO.java @@ -0,0 +1,58 @@ +package com.zds.boss.model.vo; + +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +/** + * 简历视图 + */ +@Data +public class ResumeVO implements Serializable { + /** + * 简历ID + */ + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 简历标题 + */ + private String resumeTitle; + + /** + * 是否默认:0否 1是 + */ + private Integer isDefault; + + /** + * 摘要 + */ + private String summary; + + /** + * 正文 + */ + private String content; + + /** + * 附件URL + */ + private String attachmentUrl; + + /** + * 更新时间 + */ + private Date updatedAt; + + /** + * 创建时间 + */ + private Date createdAt; + + private static final long serialVersionUID = 1L; +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/UserVO.java b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/UserVO.java new file mode 100644 index 0000000..0830e54 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/model/vo/UserVO.java @@ -0,0 +1,69 @@ +package com.zds.boss.model.vo; + +import lombok.Data; + +import java.util.Date; + +/** + * 脱敏用户 + * + * @TableName user + */ +@Data +public class UserVO { + /** + * id + */ + private Long id; + + /** + * 账号 + */ + private String userAccount; + + /** + * 手机号 + */ + private String phone; + + /** + * 邮箱 + */ + private String email; + + /** + * 用户名 + */ + private String userName; + + /** + * 状态:0禁用 1正常 + */ + private Integer status; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + /** + * 公司ID(仅Boss角色有效) + */ + private Long companyId; + + /** + * 简介 + */ + private String userProfile; + + /** + * 创建时间 + */ + private Date createdAt; + + /** + * 更新时间 + */ + private Date updatedAt; + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/ApplicationService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/ApplicationService.java new file mode 100644 index 0000000..112d9fd --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/ApplicationService.java @@ -0,0 +1,25 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.application.ApplicationAddRequest; +import com.zds.boss.model.dto.application.ApplicationQueryRequest; +import com.zds.boss.model.dto.application.ApplicationUpdateRequest; +import com.zds.boss.model.entity.Application; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.vo.ApplicationVO; + +import java.util.List; + +public interface ApplicationService extends IService { + long addApplication(ApplicationAddRequest addRequest, User loginUser); + boolean deleteApplication(long id, User loginUser); + boolean updateApplication(ApplicationUpdateRequest updateRequest, User loginUser); + boolean updateApplicationStatus(long applicationId, int status); + ApplicationVO getApplicationVO(Application app); + List getApplicationVOList(List list); + QueryWrapper getQueryWrapper(ApplicationQueryRequest query); + Page listApplicationVOByPage(ApplicationQueryRequest query); +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/BossApplicationDecisionService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/BossApplicationDecisionService.java new file mode 100644 index 0000000..54dafee --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/BossApplicationDecisionService.java @@ -0,0 +1,25 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.decision.BossApplicationDecisionAddRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionQueryRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionUpdateRequest; +import com.zds.boss.model.entity.BossApplicationDecision; +import com.zds.boss.model.vo.BossApplicationDecisionVO; + +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +public interface BossApplicationDecisionService extends IService { + long addDecision(BossApplicationDecisionAddRequest addRequest, HttpServletRequest request); + boolean deleteDecision(long id, HttpServletRequest request); + boolean updateDecision(BossApplicationDecisionUpdateRequest updateRequest, HttpServletRequest request); + BossApplicationDecisionVO getDecisionVO(BossApplicationDecision decision); + List getDecisionVOList(List list); + QueryWrapper getQueryWrapper(BossApplicationDecisionQueryRequest query); + Page listDecisionVOByPage(BossApplicationDecisionQueryRequest query); +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/CompanyService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/CompanyService.java new file mode 100644 index 0000000..00585b2 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/CompanyService.java @@ -0,0 +1,32 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zds.boss.model.entity.Company; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.company.CompanyAddRequest; +import com.zds.boss.model.dto.company.CompanyQueryRequest; +import com.zds.boss.model.dto.company.CompanyUpdateRequest; +import com.zds.boss.model.vo.CompanyVO; +import java.util.List; + +/** +* @author 33882 +* @description 针对表【company(公司表)】的数据库操作Service +* @createDate 2025-12-31 23:47:37 +*/import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +public interface CompanyService extends IService { + long addCompany(CompanyAddRequest addRequest, HttpServletRequest request); + boolean deleteCompany(long id, HttpServletRequest request); + boolean updateCompany(CompanyUpdateRequest updateRequest, HttpServletRequest request); + CompanyVO getCompanyVO(Company company); + + List getCompanyVOList(List companyList); + + QueryWrapper getQueryWrapper(CompanyQueryRequest queryRequest); + + Page listCompanyVOByPage(CompanyQueryRequest queryRequest); +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/FileService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/FileService.java new file mode 100644 index 0000000..ba961b5 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/FileService.java @@ -0,0 +1,219 @@ +package com.zds.boss.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.annotation.PostConstruct; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * 本地文件服务 + * 提供文件上传、删除等功能,文件存储在 src/main/resources/static 目录下 + */ +@Service +@Slf4j +public class FileService { + + /** + * 文件存储基础路径 + */ + private String basePath; + + /** + * 文件访问基础URL(用于构建访问地址) + */ + @Value("${server.port:8081}") + private int serverPort; + + private final ResourceLoader resourceLoader; + + public FileService(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + /** + * 初始化方法,在Bean创建后执行 + */ + @PostConstruct + public void init() { + try { + // 获取src/main/resources/static目录的绝对路径 + Resource resource = resourceLoader.getResource("classpath:/static/"); + File staticDir; + + try { + // 尝试获取资源文件的实际路径 + staticDir = resource.getFile(); + } catch (IOException e) { + // 如果在jar包中运行,无法直接获取File,则使用项目根目录下的路径 + String projectRoot = System.getProperty("user.dir"); + staticDir = new File(projectRoot, "src/main/resources/static"); + + // 如果项目根目录下不存在,尝试使用target/classes/static + if (!staticDir.exists()) { + staticDir = new File(projectRoot, "target/classes/static"); + } + } + + this.basePath = staticDir.getAbsolutePath(); + + // 确保目录存在 + initStorageDirectory(); + } catch (Exception e) { + log.error("初始化文件存储目录失败", e); + // 降级方案:使用项目根目录下的static目录 + String projectRoot = System.getProperty("user.dir"); + this.basePath = new File(projectRoot, "src/main/resources/static").getAbsolutePath(); + initStorageDirectory(); + } + } + + /** + * 初始化存储目录 + */ + private void initStorageDirectory() { + try { + Path path = Paths.get(basePath); + if (!Files.exists(path)) { + Files.createDirectories(path); + log.info("创建文件存储目录: {}", basePath); + } + log.info("文件存储目录已就绪: {}", basePath); + } catch (IOException e) { + log.error("创建文件存储目录失败: {}", basePath, e); + throw new RuntimeException("文件存储目录初始化失败", e); + } + } + + /** + * 构建文件的访问URL + * + * @param relativePath 文件相对路径(相对于 basePath),例如:resume/123/Resume.pdf + * @return 文件的访问URL(用于HTTP访问),例如:/static/resume/123/Resume.pdf + */ + public String buildUrl(String relativePath) { + // 移除开头的 /,确保路径正确 + String cleanPath = relativePath.startsWith("/") ? relativePath.substring(1) : relativePath; + // 构建静态资源访问URL,映射到 /static/** 路径 + String url = String.format("/static/%s", cleanPath.replace("\\", "/")); + log.debug("构建文件访问URL: {}", url); + return url; + } + + /** + * 上传文件 + * + * @param relativePath 文件相对路径(相对于 basePath),例如:resume/123/Resume.pdf + * @param file 要上传的文件 + * @throws IOException 文件操作异常 + */ + public void upload(String relativePath, File file) throws IOException { + log.info("开始上传文件到本地存储,路径: {}", relativePath); + + try { + // 构建完整路径 + Path targetPath = Paths.get(basePath, relativePath); + + // 确保父目录存在 + Path parentDir = targetPath.getParent(); + if (parentDir != null && !Files.exists(parentDir)) { + Files.createDirectories(parentDir); + log.debug("创建文件目录: {}", parentDir); + } + + // 复制文件到目标位置 + Files.copy(file.toPath(), targetPath, java.nio.file.StandardCopyOption.REPLACE_EXISTING); + + log.info("文件成功上传到本地存储,路径: {}", targetPath.toAbsolutePath()); + } catch (Exception e) { + log.error("文件上传失败,路径: {}, 错误信息: {}", relativePath, e.getMessage(), e); + throw e; + } + } + + /** + * 上传文件(使用MultipartFile) + * + * @param relativePath 文件相对路径(相对于 basePath) + * @param multipartFile 要上传的文件 + * @throws IOException 文件操作异常 + */ + public void upload(String relativePath, MultipartFile multipartFile) throws IOException { + log.info("开始上传文件到本地存储,路径: {}", relativePath); + + try { + // 构建完整路径 + Path targetPath = Paths.get(basePath, relativePath); + + // 确保父目录存在 + Path parentDir = targetPath.getParent(); + if (parentDir != null && !Files.exists(parentDir)) { + Files.createDirectories(parentDir); + log.debug("创建文件目录: {}", parentDir); + } + + // 保存文件 + multipartFile.transferTo(targetPath.toFile()); + + log.info("文件成功上传到本地存储,路径: {}", targetPath.toAbsolutePath()); + } catch (Exception e) { + log.error("文件上传失败,路径: {}, 错误信息: {}", relativePath, e.getMessage(), e); + throw e; + } + } + + /** + * 删除文件 + * + * @param relativePath 文件相对路径(相对于 basePath) + * @throws IOException 文件操作异常 + */ + public void delete(String relativePath) throws IOException { + log.info("删除本地文件,路径: {}", relativePath); + + try { + Path filePath = Paths.get(basePath, relativePath); + + if (Files.exists(filePath)) { + Files.delete(filePath); + log.info("文件删除成功,路径: {}", filePath.toAbsolutePath()); + } else { + log.warn("文件不存在,无法删除,路径: {}", filePath.toAbsolutePath()); + } + } catch (Exception e) { + log.error("文件删除失败,路径: {}, 错误信息: {}", relativePath, e.getMessage(), e); + throw e; + } + } + + /** + * 检查文件是否存在 + * + * @param relativePath 文件相对路径 + * @return 文件是否存在 + */ + public boolean exists(String relativePath) { + Path filePath = Paths.get(basePath, relativePath); + return Files.exists(filePath); + } + + /** + * 获取文件的完整路径 + * + * @param relativePath 文件相对路径 + * @return 文件的完整路径 + */ + public String getFullPath(String relativePath) { + Path filePath = Paths.get(basePath, relativePath); + return filePath.toAbsolutePath().toString(); + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/InterviewService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/InterviewService.java new file mode 100644 index 0000000..24c2f2b --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/InterviewService.java @@ -0,0 +1,25 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.interview.InterviewAddRequest; +import com.zds.boss.model.dto.interview.InterviewQueryRequest; +import com.zds.boss.model.dto.interview.InterviewUpdateRequest; +import com.zds.boss.model.entity.Interview; +import com.zds.boss.model.vo.InterviewVO; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; + +public interface InterviewService extends IService { + long addInterview(InterviewAddRequest addRequest, HttpServletRequest request); + boolean deleteInterview(long id); + boolean updateInterview(InterviewUpdateRequest updateRequest); + InterviewVO getInterviewVO(Interview interview); + List getInterviewVOList(List list); + QueryWrapper getQueryWrapper(InterviewQueryRequest query); + Page listInterviewVOByPage(InterviewQueryRequest query); +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/JobPostingService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/JobPostingService.java new file mode 100644 index 0000000..d7ac01e --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/JobPostingService.java @@ -0,0 +1,25 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.job.JobPostingAddRequest; +import com.zds.boss.model.dto.job.JobPostingQueryRequest; +import com.zds.boss.model.dto.job.JobPostingUpdateRequest; +import com.zds.boss.model.entity.JobPosting; +import com.zds.boss.model.vo.JobPostingVO; + +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +public interface JobPostingService extends IService { + long addJobPosting(JobPostingAddRequest addRequest, HttpServletRequest request); + boolean deleteJobPosting(long id, HttpServletRequest request); + boolean updateJobPosting(JobPostingUpdateRequest updateRequest, HttpServletRequest request); + JobPostingVO getJobPostingVO(JobPosting job); + List getJobPostingVOList(List list); + QueryWrapper getQueryWrapper(JobPostingQueryRequest query); + Page listJobPostingVOByPage(JobPostingQueryRequest query); +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/ResumeService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/ResumeService.java new file mode 100644 index 0000000..dc1430c --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/ResumeService.java @@ -0,0 +1,79 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.resume.ResumeAddRequest; +import com.zds.boss.model.dto.resume.ResumeQueryRequest; +import com.zds.boss.model.dto.resume.ResumeUpdateRequest; +import com.zds.boss.model.entity.Resume; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.vo.ResumeVO; + +import java.util.List; + +/** +* @author 33882 +* @description 针对表【resume(简历表)】的数据库操作Service +* @createDate 2025-12-31 23:30:00 +*/ +public interface ResumeService extends IService { + + /** + * 创建简历 + * + * @param resumeAddRequest + * @param loginUser + * @return + */ + long addResume(ResumeAddRequest resumeAddRequest, User loginUser); + + /** + * 删除简历 + * + * @param id + * @param loginUser + * @return + */ + boolean deleteResume(long id, User loginUser); + + /** + * 更新简历 + * + * @param resumeUpdateRequest + * @param loginUser + * @return + */ + boolean updateResume(ResumeUpdateRequest resumeUpdateRequest, User loginUser); + + /** + * 获取简历VO + * + * @param resume + * @return + */ + ResumeVO getResumeVO(Resume resume); + + /** + * 获取简历VO列表 + * + * @param resumeList + * @return + */ + List getResumeVOList(List resumeList); + + /** + * 获取查询条件 + * + * @param resumeQueryRequest + * @return + */ + QueryWrapper getQueryWrapper(ResumeQueryRequest resumeQueryRequest); + + /** + * 分页获取简历VO + * @param resumeQueryRequest + * @return + */ + Page listResumeVOByPage(ResumeQueryRequest resumeQueryRequest); +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/UserService.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/UserService.java new file mode 100644 index 0000000..df37b0c --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/UserService.java @@ -0,0 +1,96 @@ +package com.zds.boss.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zds.boss.model.dto.user.UserQueryRequest; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.vo.LoginUserVO; +import com.zds.boss.model.vo.UserVO; +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +/** + * @author 33882 + * @description 针对表【user(候选人用户表)】的数据库操作Service + * @createDate 2025-12-30 23:14:37 + */ +public interface UserService extends IService { + /** + * 用户注册方法 + * + * @param userAccount 用户账号,用于唯一标识一个用户 + * @param userPassword 用户密码,需要进行加密处理 + * @param checkPassword 确认密码,用于二次验证用户输入的密码是否正确 + * @param userRole 用户角色 + * @return 返回一个长整型值,通常用于表示操作结果: + */ + long userRegister(String userAccount, String userPassword, String checkPassword, String userRole); + + /** + * 用户登录方法 + * + * @param userAccount 用户账号 + * @param userPassword 用户密码 + * @param request HTTP请求对象 + * @return 返回一个用户对象,通常用于表示登录成功后的用户信息 + */ + LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request); + + /** + * 获取登录用户信息 + * + * @param user + * @return + */ + LoginUserVO getLoginUserVO(User user); + + /** + * 获取用户VO + * + * @param user + * @return + */ + UserVO getUserVO(User user); + + /** + * 获取用户VO列表 + * + * @param userList + * @return + */ + List getUserVOList(List userList); + + /** + * 密码加密 + * + * @param userPassword + * @return + */ + String getEncryptPassword(String userPassword); + + /** + * 获取当前登录用户 + * + * @param request + * @return + */ + User getLoginUser(HttpServletRequest request); + + /** + * 用户登出 + * + * @param request + * @return + */ + boolean userLogOut(HttpServletRequest request); + + /** + * 获取查询条件 + * + * @param userQueryRequest + * @return + */ + QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest); + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ApplicationServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ApplicationServiceImpl.java new file mode 100644 index 0000000..ffee372 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ApplicationServiceImpl.java @@ -0,0 +1,199 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.ApplicationMapper; +import com.zds.boss.model.dto.application.ApplicationAddRequest; +import com.zds.boss.model.dto.application.ApplicationQueryRequest; +import com.zds.boss.model.dto.application.ApplicationUpdateRequest; +import com.zds.boss.model.entity.Application; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.vo.ApplicationVO; +import com.zds.boss.service.ApplicationService; +import com.zds.boss.service.JobPostingService; +import com.zds.boss.model.entity.JobPosting; +import com.zds.boss.utils.UserUtils; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ApplicationServiceImpl extends ServiceImpl implements ApplicationService { + + @Resource + @Lazy + private JobPostingService jobPostingService; + + @Override + @Transactional(rollbackFor = Exception.class) + public long addApplication(ApplicationAddRequest addRequest, User loginUser) { + if (addRequest == null || loginUser == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + // 检查是否已投递 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", loginUser.getId()); + queryWrapper.eq("job_id", addRequest.getJobId()); + long count = this.count(queryWrapper); + if (count > 0) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "您已经投递过该职位"); + } + + Application app = new Application(); + BeanUtil.copyProperties(addRequest, app); + app.setUserId(loginUser.getId()); + + // 补充 bossId (从 JobPosting 获取) + if (app.getJobId() != null) { + JobPosting job = jobPostingService.getById(app.getJobId()); + if (job != null) { + app.setBossId(job.getBossId()); + } + } + + boolean res = this.save(app); + if (!res) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return app.getId(); + } + + @Override + public boolean deleteApplication(long id, User loginUser) { + Application app = this.getById(id); + if (app == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + // 管理员可以删除 + if (UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole())) { + return this.removeById(id); + } + + // 本人可以删除 + if (app.getUserId().equals(loginUser.getId())) { + return this.removeById(id); + } + + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + + @Override + public boolean updateApplication(ApplicationUpdateRequest updateRequest, User loginUser) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Application app = this.getById(updateRequest.getId()); + if (app == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + // 管理员可以修改 + if (UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole())) { + BeanUtil.copyProperties(updateRequest, app); + return this.updateById(app); + } + + // 本人可以修改 + if (app.getUserId().equals(loginUser.getId())) { + BeanUtil.copyProperties(updateRequest, app); + return this.updateById(app); + } + + // Boss (招聘方) 也可以修改 (例如修改状态) + if (app.getBossId() != null && app.getBossId().equals(loginUser.getId())) { + BeanUtil.copyProperties(updateRequest, app); + return this.updateById(app); + } + + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + + @Override + @Transactional + public boolean updateApplicationStatus(long applicationId, int status) { + if (applicationId <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请ID不能为空"); + } + if (status != 1 && status != 2) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "状态值必须为1(接受)或2(拒绝)"); + } + + Application app = this.getById(applicationId); + if (app == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "申请不存在"); + } + + app.setStatus(status); + return this.updateById(app); + } + + @Override + public ApplicationVO getApplicationVO(Application app) { + if (app == null) { + return null; + } + ApplicationVO vo = new ApplicationVO(); + BeanUtil.copyProperties(app, vo); + return vo; + } + + @Override + public List getApplicationVOList(List list) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + return list.stream().map(this::getApplicationVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(ApplicationQueryRequest query) { + if (query == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = query.getId(); + Long userId = query.getUserId(); + Long resumeId = query.getResumeId(); + Long jobId = query.getJobId(); + Long bossId = query.getBossId(); + Integer status = query.getStatus(); + String sortField = query.getSortField(); + String sortOrder = query.getSortOrder(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq(ObjUtil.isNotNull(id), "id", id); + qw.eq(ObjUtil.isNotNull(userId), "user_id", userId); + qw.eq(ObjUtil.isNotNull(resumeId), "resume_id", resumeId); + qw.eq(ObjUtil.isNotNull(jobId), "job_id", jobId); + qw.eq(ObjUtil.isNotNull(bossId), "boss_id", bossId); + qw.eq(ObjUtil.isNotNull(status), "status", status); + qw.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return qw; + } + + @Override + public Page listApplicationVOByPage(ApplicationQueryRequest query) { + long current = query.getCurrent(); + long size = query.getPageSize(); + Page page = this.page(new Page<>(current, size), getQueryWrapper(query)); + Page voPage = new Page<>(current, size, page.getTotal()); + voPage.setRecords(getApplicationVOList(page.getRecords())); + return voPage; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/BossApplicationDecisionServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/BossApplicationDecisionServiceImpl.java new file mode 100644 index 0000000..5a9cc84 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/BossApplicationDecisionServiceImpl.java @@ -0,0 +1,174 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.BossApplicationDecisionMapper; +import com.zds.boss.model.dto.decision.BossApplicationDecisionAddRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionQueryRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionUpdateRequest; +import com.zds.boss.model.entity.BossApplicationDecision; +import com.zds.boss.model.vo.BossApplicationDecisionVO; +import com.zds.boss.service.BossApplicationDecisionService; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.service.UserService; +import com.zds.boss.service.ApplicationService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class BossApplicationDecisionServiceImpl extends ServiceImpl + implements BossApplicationDecisionService { + + @Resource + private UserService userService; + + @Resource + private ApplicationService applicationService; + + @Override + @Transactional + public long addDecision(BossApplicationDecisionAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null || addRequest.getApplicationId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + // 验证决策值是否有效 + if (addRequest.getDecision() == null || (addRequest.getDecision() != 1 && addRequest.getDecision() != 2)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "决策值必须为1(接受)或2(拒绝)"); + } + + User loginUser = userService.getLoginUser(request); + + BossApplicationDecision e = new BossApplicationDecision(); + BeanUtil.copyProperties(addRequest, e); + e.setBossId(loginUser.getId()); + e.setDecidedAt(new Date()); // 设置决策时间 + + boolean res = this.save(e); + if (!res) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + + // 更新申请状态 + try { + applicationService.updateApplicationStatus(addRequest.getApplicationId(), addRequest.getDecision()); + } catch (Exception ex) { + log.error("更新申请状态失败", ex); + // 不抛出异常,因为决策已经创建成功 + } + + return e.getId(); + } + + @Override + public boolean deleteDecision(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + BossApplicationDecision decision = this.getById(id); + if (decision == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + if (!isAdmin) { + if (!loginUser.getId().equals(decision.getBossId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + return this.removeById(id); + } + + @Override + public boolean updateDecision(BossApplicationDecisionUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + BossApplicationDecision decision = this.getById(updateRequest.getId()); + if (decision == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + if (!isAdmin) { + if (!loginUser.getId().equals(decision.getBossId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + + BeanUtil.copyProperties(updateRequest, decision); + return this.updateById(decision); + } + + @Override + public BossApplicationDecisionVO getDecisionVO(BossApplicationDecision decision) { + if (decision == null) { + return null; + } + BossApplicationDecisionVO vo = new BossApplicationDecisionVO(); + BeanUtil.copyProperties(decision, vo); + return vo; + } + + @Override + public List getDecisionVOList(List list) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + return list.stream().map(this::getDecisionVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(BossApplicationDecisionQueryRequest query) { + if (query == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = query.getId(); + Long applicationId = query.getApplicationId(); + Long bossId = query.getBossId(); + Integer decision = query.getDecision(); + Integer stage = query.getStage(); + String sortField = query.getSortField(); + String sortOrder = query.getSortOrder(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq(ObjUtil.isNotNull(id), "id", id); + qw.eq(ObjUtil.isNotNull(applicationId), "application_id", applicationId); + qw.eq(ObjUtil.isNotNull(bossId), "boss_id", bossId); + qw.eq(ObjUtil.isNotNull(decision), "decision", decision); + qw.eq(ObjUtil.isNotNull(stage), "stage", stage); + qw.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return qw; + } + + @Override + public Page listDecisionVOByPage(BossApplicationDecisionQueryRequest query) { + long current = query.getCurrent(); + long size = query.getPageSize(); + Page page = this.page(new Page<>(current, size), getQueryWrapper(query)); + Page voPage = new Page<>(current, size, page.getTotal()); + voPage.setRecords(getDecisionVOList(page.getRecords())); + return voPage; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/CompanyServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/CompanyServiceImpl.java new file mode 100644 index 0000000..d3cc54a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/CompanyServiceImpl.java @@ -0,0 +1,165 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.CompanyMapper; +import com.zds.boss.model.dto.company.CompanyAddRequest; +import com.zds.boss.model.dto.company.CompanyQueryRequest; +import com.zds.boss.model.dto.company.CompanyUpdateRequest; +import com.zds.boss.model.entity.Company; +import com.zds.boss.model.vo.CompanyVO; +import com.zds.boss.service.CompanyService; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** +* @author 33882 +* @description 针对表【company(公司表)】的数据库操作Service实现 +* @createDate 2025-12-31 23:47:37 +*/ +@Service +public class CompanyServiceImpl extends ServiceImpl + implements CompanyService{ + + @Resource + private UserService userService; + + @Override + @Transactional(rollbackFor = Exception.class) + public long addCompany(CompanyAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null || StrUtil.isBlank(addRequest.getName())) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + + if (!isAdmin) { + if (!UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "只有BOSS可以创建公司"); + } + if (loginUser.getCompanyId() != null && loginUser.getCompanyId() > 0) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "您已经创建过公司,不能重复创建"); + } + } + + Company company = new Company(); + BeanUtil.copyProperties(addRequest, company); + boolean result = this.save(company); + if (!result) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + + if (!isAdmin) { + loginUser.setCompanyId(company.getId()); + boolean updateUser = userService.updateById(loginUser); + if (!updateUser) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "绑定公司失败"); + } + request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, loginUser); + } + + return company.getId(); + } + + @Override + public boolean deleteCompany(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + if (!isAdmin) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + return this.removeById(id); + } + + @Override + public boolean updateCompany(CompanyUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + + if (!isAdmin) { + if (loginUser.getCompanyId() == null || !loginUser.getCompanyId().equals(updateRequest.getId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + + Company company = new Company(); + BeanUtil.copyProperties(updateRequest, company); + return this.updateById(company); + } + + @Override + public CompanyVO getCompanyVO(Company company) { + if (company == null) { + return null; + } + CompanyVO vo = new CompanyVO(); + BeanUtil.copyProperties(company, vo); + return vo; + } + + @Override + public List getCompanyVOList(List companyList) { + if (CollUtil.isEmpty(companyList)) { + return new ArrayList<>(); + } + return companyList.stream().map(this::getCompanyVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(CompanyQueryRequest queryRequest) { + if (queryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = queryRequest.getId(); + String name = queryRequest.getName(); + String industry = queryRequest.getIndustry(); + Integer status = queryRequest.getStatus(); + String sortField = queryRequest.getSortField(); + String sortOrder = queryRequest.getSortOrder(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq(ObjUtil.isNotNull(id), "id", id); + qw.eq(ObjUtil.isNotNull(status), "status", status); + qw.like(StrUtil.isNotBlank(name), "name", name); + qw.like(StrUtil.isNotBlank(industry), "industry", industry); + qw.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return qw; + } + + @Override + public Page listCompanyVOByPage(CompanyQueryRequest queryRequest) { + long current = queryRequest.getCurrent(); + long size = queryRequest.getPageSize(); + Page page = this.page(new Page<>(current, size), getQueryWrapper(queryRequest)); + Page voPage = new Page<>(current, size, page.getTotal()); + voPage.setRecords(getCompanyVOList(page.getRecords())); + return voPage; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/InterviewServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/InterviewServiceImpl.java new file mode 100644 index 0000000..0bd9b14 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/InterviewServiceImpl.java @@ -0,0 +1,134 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.InterviewMapper; +import com.zds.boss.model.dto.interview.InterviewAddRequest; +import com.zds.boss.model.dto.interview.InterviewQueryRequest; +import com.zds.boss.model.dto.interview.InterviewUpdateRequest; +import com.zds.boss.model.entity.Interview; +import com.zds.boss.model.vo.InterviewVO; +import com.zds.boss.service.InterviewService; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class InterviewServiceImpl extends ServiceImpl implements InterviewService { + + @Resource + private UserService userService; + + @Override + public long addInterview(InterviewAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null || addRequest.getApplicationId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + // 权限:Admin 或 Boss + if (!UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()) && !UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + + Interview e = new Interview(); + BeanUtil.copyProperties(addRequest, e); + + // 如果是 Boss,自动填充 bossId + if (UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole())) { + e.setBossId(loginUser.getId()); + } + + boolean res = this.save(e); + if (!res) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return e.getId(); + } + + @Override + public boolean deleteInterview(long id) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + return this.removeById(id); + } + + @Override + public boolean updateInterview(InterviewUpdateRequest updateRequest) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Interview e = new Interview(); + BeanUtil.copyProperties(updateRequest, e); + return this.updateById(e); + } + + @Override + public InterviewVO getInterviewVO(Interview interview) { + if (interview == null) { + return null; + } + InterviewVO vo = new InterviewVO(); + BeanUtil.copyProperties(interview, vo); + return vo; + } + + @Override + public List getInterviewVOList(List list) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + return list.stream().map(this::getInterviewVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(InterviewQueryRequest query) { + if (query == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = query.getId(); + Long applicationId = query.getApplicationId(); + Long bossId = query.getBossId(); + Long userId = query.getUserId(); + Integer status = query.getStatus(); + String sortField = query.getSortField(); + String sortOrder = query.getSortOrder(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq(ObjUtil.isNotNull(id), "id", id); + qw.eq(ObjUtil.isNotNull(applicationId), "application_id", applicationId); + qw.eq(ObjUtil.isNotNull(bossId), "boss_id", bossId); + qw.eq(ObjUtil.isNotNull(userId), "user_id", userId); + qw.eq(ObjUtil.isNotNull(status), "status", status); + qw.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return qw; + } + + @Override + public Page listInterviewVOByPage(InterviewQueryRequest query) { + long current = query.getCurrent(); + long size = query.getPageSize(); + Page page = this.page(new Page<>(current, size), getQueryWrapper(query)); + Page voPage = new Page<>(current, size, page.getTotal()); + voPage.setRecords(getInterviewVOList(page.getRecords())); + return voPage; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/JobPostingServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/JobPostingServiceImpl.java new file mode 100644 index 0000000..0109bb9 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/JobPostingServiceImpl.java @@ -0,0 +1,166 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.JobPostingMapper; +import com.zds.boss.model.dto.job.JobPostingAddRequest; +import com.zds.boss.model.dto.job.JobPostingQueryRequest; +import com.zds.boss.model.dto.job.JobPostingUpdateRequest; +import com.zds.boss.model.entity.JobPosting; +import com.zds.boss.model.vo.JobPostingVO; +import com.zds.boss.service.JobPostingService; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Service; +import org.springframework.context.annotation.Lazy; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class JobPostingServiceImpl extends ServiceImpl implements JobPostingService { + + @Resource + @Lazy + private UserService userService; + + @Override + public long addJobPosting(JobPostingAddRequest addRequest, HttpServletRequest request) { + if (addRequest == null || StrUtil.isBlank(addRequest.getTitle())) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + + // 权限检查 + if (!UserRoleEnum.BOSS.getValue().equals(loginUser.getUserRole()) && !UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "非Boss权限"); + } + + JobPosting job = new JobPosting(); + BeanUtil.copyProperties(addRequest, job); + job.setBossId(loginUser.getId()); + job.setCompanyId(loginUser.getCompanyId()); + + if (job.getCompanyId() == null || job.getCompanyId() <= 0) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "请先加入或创建公司"); + } + + boolean res = this.save(job); + if (!res) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return job.getId(); + } + + @Override + public boolean deleteJobPosting(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + + if (!isAdmin) { + JobPosting job = this.getById(id); + if (job == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + if (!loginUser.getId().equals(job.getBossId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + return this.removeById(id); + } + + @Override + public boolean updateJobPosting(JobPostingUpdateRequest updateRequest, HttpServletRequest request) { + if (updateRequest == null || updateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + JobPosting job = this.getById(updateRequest.getId()); + if (job == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + + User loginUser = userService.getLoginUser(request); + boolean isAdmin = UserRoleEnum.ADMIN.getValue().equals(loginUser.getUserRole()); + + if (!isAdmin) { + if (!loginUser.getId().equals(job.getBossId())) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + + BeanUtil.copyProperties(updateRequest, job); + return this.updateById(job); + } + + @Override + public JobPostingVO getJobPostingVO(JobPosting job) { + if (job == null) { + return null; + } + JobPostingVO vo = new JobPostingVO(); + BeanUtil.copyProperties(job, vo); + return vo; + } + + @Override + public List getJobPostingVOList(List list) { + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + return list.stream().map(this::getJobPostingVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(JobPostingQueryRequest query) { + if (query == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = query.getId(); + Long bossId = query.getBossId(); + Long companyId = query.getCompanyId(); + String title = query.getTitle(); + String location = query.getLocation(); + String jobType = query.getJobType(); + Integer status = query.getStatus(); + String sortField = query.getSortField(); + String sortOrder = query.getSortOrder(); + + QueryWrapper qw = new QueryWrapper<>(); + qw.eq(ObjUtil.isNotNull(id), "id", id); + qw.eq(ObjUtil.isNotNull(bossId), "boss_id", bossId); + qw.eq(ObjUtil.isNotNull(companyId), "company_id", companyId); + qw.eq(ObjUtil.isNotNull(status), "status", status); + qw.like(StrUtil.isNotBlank(title), "title", title); + qw.like(StrUtil.isNotBlank(location), "location", location); + qw.like(StrUtil.isNotBlank(jobType), "job_type", jobType); + qw.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return qw; + } + + @Override + public Page listJobPostingVOByPage(JobPostingQueryRequest query) { + long current = query.getCurrent(); + long size = query.getPageSize(); + Page page = this.page(new Page<>(current, size), getQueryWrapper(query)); + Page voPage = new Page<>(current, size, page.getTotal()); + voPage.setRecords(getJobPostingVOList(page.getRecords())); + return voPage; + } +} + diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ResumeServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ResumeServiceImpl.java new file mode 100644 index 0000000..24f303a --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/ResumeServiceImpl.java @@ -0,0 +1,137 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.exception.ThrowUtils; +import com.zds.boss.mapper.ResumeMapper; +import com.zds.boss.model.dto.resume.ResumeAddRequest; +import com.zds.boss.model.dto.resume.ResumeQueryRequest; +import com.zds.boss.model.dto.resume.ResumeUpdateRequest; +import com.zds.boss.model.entity.Resume; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.ResumeVO; +import com.zds.boss.service.ResumeService; +import com.zds.boss.utils.UserUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** +* @author 33882 +* @description 针对表【resume(简历表)】的数据库操作Service实现 +* @createDate 2025-12-31 23:30:00 +*/ +@Service +public class ResumeServiceImpl extends ServiceImpl + implements ResumeService { + + @Override + public long addResume(ResumeAddRequest resumeAddRequest, User loginUser) { + if (resumeAddRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Resume resume = new Resume(); + BeanUtil.copyProperties(resumeAddRequest, resume); + // 设置用户ID + resume.setUserId(loginUser.getId()); + + boolean result = this.save(resume); + if (!result) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return resume.getId(); + } + + @Override + public boolean deleteResume(long id, User loginUser) { + Resume resume = this.getById(id); + if (resume == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + // 仅本人或管理员可删除 + if (!resume.getUserId().equals(loginUser.getId()) && !UserUtils.isAdmin(loginUser)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 逻辑删除,MyBatis Plus会自动处理 is_deleted 字段 + return this.removeById(id); + } + + @Override + public boolean updateResume(ResumeUpdateRequest resumeUpdateRequest, User loginUser) { + if (resumeUpdateRequest == null || resumeUpdateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Resume resume = this.getById(resumeUpdateRequest.getId()); + if (resume == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + // 仅本人或管理员可修改 + if (!resume.getUserId().equals(loginUser.getId()) && !UserUtils.isAdmin(loginUser)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + + BeanUtil.copyProperties(resumeUpdateRequest, resume); + return this.updateById(resume); + } + + @Override + public ResumeVO getResumeVO(Resume resume) { + if (resume == null) { + return null; + } + ResumeVO resumeVO = new ResumeVO(); + BeanUtil.copyProperties(resume, resumeVO); + return resumeVO; + } + + @Override + public List getResumeVOList(List resumeList) { + if (CollUtil.isEmpty(resumeList)) { + return new ArrayList<>(); + } + return resumeList.stream().map(this::getResumeVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(ResumeQueryRequest resumeQueryRequest) { + if (resumeQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = resumeQueryRequest.getId(); + Long userId = resumeQueryRequest.getUserId(); + String resumeTitle = resumeQueryRequest.getResumeTitle(); + Integer isDefault = resumeQueryRequest.getIsDefault(); + String sortField = resumeQueryRequest.getSortField(); + String sortOrder = resumeQueryRequest.getSortOrder(); + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(ObjUtil.isNotNull(id), "id", id); + queryWrapper.eq(ObjUtil.isNotNull(userId), "user_id", userId); + queryWrapper.eq(ObjUtil.isNotNull(isDefault), "is_default", isDefault); + queryWrapper.like(StrUtil.isNotBlank(resumeTitle), "resume_title", resumeTitle); + queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + + return queryWrapper; + } + + @Override + public Page listResumeVOByPage(ResumeQueryRequest resumeQueryRequest) { + long current = resumeQueryRequest.getCurrent(); + long size = resumeQueryRequest.getPageSize(); + Page resumePage = this.page(new Page<>(current, size), getQueryWrapper(resumeQueryRequest)); + Page resumeVOPage = new Page<>(current, size, resumePage.getTotal()); + List resumeVOList = getResumeVOList(resumePage.getRecords()); + resumeVOPage.setRecords(resumeVOList); + return resumeVOPage; + } +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/UserServiceImpl.java b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..7ed62be --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/service/impl/UserServiceImpl.java @@ -0,0 +1,265 @@ +package com.zds.boss.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zds.boss.constant.UserConstant; +import com.zds.boss.exception.BusinessException; +import com.zds.boss.exception.ErrorCode; +import com.zds.boss.mapper.UserMapper; +import com.zds.boss.model.dto.user.UserQueryRequest; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.LoginUserVO; +import com.zds.boss.model.vo.UserVO; +import com.zds.boss.service.UserService; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author 33882 + * @description 针对表【user(用户)】的数据库操作Service实现 + * @createDate 2025-09-21 19:45:22 + */ +@Service +@Slf4j +public class UserServiceImpl extends ServiceImpl + implements UserService { + + /** + * @param userAccount + * @param userPassword + * @param checkPassword + * @return + */ + @Override + public long userRegister(String userAccount, String userPassword, String checkPassword, String userRole) { + if (StrUtil.hasBlank(userAccount, userPassword, checkPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); + } + if (!userPassword.equals(checkPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次密码不一致"); + } + if (userAccount.length() < 4) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短"); + } + if (userAccount.length() > 10) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过长"); + } + if (userPassword.length() < 8) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短"); + } + if (userPassword.length() > 15) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过长"); + } + + // 角色处理 + String finalRole = UserRoleEnum.USER.getValue(); + if (StrUtil.isNotBlank(userRole)) { + if ("1".equals(userRole)) { + finalRole = UserRoleEnum.USER.getValue(); + } else if ("2".equals(userRole)) { + finalRole = UserRoleEnum.BOSS.getValue(); + } else if ("3".equals(userRole)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "暂不支持注册管理员"); + } else { + UserRoleEnum roleEnum = UserRoleEnum.getEnumByValue(userRole); + if (roleEnum != null) { + if (UserRoleEnum.ADMIN.equals(roleEnum)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "暂不支持注册管理员"); + } + finalRole = roleEnum.getValue(); + } + } + } + + //校验账号相同 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_account", userAccount); + long count = this.baseMapper.selectCount(queryWrapper); + if (count > 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号已存在"); + } + + //加密 + String pas = getEncryptPassword(userPassword); + + //插入数据 + User user = new User(); + user.setUserAccount(userAccount); + user.setUserPassword(pas); + user.setUserName(userAccount); // 默认昵称 + user.setUserRole(finalRole); + + boolean saveResult = this.save(user); + if (!saveResult) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "注册失败,数据库错误"); + } + return user.getId(); + } + + @Override + public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) { + //校验 + if (StrUtil.hasBlank(userAccount, userPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); + } + if (userAccount.length() < 4 || userAccount.length() > 10) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号错误"); + } + if (userPassword.length() < 8 || userPassword.length() > 15) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码错误"); + } + + //校验密码是否正确 + String pas = getEncryptPassword(userPassword); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_account", userAccount); + queryWrapper.eq("password", pas); + User user = this.baseMapper.selectOne(queryWrapper); + if (user == null) { + log.info("user login failed, userAccount can not match userPassword"); + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户名或密码错误"); + } + //保存用户登录态信息 + request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user); + return getLoginUserVO(user); + } + + /** + * 用户脱敏 + * + * @param user + * @return + */ + @Override + public LoginUserVO getLoginUserVO(User user) { + if (user == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在"); + } + LoginUserVO loginUserVO = new LoginUserVO(); + BeanUtil.copyProperties(user, loginUserVO); + // 数据库无角色字段,默认为 USER + if (loginUserVO.getUserRole() == null) { + loginUserVO.setUserRole(UserRoleEnum.USER.getValue()); + } + return loginUserVO; + } + + @Override + public UserVO getUserVO(User user) { + if (user == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在"); + } + UserVO userVO = new UserVO(); + BeanUtil.copyProperties(user, userVO); + // 数据库无角色字段,默认为 USER + if (userVO.getUserRole() == null) { + userVO.setUserRole(UserRoleEnum.USER.getValue()); + } + return userVO; + } + + @Override + public List getUserVOList(List userList) { + if (CollUtil.isEmpty(userList)) { + return new ArrayList<>(); + } + return userList.stream().map(this::getUserVO).collect(Collectors.toList()); + } + + /** + * 密码加密 + * + * @param userPassword 用户输入的原始密码 + * @return + */ + @Override + public String getEncryptPassword(String userPassword) { + // 盐值,混淆密码 + final String SALT = "zhengdushi"; + return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes()); + } + + @Override + public User getLoginUser(HttpServletRequest request) { + // 先判断是否已登录 + // 从会话中获取登录用户对象 + Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE); + User currentUser = (User) userObj; + // 检查用户对象或用户ID是否为空 + if (currentUser == null || currentUser.getId() == null) { + // 如果未登录,抛出业务异常 + throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); + } + // 从数据库查询(追求性能的话可以注释,直接返回上述结果) + // 获取用户ID + long userId = currentUser.getId(); + // 根据ID从数据库查询用户信息 + currentUser = this.getById(userId); + // 检查数据库中是否存在该用户 + if (currentUser == null) { + // 如果用户不存在,抛出业务异常 + throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); + } + return currentUser; + } + + /** + * 用户登出方法 + * + * @param request HttpServletRequest对象,用于获取会话信息 + * @return 登出成功返回true + * @throws BusinessException 当用户未登录时抛出业务异常 + */ + @Override + public boolean userLogOut(HttpServletRequest request) { + // 从会话中获取用户登录状态信息 + Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE); + // 检查用户是否已登录 + if (userObj == null) { + // 如果用户未登录,抛出业务异常 + throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户未登录"); + } + // 移除登录态,使用户登出 + request.getSession().invalidate(); + // 返回登出成功标志 + return true; + } + + /** + * 获取查询条件 + * @param userQueryRequest + * @return + */ + @Override + public QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest) { + if (userQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = userQueryRequest.getId(); + String userAccount = userQueryRequest.getUserAccount(); + String userName = userQueryRequest.getUserName(); + String userProfile = userQueryRequest.getUserProfile(); + String sortField = userQueryRequest.getSortField(); + String sortOrder = userQueryRequest.getSortOrder(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(ObjUtil.isNotNull(id), "id", id); + queryWrapper.like(StrUtil.isNotBlank(userAccount), "user_account", userAccount); + queryWrapper.like(StrUtil.isNotBlank(userName), "username", userName); + queryWrapper.like(StrUtil.isNotBlank(userProfile), "profile", userProfile); + queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField); + return queryWrapper; + } + + +} diff --git a/BOSSBackEnd/src/main/java/com/zds/boss/utils/UserUtils.java b/BOSSBackEnd/src/main/java/com/zds/boss/utils/UserUtils.java new file mode 100644 index 0000000..38cbe97 --- /dev/null +++ b/BOSSBackEnd/src/main/java/com/zds/boss/utils/UserUtils.java @@ -0,0 +1,25 @@ +package com.zds.boss.utils; + +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import org.springframework.stereotype.Component; + +/** + * 用户工具类 + */ +@Component +public class UserUtils { + + /** + * 判断用户是否是管理员 + * + * @param user 用户对象 + * @return true 如果是管理员,否则 false + */ + public static boolean isAdmin(User user) { + if (user == null || user.getUserRole() == null) { + return false; + } + return UserRoleEnum.ADMIN.getValue().equals(user.getUserRole()); + } +} diff --git a/BOSSBackEnd/src/main/java/generator/domain/Application.java b/BOSSBackEnd/src/main/java/generator/domain/Application.java new file mode 100644 index 0000000..3236701 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/domain/Application.java @@ -0,0 +1,117 @@ +package generator.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 用户投递记录表 + * @TableName application + */ +@TableName(value ="application") +@Data +public class Application implements Serializable { + /** + * 投递ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID(无外键) + */ + private Long userId; + + /** + * 简历ID(无外键,可为空) + */ + private Long resumeId; + + /** + * 岗位ID(无外键,建议配岗位表) + */ + private Long jobId; + + /** + * BossID(无外键,冗余字段便于查) + */ + private Long bossId; + + /** + * 状态:0已投递 1已撤回 2已过期 + */ + private Integer status; + + /** + * 投递时间 + */ + private Date appliedAt; + + /** + * + */ + private Date updatedAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + Application other = (Application) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) + && (this.getResumeId() == null ? other.getResumeId() == null : this.getResumeId().equals(other.getResumeId())) + && (this.getJobId() == null ? other.getJobId() == null : this.getJobId().equals(other.getJobId())) + && (this.getBossId() == null ? other.getBossId() == null : this.getBossId().equals(other.getBossId())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getAppliedAt() == null ? other.getAppliedAt() == null : this.getAppliedAt().equals(other.getAppliedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); + result = prime * result + ((getResumeId() == null) ? 0 : getResumeId().hashCode()); + result = prime * result + ((getJobId() == null) ? 0 : getJobId().hashCode()); + result = prime * result + ((getBossId() == null) ? 0 : getBossId().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getAppliedAt() == null) ? 0 : getAppliedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", userId=").append(userId); + sb.append(", resumeId=").append(resumeId); + sb.append(", jobId=").append(jobId); + sb.append(", bossId=").append(bossId); + sb.append(", status=").append(status); + sb.append(", appliedAt=").append(appliedAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/generator/domain/BossApplicationDecision.java b/BOSSBackEnd/src/main/java/generator/domain/BossApplicationDecision.java new file mode 100644 index 0000000..351aa6b --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/domain/BossApplicationDecision.java @@ -0,0 +1,117 @@ +package generator.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * Boss处理投递(接受/拒绝)表 + * @TableName boss_application_decision + */ +@TableName(value ="boss_application_decision") +@Data +public class BossApplicationDecision implements Serializable { + /** + * ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 投递ID(无外键) + */ + private Long applicationId; + + /** + * BossID(无外键) + */ + private Long bossId; + + /** + * 处理结果:1接受/进入流程 2拒绝 3待定 + */ + private Integer decision; + + /** + * 阶段:0筛选 1邀面 2面试 3Offer 4结束 + */ + private Integer stage; + + /** + * 备注 + */ + private String note; + + /** + * 处理时间 + */ + private Date decidedAt; + + /** + * + */ + private Date updatedAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + BossApplicationDecision other = (BossApplicationDecision) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getApplicationId() == null ? other.getApplicationId() == null : this.getApplicationId().equals(other.getApplicationId())) + && (this.getBossId() == null ? other.getBossId() == null : this.getBossId().equals(other.getBossId())) + && (this.getDecision() == null ? other.getDecision() == null : this.getDecision().equals(other.getDecision())) + && (this.getStage() == null ? other.getStage() == null : this.getStage().equals(other.getStage())) + && (this.getNote() == null ? other.getNote() == null : this.getNote().equals(other.getNote())) + && (this.getDecidedAt() == null ? other.getDecidedAt() == null : this.getDecidedAt().equals(other.getDecidedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getApplicationId() == null) ? 0 : getApplicationId().hashCode()); + result = prime * result + ((getBossId() == null) ? 0 : getBossId().hashCode()); + result = prime * result + ((getDecision() == null) ? 0 : getDecision().hashCode()); + result = prime * result + ((getStage() == null) ? 0 : getStage().hashCode()); + result = prime * result + ((getNote() == null) ? 0 : getNote().hashCode()); + result = prime * result + ((getDecidedAt() == null) ? 0 : getDecidedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", applicationId=").append(applicationId); + sb.append(", bossId=").append(bossId); + sb.append(", decision=").append(decision); + sb.append(", stage=").append(stage); + sb.append(", note=").append(note); + sb.append(", decidedAt=").append(decidedAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/generator/domain/Interview.java b/BOSSBackEnd/src/main/java/generator/domain/Interview.java new file mode 100644 index 0000000..f05b1a6 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/domain/Interview.java @@ -0,0 +1,141 @@ +package generator.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 面试安排表 + * @TableName interview + */ +@TableName(value ="interview") +@Data +public class Interview implements Serializable { + /** + * 面试ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 投递ID(无外键) + */ + private Long applicationId; + + /** + * BossID(无外键) + */ + private Long bossId; + + /** + * 用户ID(无外键) + */ + private Long userId; + + /** + * 面试时间 + */ + private Date interviewTime; + + /** + * 方式:0线上 1线下 + */ + private Integer mode; + + /** + * 地点/会议链接 + */ + private String location; + + /** + * 状态:0待确认 1已确认 2已完成 3取消 + */ + private Integer status; + + /** + * + */ + private String note; + + /** + * + */ + private Date createdAt; + + /** + * + */ + private Date updatedAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + Interview other = (Interview) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getApplicationId() == null ? other.getApplicationId() == null : this.getApplicationId().equals(other.getApplicationId())) + && (this.getBossId() == null ? other.getBossId() == null : this.getBossId().equals(other.getBossId())) + && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) + && (this.getInterviewTime() == null ? other.getInterviewTime() == null : this.getInterviewTime().equals(other.getInterviewTime())) + && (this.getMode() == null ? other.getMode() == null : this.getMode().equals(other.getMode())) + && (this.getLocation() == null ? other.getLocation() == null : this.getLocation().equals(other.getLocation())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getNote() == null ? other.getNote() == null : this.getNote().equals(other.getNote())) + && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getApplicationId() == null) ? 0 : getApplicationId().hashCode()); + result = prime * result + ((getBossId() == null) ? 0 : getBossId().hashCode()); + result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); + result = prime * result + ((getInterviewTime() == null) ? 0 : getInterviewTime().hashCode()); + result = prime * result + ((getMode() == null) ? 0 : getMode().hashCode()); + result = prime * result + ((getLocation() == null) ? 0 : getLocation().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getNote() == null) ? 0 : getNote().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", applicationId=").append(applicationId); + sb.append(", bossId=").append(bossId); + sb.append(", userId=").append(userId); + sb.append(", interviewTime=").append(interviewTime); + sb.append(", mode=").append(mode); + sb.append(", location=").append(location); + sb.append(", status=").append(status); + sb.append(", note=").append(note); + sb.append(", createdAt=").append(createdAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/generator/domain/JobPosting.java b/BOSSBackEnd/src/main/java/generator/domain/JobPosting.java new file mode 100644 index 0000000..97e1b98 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/domain/JobPosting.java @@ -0,0 +1,165 @@ +package generator.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 岗位表 + * @TableName job_posting + */ +@TableName(value ="job_posting") +@Data +public class JobPosting implements Serializable { + /** + * 岗位ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * BossID(无外键) + */ + private Long bossId; + + /** + * 公司ID(无外键) + */ + private Long companyId; + + /** + * 岗位名称 + */ + private String title; + + /** + * 地点 + */ + private String location; + + /** + * 类型:全职/实习 + */ + private String jobType; + + /** + * + */ + private Integer salaryMin; + + /** + * + */ + private Integer salaryMax; + + /** + * 描述 + */ + private String description; + + /** + * 要求 + */ + private String requirement; + + /** + * 状态:0草稿 1发布 2关闭 + */ + private Integer status; + + /** + * + */ + private Date publishAt; + + /** + * + */ + private Date createdAt; + + /** + * + */ + private Date updatedAt; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + JobPosting other = (JobPosting) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getBossId() == null ? other.getBossId() == null : this.getBossId().equals(other.getBossId())) + && (this.getCompanyId() == null ? other.getCompanyId() == null : this.getCompanyId().equals(other.getCompanyId())) + && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle())) + && (this.getLocation() == null ? other.getLocation() == null : this.getLocation().equals(other.getLocation())) + && (this.getJobType() == null ? other.getJobType() == null : this.getJobType().equals(other.getJobType())) + && (this.getSalaryMin() == null ? other.getSalaryMin() == null : this.getSalaryMin().equals(other.getSalaryMin())) + && (this.getSalaryMax() == null ? other.getSalaryMax() == null : this.getSalaryMax().equals(other.getSalaryMax())) + && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription())) + && (this.getRequirement() == null ? other.getRequirement() == null : this.getRequirement().equals(other.getRequirement())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getPublishAt() == null ? other.getPublishAt() == null : this.getPublishAt().equals(other.getPublishAt())) + && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())) + && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getBossId() == null) ? 0 : getBossId().hashCode()); + result = prime * result + ((getCompanyId() == null) ? 0 : getCompanyId().hashCode()); + result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode()); + result = prime * result + ((getLocation() == null) ? 0 : getLocation().hashCode()); + result = prime * result + ((getJobType() == null) ? 0 : getJobType().hashCode()); + result = prime * result + ((getSalaryMin() == null) ? 0 : getSalaryMin().hashCode()); + result = prime * result + ((getSalaryMax() == null) ? 0 : getSalaryMax().hashCode()); + result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode()); + result = prime * result + ((getRequirement() == null) ? 0 : getRequirement().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getPublishAt() == null) ? 0 : getPublishAt().hashCode()); + result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", bossId=").append(bossId); + sb.append(", companyId=").append(companyId); + sb.append(", title=").append(title); + sb.append(", location=").append(location); + sb.append(", jobType=").append(jobType); + sb.append(", salaryMin=").append(salaryMin); + sb.append(", salaryMax=").append(salaryMax); + sb.append(", description=").append(description); + sb.append(", requirement=").append(requirement); + sb.append(", status=").append(status); + sb.append(", publishAt=").append(publishAt); + sb.append(", createdAt=").append(createdAt); + sb.append(", updatedAt=").append(updatedAt); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/BOSSBackEnd/src/main/java/generator/mapper/ApplicationMapper.java b/BOSSBackEnd/src/main/java/generator/mapper/ApplicationMapper.java new file mode 100644 index 0000000..06915ba --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/mapper/ApplicationMapper.java @@ -0,0 +1,18 @@ +package generator.mapper; + +import generator.domain.Application; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【application(用户投递记录表)】的数据库操作Mapper +* @createDate 2026-01-01 00:03:28 +* @Entity generator.domain.Application +*/ +public interface ApplicationMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/mapper/BossApplicationDecisionMapper.java b/BOSSBackEnd/src/main/java/generator/mapper/BossApplicationDecisionMapper.java new file mode 100644 index 0000000..cd18354 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/mapper/BossApplicationDecisionMapper.java @@ -0,0 +1,18 @@ +package generator.mapper; + +import generator.domain.BossApplicationDecision; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【boss_application_decision(Boss处理投递(接受/拒绝)表)】的数据库操作Mapper +* @createDate 2026-01-01 00:02:27 +* @Entity generator.domain.BossApplicationDecision +*/ +public interface BossApplicationDecisionMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/mapper/InterviewMapper.java b/BOSSBackEnd/src/main/java/generator/mapper/InterviewMapper.java new file mode 100644 index 0000000..ed45994 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/mapper/InterviewMapper.java @@ -0,0 +1,18 @@ +package generator.mapper; + +import generator.domain.Interview; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【interview(面试安排表)】的数据库操作Mapper +* @createDate 2026-01-01 00:03:01 +* @Entity generator.domain.Interview +*/ +public interface InterviewMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/mapper/JobPostingMapper.java b/BOSSBackEnd/src/main/java/generator/mapper/JobPostingMapper.java new file mode 100644 index 0000000..8ea8d89 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/mapper/JobPostingMapper.java @@ -0,0 +1,18 @@ +package generator.mapper; + +import generator.domain.JobPosting; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author 33882 +* @description 针对表【job_posting(岗位表)】的数据库操作Mapper +* @createDate 2026-01-01 00:02:54 +* @Entity generator.domain.JobPosting +*/ +public interface JobPostingMapper extends BaseMapper { + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/service/ApplicationService.java b/BOSSBackEnd/src/main/java/generator/service/ApplicationService.java new file mode 100644 index 0000000..781b641 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/ApplicationService.java @@ -0,0 +1,13 @@ +package generator.service; + +import generator.domain.Application; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 33882 +* @description 针对表【application(用户投递记录表)】的数据库操作Service +* @createDate 2026-01-01 00:03:28 +*/ +public interface ApplicationService extends IService { + +} diff --git a/BOSSBackEnd/src/main/java/generator/service/BossApplicationDecisionService.java b/BOSSBackEnd/src/main/java/generator/service/BossApplicationDecisionService.java new file mode 100644 index 0000000..763ef68 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/BossApplicationDecisionService.java @@ -0,0 +1,13 @@ +package generator.service; + +import generator.domain.BossApplicationDecision; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 33882 +* @description 针对表【boss_application_decision(Boss处理投递(接受/拒绝)表)】的数据库操作Service +* @createDate 2026-01-01 00:02:27 +*/ +public interface BossApplicationDecisionService extends IService { + +} diff --git a/BOSSBackEnd/src/main/java/generator/service/InterviewService.java b/BOSSBackEnd/src/main/java/generator/service/InterviewService.java new file mode 100644 index 0000000..84590c7 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/InterviewService.java @@ -0,0 +1,13 @@ +package generator.service; + +import generator.domain.Interview; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 33882 +* @description 针对表【interview(面试安排表)】的数据库操作Service +* @createDate 2026-01-01 00:03:01 +*/ +public interface InterviewService extends IService { + +} diff --git a/BOSSBackEnd/src/main/java/generator/service/JobPostingService.java b/BOSSBackEnd/src/main/java/generator/service/JobPostingService.java new file mode 100644 index 0000000..28b64f3 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/JobPostingService.java @@ -0,0 +1,13 @@ +package generator.service; + +import generator.domain.JobPosting; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author 33882 +* @description 针对表【job_posting(岗位表)】的数据库操作Service +* @createDate 2026-01-01 00:02:54 +*/ +public interface JobPostingService extends IService { + +} diff --git a/BOSSBackEnd/src/main/java/generator/service/impl/ApplicationServiceImpl.java b/BOSSBackEnd/src/main/java/generator/service/impl/ApplicationServiceImpl.java new file mode 100644 index 0000000..16a5905 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/impl/ApplicationServiceImpl.java @@ -0,0 +1,22 @@ +package generator.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import generator.domain.Application; +import generator.service.ApplicationService; +import generator.mapper.ApplicationMapper; +import org.springframework.stereotype.Service; + +/** +* @author 33882 +* @description 针对表【application(用户投递记录表)】的数据库操作Service实现 +* @createDate 2026-01-01 00:03:28 +*/ +@Service +public class ApplicationServiceImpl extends ServiceImpl + implements ApplicationService{ + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/service/impl/BossApplicationDecisionServiceImpl.java b/BOSSBackEnd/src/main/java/generator/service/impl/BossApplicationDecisionServiceImpl.java new file mode 100644 index 0000000..53baa94 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/impl/BossApplicationDecisionServiceImpl.java @@ -0,0 +1,22 @@ +package generator.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import generator.domain.BossApplicationDecision; +import generator.service.BossApplicationDecisionService; +import generator.mapper.BossApplicationDecisionMapper; +import org.springframework.stereotype.Service; + +/** +* @author 33882 +* @description 针对表【boss_application_decision(Boss处理投递(接受/拒绝)表)】的数据库操作Service实现 +* @createDate 2026-01-01 00:02:27 +*/ +@Service +public class BossApplicationDecisionServiceImpl extends ServiceImpl + implements BossApplicationDecisionService{ + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/service/impl/InterviewServiceImpl.java b/BOSSBackEnd/src/main/java/generator/service/impl/InterviewServiceImpl.java new file mode 100644 index 0000000..7edcac6 --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/impl/InterviewServiceImpl.java @@ -0,0 +1,22 @@ +package generator.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import generator.domain.Interview; +import generator.service.InterviewService; +import generator.mapper.InterviewMapper; +import org.springframework.stereotype.Service; + +/** +* @author 33882 +* @description 针对表【interview(面试安排表)】的数据库操作Service实现 +* @createDate 2026-01-01 00:03:01 +*/ +@Service +public class InterviewServiceImpl extends ServiceImpl + implements InterviewService{ + +} + + + + diff --git a/BOSSBackEnd/src/main/java/generator/service/impl/JobPostingServiceImpl.java b/BOSSBackEnd/src/main/java/generator/service/impl/JobPostingServiceImpl.java new file mode 100644 index 0000000..98018bf --- /dev/null +++ b/BOSSBackEnd/src/main/java/generator/service/impl/JobPostingServiceImpl.java @@ -0,0 +1,22 @@ +package generator.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import generator.domain.JobPosting; +import generator.service.JobPostingService; +import generator.mapper.JobPostingMapper; +import org.springframework.stereotype.Service; + +/** +* @author 33882 +* @description 针对表【job_posting(岗位表)】的数据库操作Service实现 +* @createDate 2026-01-01 00:02:54 +*/ +@Service +public class JobPostingServiceImpl extends ServiceImpl + implements JobPostingService{ + +} + + + + diff --git a/BOSSBackEnd/src/main/resources/application.yml b/BOSSBackEnd/src/main/resources/application.yml new file mode 100644 index 0000000..bd98e05 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/application.yml @@ -0,0 +1,73 @@ +server: + port: 8081 + servlet: + session: + cookie: + max-age: 2592000s + +spring: + servlet: + multipart: + enabled: true + max-file-size: 10MB + max-request-size: 10MB + file-size-threshold: 1MB + resolve-lazily: true # 延迟解析,避免提前解析导致 boundary 错误 + session: + store-type: redis + timeout: 30d + application: + name: BOSS + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/boss?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: root + password: 123456 + hikari: + maximum-pool-size: 20 + minimum-idle: 5 + connection-timeout: 30000 + + data: + redis: + host: 127.0.0.1 + port: 6379 + database: 0 + password: "" # ????????? + timeout: 5s + lettuce: + pool: + max-active: 16 + max-idle: 8 + min-idle: 0 + max-wait: 2s + +# 关闭自动数据库初始化 + sql: + init: + mode: never + + +mybatis-plus: + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + logic-delete-field: isDelete # 全局逻辑删除字段名 + logic-delete-value: 1 # 逻辑已删除值 + logic-not-delete-value: 0 # 逻辑未删除值 + +logging: + level: + root: info + com.zds.boss.mapper: debug + +# 本地文件存储配置 +file: + # 文件存储路径(相对于项目根目录) + storage: + path: src/main/resources/static + # 最大文件大小(MB) + max-size-mb: 10 diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/ApplicationMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/ApplicationMapper.xml new file mode 100644 index 0000000..f1c79c8 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/ApplicationMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,user_id,resume_id,job_id,boss_id,status,applied_at,updated_at + + + diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/BossApplicationDecisionMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/BossApplicationDecisionMapper.xml new file mode 100644 index 0000000..6897e54 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/BossApplicationDecisionMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,application_id,boss_id,decision,stage,note,decided_at,updated_at + + + diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/CompanyMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/CompanyMapper.xml new file mode 100644 index 0000000..e44cc62 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/CompanyMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + id,name,industry,size_range,website,address, + intro,status,created_at,updated_at + + diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/InterviewMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/InterviewMapper.xml new file mode 100644 index 0000000..91fd300 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/InterviewMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + id,application_id,boss_id,user_id,interview_time,mode,location,status,note,created_at,updated_at + + + diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/JobPostingMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/JobPostingMapper.xml new file mode 100644 index 0000000..33c2d63 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/JobPostingMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + id,boss_id,company_id,title,location,job_type,salary_min,salary_max,description,requirement,status,publish_at,created_at,updated_at + + + diff --git a/BOSSBackEnd/src/main/resources/generator/mapper/userMapper.xml b/BOSSBackEnd/src/main/resources/generator/mapper/userMapper.xml new file mode 100644 index 0000000..d1ea371 --- /dev/null +++ b/BOSSBackEnd/src/main/resources/generator/mapper/userMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + id,user_account,password,phone,email,username, + status,created_at,updated_at,is_deleted, + profile + + diff --git a/BOSSBackEnd/src/test/java/com/zds/boss/BossApplicationTests.java b/BOSSBackEnd/src/test/java/com/zds/boss/BossApplicationTests.java new file mode 100644 index 0000000..6c5a03c --- /dev/null +++ b/BOSSBackEnd/src/test/java/com/zds/boss/BossApplicationTests.java @@ -0,0 +1,39 @@ +package com.zds.boss; + +import com.zds.boss.model.vo.LoginUserVO; +import com.zds.boss.service.UserService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletRequest; + +@SpringBootTest +class BossApplicationTests { + + @Resource + private UserService userService; + + @Test + void testRegisterAndLogin() { + String account = "test" + (System.currentTimeMillis() % 1000); // ensure short enough + String password = "password123"; + + // 1. Register + long userId = userService.userRegister(account, password, password, "1"); + Assertions.assertTrue(userId > 0); + + // 2. Login + MockHttpServletRequest request = new MockHttpServletRequest(); + LoginUserVO loginUserVO = userService.userLogin(account, password, request); + + // 3. Verify + Assertions.assertNotNull(loginUserVO); + Assertions.assertEquals(account, loginUserVO.getUserAccount()); + // Verify default role + Assertions.assertEquals("user", loginUserVO.getUserRole()); + + System.out.println("Test passed! User registered and logged in successfully. Role: " + loginUserVO.getUserRole()); + } + +} diff --git a/BOSSBackEnd/src/test/java/com/zds/boss/FullFlowTests.java b/BOSSBackEnd/src/test/java/com/zds/boss/FullFlowTests.java new file mode 100644 index 0000000..46b4403 --- /dev/null +++ b/BOSSBackEnd/src/test/java/com/zds/boss/FullFlowTests.java @@ -0,0 +1,116 @@ +package com.zds.boss; + +import com.zds.boss.constant.UserConstant; +import com.zds.boss.model.dto.application.ApplicationAddRequest; +import com.zds.boss.model.dto.company.CompanyAddRequest; +import com.zds.boss.model.dto.decision.BossApplicationDecisionAddRequest; +import com.zds.boss.model.dto.job.JobPostingAddRequest; +import com.zds.boss.model.entity.User; +import com.zds.boss.model.enums.UserRoleEnum; +import com.zds.boss.model.vo.LoginUserVO; +import com.zds.boss.model.dto.interview.InterviewAddRequest; +import com.zds.boss.service.*; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpSession; + +import java.util.Date; + +@SpringBootTest +class FullFlowTests { + + @Resource + private UserService userService; + @Resource + private CompanyService companyService; + @Resource + private JobPostingService jobPostingService; + @Resource + private ApplicationService applicationService; + @Resource + private BossApplicationDecisionService decisionService; + @Resource + private InterviewService interviewService; + + @Test + void testFullRecruitmentFlow() { + // --- 1. 注册 Boss --- + String bossAccount = "boss_" + (System.currentTimeMillis() % 100000); + String password = "password123"; + long bossId = userService.userRegister(bossAccount, password, password, "2"); // 2 for Boss + Assertions.assertTrue(bossId > 0); + + // Boss 登录 + MockHttpServletRequest bossRequest = new MockHttpServletRequest(); + MockHttpSession bossSession = new MockHttpSession(); + bossRequest.setSession(bossSession); + + LoginUserVO bossVO = userService.userLogin(bossAccount, password, bossRequest); + Assertions.assertEquals(UserRoleEnum.BOSS.getValue(), bossVO.getUserRole()); + + // --- 2. Boss 创建公司 --- + CompanyAddRequest companyReq = new CompanyAddRequest(); + companyReq.setName("Tech Corp " + System.currentTimeMillis()); + companyReq.setIndustry("IT"); + long companyId = companyService.addCompany(companyReq, bossRequest); + Assertions.assertTrue(companyId > 0); + + // 验证 Boss 关联了公司 + User bossUser = userService.getById(bossId); + Assertions.assertEquals(companyId, bossUser.getCompanyId()); + + // --- 3. Boss 发布职位 --- + JobPostingAddRequest jobReq = new JobPostingAddRequest(); + jobReq.setTitle("Java Developer"); + jobReq.setDescription("Write Java code"); + jobReq.setRequirement("Know Spring Boot"); + // 更新 request 中的 user session (因为 addCompany 更新了 user) + bossSession.setAttribute(UserConstant.USER_LOGIN_STATE, bossUser); + + long jobId = jobPostingService.addJobPosting(jobReq, bossRequest); + Assertions.assertTrue(jobId > 0); + + // --- 4. 注册求职者 --- + String userAccount = "user_" + (System.currentTimeMillis() % 100000); + long userId = userService.userRegister(userAccount, password, password, "1"); // 1 for User + Assertions.assertTrue(userId > 0); + + // 求职者登录 + MockHttpServletRequest userRequest = new MockHttpServletRequest(); + MockHttpSession userSession = new MockHttpSession(); + userRequest.setSession(userSession); + LoginUserVO userVO = userService.userLogin(userAccount, password, userRequest); + User userUser = userService.getById(userId); + + // --- 5. 求职者投递 --- + ApplicationAddRequest appReq = new ApplicationAddRequest(); + appReq.setJobId(jobId); + long appId = applicationService.addApplication(appReq, userUser); + Assertions.assertTrue(appId > 0); + + // --- 6. Boss 处理投递 --- + BossApplicationDecisionAddRequest decisionReq = new BossApplicationDecisionAddRequest(); + decisionReq.setApplicationId(appId); + decisionReq.setDecision(1); // Accept + decisionReq.setStage(1); // Interview + + long decisionId = decisionService.addDecision(decisionReq, bossRequest); + Assertions.assertTrue(decisionId > 0); + + // --- 7. Boss 发起面试 --- + InterviewAddRequest interviewReq = new InterviewAddRequest(); + interviewReq.setApplicationId(appId); + interviewReq.setUserId(userId); + interviewReq.setInterviewTime(new Date()); + interviewReq.setMode(0); // Online + interviewReq.setLocation("Zoom Link"); + + long interviewId = interviewService.addInterview(interviewReq, bossRequest); + Assertions.assertTrue(interviewId > 0); + + System.out.println("Full flow test passed!"); + } +} diff --git a/BOSSFrontEnd/.idea/.gitignore b/BOSSFrontEnd/.idea/.gitignore new file mode 100644 index 0000000..10b731c --- /dev/null +++ b/BOSSFrontEnd/.idea/.gitignore @@ -0,0 +1,5 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ diff --git a/BOSSFrontEnd/.idea/BOSSFrontEnd.iml b/BOSSFrontEnd/.idea/BOSSFrontEnd.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/BOSSFrontEnd/.idea/BOSSFrontEnd.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/.idea/modules.xml b/BOSSFrontEnd/.idea/modules.xml new file mode 100644 index 0000000..19381cb --- /dev/null +++ b/BOSSFrontEnd/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/.idea/vcs.xml b/BOSSFrontEnd/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/BOSSFrontEnd/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/.gitignore b/BOSSFrontEnd/BOSS/.gitignore new file mode 100644 index 0000000..a3f7a51 --- /dev/null +++ b/BOSSFrontEnd/BOSS/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +.eslintcache + +# Cypress +/cypress/videos/ +/cypress/screenshots/ + +# Vitest +__screenshots__/ diff --git a/BOSSFrontEnd/BOSS/.prettierrc.json b/BOSSFrontEnd/BOSS/.prettierrc.json new file mode 100644 index 0000000..29a2402 --- /dev/null +++ b/BOSSFrontEnd/BOSS/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "singleQuote": true, + "printWidth": 100 +} diff --git a/BOSSFrontEnd/BOSS/.vscode/extensions.json b/BOSSFrontEnd/BOSS/.vscode/extensions.json new file mode 100644 index 0000000..f473615 --- /dev/null +++ b/BOSSFrontEnd/BOSS/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "Vue.volar", + "prettier.prettier-vscode" + ] +} diff --git a/BOSSFrontEnd/BOSS/README.md b/BOSSFrontEnd/BOSS/README.md new file mode 100644 index 0000000..afe2e42 --- /dev/null +++ b/BOSSFrontEnd/BOSS/README.md @@ -0,0 +1,42 @@ +# BOSS + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Recommended Browser Setup + +- Chromium-based browsers (Chrome, Edge, Brave, etc.): + - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) + - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters) +- Firefox: + - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/) + - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/) + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` diff --git a/BOSSFrontEnd/BOSS/env.d.ts b/BOSSFrontEnd/BOSS/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/BOSSFrontEnd/BOSS/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/BOSSFrontEnd/BOSS/index.html b/BOSSFrontEnd/BOSS/index.html new file mode 100644 index 0000000..74383db --- /dev/null +++ b/BOSSFrontEnd/BOSS/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/BOSSFrontEnd/BOSS/mock-api.json b/BOSSFrontEnd/BOSS/mock-api.json new file mode 100644 index 0000000..7e32d70 --- /dev/null +++ b/BOSSFrontEnd/BOSS/mock-api.json @@ -0,0 +1,178 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "BOSS Backend API", + "version": "1.0.0" + }, + "paths": { + "/api/users": { + "get": { + "summary": "Get all users", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "number" + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "summary": "Create a user", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/users/{id}": { + "get": { + "summary": "Get user by ID", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "number" + }, + "data": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + }, + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "summary": "Update user by ID", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + }, + "delete": { + "summary": "Delete user by ID", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "Successful response" + } + } + } + } + } +} \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/openapi.config.ts b/BOSSFrontEnd/BOSS/openapi.config.ts new file mode 100644 index 0000000..e82651d --- /dev/null +++ b/BOSSFrontEnd/BOSS/openapi.config.ts @@ -0,0 +1,18 @@ +import { generateService } from '@umijs/openapi'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +// 获取当前文件目录 +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// 生成 API 服务代码 +generateService({ + requestLibPath: "import request from '@/libs/request'", + schemaPath: 'http://localhost:8082/v3/api-docs', + serversPath: join(__dirname, 'src/api'), + mock: false, +}).catch((error) => { + console.error('API生成失败:', error); + process.exit(1); +}); diff --git a/BOSSFrontEnd/BOSS/package-lock.json b/BOSSFrontEnd/BOSS/package-lock.json new file mode 100644 index 0000000..acf518c --- /dev/null +++ b/BOSSFrontEnd/BOSS/package-lock.json @@ -0,0 +1,5188 @@ +{ + "name": "boss", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "boss", + "version": "0.0.0", + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "ant-design-vue": "^4.2.6", + "axios": "^1.13.2", + "pinia": "^3.0.4", + "vue": "^3.5.26", + "vue-router": "^4.6.4" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.3", + "@types/node": "^24.10.4", + "@umijs/openapi": "^1.14.1", + "@vitejs/plugin-vue": "^6.0.3", + "@vue/tsconfig": "^0.8.1", + "npm-run-all2": "^8.0.4", + "prettier": "3.7.4", + "ts-node": "^10.9.2", + "tslib": "^2.8.1", + "tsx": "^4.21.0", + "typescript": "~5.9.3", + "umi-request": "^1.4.0", + "vite": "^7.3.0", + "vite-plugin-vue-devtools": "^8.0.5", + "vue-tsc": "^3.2.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/icons-vue": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-7.0.1.tgz", + "integrity": "sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1" + }, + "peerDependencies": { + "vue": ">=3.0.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", + "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz", + "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz", + "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz", + "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz", + "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz", + "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz", + "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz", + "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz", + "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz", + "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz", + "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz", + "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz", + "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz", + "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz", + "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz", + "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz", + "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz", + "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz", + "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz", + "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz", + "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz", + "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz", + "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@simonwep/pickr": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.8.2.tgz", + "integrity": "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==", + "license": "MIT", + "dependencies": { + "core-js": "^3.15.1", + "nanopop": "^2.1.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node24": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.3.tgz", + "integrity": "sha512-vcERKtKQKHgzt/vfS3Gjasd8SUI2a0WZXpgJURdJsMySpS5+ctgbPfuLj2z/W+w4lAfTWxoN4upKfu2WzIRYnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz", + "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@umijs/openapi": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@umijs/openapi/-/openapi-1.14.1.tgz", + "integrity": "sha512-riFsBjdg6OLNKWCxSyZ4BFmVKd1KkkGebxUCoDiKfz1p6L5CBiw8yVZd8J22Q/fwxKdYQ75GOCkjNouL3bGoYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "cosmiconfig": "^9.0.0", + "dayjs": "^1.10.3", + "glob": "^7.1.6", + "lodash": "^4.17.21", + "memoizee": "^0.4.15", + "mock.js": "^0.2.0", + "mockjs": "^1.1.0", + "node-fetch": "^2.6.1", + "number-to-words": "^1.2.4", + "nunjucks": "^3.2.2", + "openapi3-ts": "^2.0.1", + "prettier": "^2.2.1", + "reserved-words": "^0.1.2", + "rimraf": "^3.0.2", + "swagger2openapi": "^7.0.4", + "tiny-pinyin": "^1.3.2" + }, + "bin": { + "openapi2ts": "dist/cli.js" + } + }, + "node_modules/@umijs/openapi/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@umijs/openapi/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.3.tgz", + "integrity": "sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.53" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.27.tgz", + "integrity": "sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.27" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.27.tgz", + "integrity": "sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.27.tgz", + "integrity": "sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.27", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", + "integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.26", + "entities": "^7.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz", + "integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz", + "integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.26", + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz", + "integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-core": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.0.5.tgz", + "integrity": "sha512-dpCw8nl0GDBuiL9SaY0mtDxoGIEmU38w+TQiYEPOLhW03VDC0lfNMYXS/qhl4I0YlysGp04NLY4UNn6xgD0VIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.0.5", + "@vue/devtools-shared": "^8.0.5", + "mitt": "^3.0.1", + "nanoid": "^5.1.5", + "pathe": "^2.0.3", + "vite-hot-client": "^2.1.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.5.tgz", + "integrity": "sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.5", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.5.tgz", + "integrity": "sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", + "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.1.tgz", + "integrity": "sha512-g6oSenpnGMtpxHGAwKuu7HJJkNZpemK/zg3vZzZbJ6cnnXq1ssxuNrXSsAHYM3NvH8p4IkTw+NLmuxyeYz4r8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.27", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz", + "integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz", + "integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/shared": "3.5.26" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz", + "integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.26", + "@vue/runtime-core": "3.5.26", + "@vue/shared": "3.5.26", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz", + "integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "vue": "3.5.26" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz", + "integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.8.1.tgz", + "integrity": "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/alien-signals": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.2.tgz", + "integrity": "sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/ant-design-vue": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.2.6.tgz", + "integrity": "sha512-t7eX13Yj3i9+i5g9lqFyYneoIb3OzTvQjq9Tts1i+eiOd3Eva/6GagxBSXM1fOCjqemIu0FYVE1ByZ/38epR3Q==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-vue": "^7.0.0", + "@babel/runtime": "^7.10.5", + "@ctrl/tinycolor": "^3.5.0", + "@emotion/hash": "^0.9.0", + "@emotion/unitless": "^0.8.0", + "@simonwep/pickr": "~1.8.0", + "array-tree-filter": "^2.1.0", + "async-validator": "^4.0.0", + "csstype": "^3.1.1", + "dayjs": "^1.10.5", + "dom-align": "^1.12.1", + "dom-scroll-into-view": "^2.0.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.15", + "resize-observer-polyfill": "^1.5.1", + "scroll-into-view-if-needed": "^2.2.25", + "shallow-equal": "^1.0.0", + "stylis": "^4.1.3", + "throttle-debounce": "^5.0.0", + "vue-types": "^3.0.0", + "warning": "^4.0.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design-vue" + }, + "peerDependencies": { + "vue": ">=3.2.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001762", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", + "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-align": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", + "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==", + "license": "MIT" + }, + "node_modules/dom-scroll-into-view": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz", + "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/entities": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz", + "integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/http2-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", + "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", + "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/memoizee/node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mock.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/mock.js/-/mock.js-0.2.0.tgz", + "integrity": "sha512-DKI8Rh/h7Mma+fg+6aD0uUvwn0QXAjKG6q3s+lTaCboCQ/kvQMBN9IXRBzgEaz4aPiYoRnKU9jVsfZp0mHpWrQ==", + "dev": true + }, + "node_modules/mockjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mockjs/-/mockjs-1.1.0.tgz", + "integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==", + "dev": true, + "dependencies": { + "commander": "*" + }, + "bin": { + "random": "bin/random" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanopop": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/nanopop/-/nanopop-2.4.2.tgz", + "integrity": "sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==", + "license": "MIT" + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node_modules/node-fetch-h2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz", + "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "http2-client": "^1.2.5" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-readfiles": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", + "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-promise": "^3.2.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-8.0.4.tgz", + "integrity": "sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^20.5.0 || >=22.0.0", + "npm": ">= 10" + } + }, + "node_modules/number-to-words": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/number-to-words/-/number-to-words-1.2.4.tgz", + "integrity": "sha512-/fYevVkXRcyBiZDg6yzZbm0RuaD6i0qRfn8yr+6D0KgBMOndFPxuW10qCHpzs50nN8qKuv78k8MuotZhcVX6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-kit-common": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", + "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/oas-linter": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz", + "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@exodus/schemasafe": "^1.0.0-rc.2", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-linter/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-resolver": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz", + "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "node-fetch-h2": "^2.3.0", + "oas-kit-common": "^1.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "resolve": "resolve.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-resolver/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oas-schema-walker": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz", + "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz", + "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "oas-kit-common": "^1.0.8", + "oas-linter": "^3.2.2", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "reftools": "^1.1.9", + "should": "^13.2.1", + "yaml": "^1.10.0" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/oas-validator/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi3-ts": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-2.0.2.tgz", + "integrity": "sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "yaml": "^1.10.2" + } + }, + "node_modules/openapi3-ts/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/reftools": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz", + "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==", + "dev": true, + "license": "BSD-3-Clause", + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz", + "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger2openapi": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz", + "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "call-me-maybe": "^1.0.1", + "node-fetch": "^2.6.1", + "node-fetch-h2": "^2.3.0", + "node-readfiles": "^0.2.0", + "oas-kit-common": "^1.0.8", + "oas-resolver": "^2.5.6", + "oas-schema-walker": "^1.1.5", + "oas-validator": "^5.0.8", + "reftools": "^1.1.9", + "yaml": "^1.10.0", + "yargs": "^17.0.1" + }, + "bin": { + "boast": "boast.js", + "oas-validate": "oas-validate.js", + "swagger2openapi": "swagger2openapi.js" + }, + "funding": { + "url": "https://github.com/Mermade/oas-kit?sponsor=1" + } + }, + "node_modules/swagger2openapi/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/swagger2openapi/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/tiny-pinyin": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/tiny-pinyin/-/tiny-pinyin-1.3.2.tgz", + "integrity": "sha512-uHNGu4evFt/8eNLldazeAM1M8JrMc1jshhJJfVRARTN3yT8HEEibofeQ7QETWQ5ISBjd6fKtTVBCC/+mGS6FpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/umi-request": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/umi-request/-/umi-request-1.4.0.tgz", + "integrity": "sha512-OknwtQZddZHi0Ggi+Vr/olJ7HNMx4AzlywyK0W3NZBT7B0stjeZ9lcztA85dBgdAj3KVk8uPJPZSnGaDjELhrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "isomorphic-fetch": "^2.2.1", + "qs": "^6.9.1" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unplugin-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz", + "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", + "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-dev-rpc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", + "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", + "dev": true, + "license": "MIT", + "dependencies": { + "birpc": "^2.4.0", + "vite-hot-client": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" + } + }, + "node_modules/vite-hot-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", + "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.1.0", + "debug": "^4.4.1", + "error-stack-parser-es": "^1.0.5", + "ohash": "^2.0.11", + "open": "^10.2.0", + "perfect-debounce": "^2.0.0", + "sirv": "^3.0.1", + "unplugin-utils": "^0.3.0", + "vite-dev-rpc": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-inspect/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.0.5.tgz", + "integrity": "sha512-p619BlKFOqQXJ6uDWS1vUPQzuJOD6xJTfftj57JXBGoBD/yeQCowR7pnWcr/FEX4/HVkFbreI6w2uuGBmQOh6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^8.0.5", + "@vue/devtools-kit": "^8.0.5", + "@vue/devtools-shared": "^8.0.5", + "sirv": "^3.0.2", + "vite-plugin-inspect": "^11.3.3", + "vite-plugin-vue-inspector": "^5.3.2" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.5.tgz", + "integrity": "sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.5", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.5.tgz", + "integrity": "sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", + "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.26", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz", + "integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.26", + "@vue/compiler-sfc": "3.5.26", + "@vue/runtime-dom": "3.5.26", + "@vue/server-renderer": "3.5.26", + "@vue/shared": "3.5.26" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-tsc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.1.tgz", + "integrity": "sha512-I23Rk8dkQfmcSbxDO0dmg9ioMLjKA1pjlU3Lz6Jfk2pMGu3Uryu9810XkcZH24IzPbhzPCnkKo2rEMRX0skSrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.27", + "@vue/language-core": "3.2.1" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vue-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vue-types/-/vue-types-3.0.2.tgz", + "integrity": "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==", + "license": "MIT", + "dependencies": { + "is-plain-object": "3.0.1" + }, + "engines": { + "node": ">=10.15.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/BOSSFrontEnd/BOSS/package.json b/BOSSFrontEnd/BOSS/package.json new file mode 100644 index 0000000..77fe299 --- /dev/null +++ b/BOSSFrontEnd/BOSS/package.json @@ -0,0 +1,43 @@ +{ + "name": "boss", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build", + "format": "prettier --write --experimental-cli src/", + "openapi": "tsx openapi.config.ts" + }, + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "ant-design-vue": "^4.2.6", + "axios": "^1.13.2", + "pinia": "^3.0.4", + "vue": "^3.5.26", + "vue-router": "^4.6.4" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.3", + "@types/node": "^24.10.4", + "@umijs/openapi": "^1.14.1", + "@vitejs/plugin-vue": "^6.0.3", + "@vue/tsconfig": "^0.8.1", + "npm-run-all2": "^8.0.4", + "prettier": "3.7.4", + "ts-node": "^10.9.2", + "tslib": "^2.8.1", + "tsx": "^4.21.0", + "typescript": "~5.9.3", + "umi-request": "^1.4.0", + "vite": "^7.3.0", + "vite-plugin-vue-devtools": "^8.0.5", + "vue-tsc": "^3.2.1" + } +} diff --git a/BOSSFrontEnd/BOSS/public/favicon.svg b/BOSSFrontEnd/BOSS/public/favicon.svg new file mode 100644 index 0000000..ee8bb8b --- /dev/null +++ b/BOSSFrontEnd/BOSS/public/favicon.svg @@ -0,0 +1,1009 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/App.vue b/BOSSFrontEnd/BOSS/src/App.vue new file mode 100644 index 0000000..1363698 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/App.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/api/api/applicationController.ts b/BOSSFrontEnd/BOSS/src/api/api/applicationController.ts new file mode 100644 index 0000000..bf1288a --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/applicationController.ts @@ -0,0 +1,90 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /application/add */ +export async function addApplication( + body: API.ApplicationAddRequest, + options?: { [key: string]: any } +) { + return request('/application/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /application/delete */ +export async function deleteApplication(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/application/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /application/get */ +export async function getApplicationById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getApplicationByIdParams, + options?: { [key: string]: any } +) { + return request('/application/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /application/get/vo */ +export async function getApplicationVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getApplicationVOByIdParams, + options?: { [key: string]: any } +) { + return request('/application/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /application/list/page/vo */ +export async function listApplicationVoByPage( + body: API.ApplicationQueryRequest, + options?: { [key: string]: any } +) { + return request('/application/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /application/update */ +export async function updateApplication( + body: API.ApplicationUpdateRequest, + options?: { [key: string]: any } +) { + return request('/application/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/bossApplicationDecisionController.ts b/BOSSFrontEnd/BOSS/src/api/api/bossApplicationDecisionController.ts new file mode 100644 index 0000000..1c72ff8 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/bossApplicationDecisionController.ts @@ -0,0 +1,90 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /decision/add */ +export async function addDecision( + body: API.BossApplicationDecisionAddRequest, + options?: { [key: string]: any } +) { + return request('/decision/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /decision/delete */ +export async function deleteDecision(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/decision/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /decision/get */ +export async function getDecisionById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getDecisionByIdParams, + options?: { [key: string]: any } +) { + return request('/decision/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /decision/get/vo */ +export async function getDecisionVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getDecisionVOByIdParams, + options?: { [key: string]: any } +) { + return request('/decision/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /decision/list/page/vo */ +export async function listDecisionVoByPage( + body: API.BossApplicationDecisionQueryRequest, + options?: { [key: string]: any } +) { + return request('/decision/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /decision/update */ +export async function updateDecision( + body: API.BossApplicationDecisionUpdateRequest, + options?: { [key: string]: any } +) { + return request('/decision/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/bossController.ts b/BOSSFrontEnd/BOSS/src/api/api/bossController.ts new file mode 100644 index 0000000..dd60e09 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/bossController.ts @@ -0,0 +1,11 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 GET /boss/list */ +export async function listBoss1(options?: { [key: string]: any }) { + return request('/boss/list', { + method: 'GET', + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/companyController.ts b/BOSSFrontEnd/BOSS/src/api/api/companyController.ts new file mode 100644 index 0000000..ef2da9b --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/companyController.ts @@ -0,0 +1,87 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /company/add */ +export async function addCompany(body: API.CompanyAddRequest, options?: { [key: string]: any }) { + return request('/company/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /company/delete */ +export async function deleteCompany(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/company/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /company/get */ +export async function getCompanyById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getCompanyByIdParams, + options?: { [key: string]: any } +) { + return request('/company/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /company/get/vo */ +export async function getCompanyVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getCompanyVOByIdParams, + options?: { [key: string]: any } +) { + return request('/company/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /company/list/page/vo */ +export async function listCompanyVoByPage( + body: API.CompanyQueryRequest, + options?: { [key: string]: any } +) { + return request('/company/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /company/update */ +export async function updateCompany( + body: API.CompanyUpdateRequest, + options?: { [key: string]: any } +) { + return request('/company/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/index.ts b/BOSSFrontEnd/BOSS/src/api/api/index.ts new file mode 100644 index 0000000..5fc64ea --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/index.ts @@ -0,0 +1,22 @@ +// @ts-ignore +/* eslint-disable */ +// API 更新时间: +// API 唯一标识: +import * as userController from './userController' +import * as resumeController from './resumeController' +import * as jobPostingController from './jobPostingController' +import * as interviewController from './interviewController' +import * as bossApplicationDecisionController from './bossApplicationDecisionController' +import * as companyController from './companyController' +import * as applicationController from './applicationController' +import * as bossController from './bossController' +export default { + userController, + resumeController, + jobPostingController, + interviewController, + bossApplicationDecisionController, + companyController, + applicationController, + bossController, +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/interviewController.ts b/BOSSFrontEnd/BOSS/src/api/api/interviewController.ts new file mode 100644 index 0000000..e81c2c7 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/interviewController.ts @@ -0,0 +1,90 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /interview/add */ +export async function addInterview( + body: API.InterviewAddRequest, + options?: { [key: string]: any } +) { + return request('/interview/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /interview/delete */ +export async function deleteInterview(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/interview/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /interview/get */ +export async function getInterviewById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getInterviewByIdParams, + options?: { [key: string]: any } +) { + return request('/interview/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /interview/get/vo */ +export async function getInterviewVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getInterviewVOByIdParams, + options?: { [key: string]: any } +) { + return request('/interview/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /interview/list/page/vo */ +export async function listInterviewVoByPage( + body: API.InterviewQueryRequest, + options?: { [key: string]: any } +) { + return request('/interview/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /interview/update */ +export async function updateInterview( + body: API.InterviewUpdateRequest, + options?: { [key: string]: any } +) { + return request('/interview/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/jobPostingController.ts b/BOSSFrontEnd/BOSS/src/api/api/jobPostingController.ts new file mode 100644 index 0000000..5f4d0a5 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/jobPostingController.ts @@ -0,0 +1,87 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /job/add */ +export async function addJob(body: API.JobPostingAddRequest, options?: { [key: string]: any }) { + return request('/job/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /job/delete */ +export async function deleteJob(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/job/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /job/get */ +export async function getJobById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getJobByIdParams, + options?: { [key: string]: any } +) { + return request('/job/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /job/get/vo */ +export async function getJobVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getJobVOByIdParams, + options?: { [key: string]: any } +) { + return request('/job/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /job/list/page/vo */ +export async function listJobVoByPage( + body: API.JobPostingQueryRequest, + options?: { [key: string]: any } +) { + return request('/job/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /job/update */ +export async function updateJob( + body: API.JobPostingUpdateRequest, + options?: { [key: string]: any } +) { + return request('/job/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/resumeAddressController.ts b/BOSSFrontEnd/BOSS/src/api/api/resumeAddressController.ts new file mode 100644 index 0000000..92cf120 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/resumeAddressController.ts @@ -0,0 +1,32 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +export async function uploadResumePdf(formData: FormData, options?: { [key: string]: any }) { + return request('/resume/address/upload', { + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data', + }, + data: formData, + ...(options || {}), + }) +} + +export async function getMyResumeAddress(options?: { [key: string]: any }) { + return request('/resume/address/get', { + method: 'GET', + ...(options || {}), + }) +} + +export async function deleteMyResumeAddress(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/resume/address/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/resumeController.ts b/BOSSFrontEnd/BOSS/src/api/api/resumeController.ts new file mode 100644 index 0000000..67fe81b --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/resumeController.ts @@ -0,0 +1,84 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 POST /resume/add */ +export async function addResume(body: API.ResumeAddRequest, options?: { [key: string]: any }) { + return request('/resume/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /resume/delete */ +export async function deleteResume(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/resume/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /resume/get/vo */ +export async function getResumeVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getResumeVOByIdParams, + options?: { [key: string]: any } +) { + return request('/resume/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /resume/list/page/vo */ +export async function listResumeVoByPage( + body: API.ResumeQueryRequest, + options?: { [key: string]: any } +) { + return request('/resume/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /resume/update */ +export async function updateResume( + body: API.ResumeUpdateRequest, + options?: { [key: string]: any } +) { + return request('/resume/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 上传简历附件文件 POST /resume/upload */ +export async function uploadResumeFile( + formData: FormData, + options?: { [key: string]: any } +) { + return request('/resume/upload', { + method: 'POST', + data: formData, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/typings.d.ts b/BOSSFrontEnd/BOSS/src/api/api/typings.d.ts new file mode 100644 index 0000000..91a1073 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/typings.d.ts @@ -0,0 +1,715 @@ +declare namespace API { + type Application = { + id?: number + userId?: number + resumeId?: number + jobId?: number + bossId?: number + status?: number + appliedAt?: string + updatedAt?: string + } + + type ApplicationAddRequest = { + resumeId?: number + jobId?: number + bossId?: number + status?: number + } + + type ApplicationQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + userId?: number + resumeId?: number + jobId?: number + bossId?: number + status?: number + } + + type ApplicationUpdateRequest = { + id?: number + resumeId?: number + status?: number + } + + type ApplicationVO = { + id?: number + userId?: number + resumeId?: number + jobId?: number + bossId?: number + status?: number + appliedAt?: string + updatedAt?: string + } + + type BaseResponseApplication = { + code?: number + data?: Application + message?: string + } + + type BaseResponseApplicationVO = { + code?: number + data?: ApplicationVO + message?: string + } + + type BaseResponseBoolean = { + code?: number + data?: boolean + message?: string + } + + type BaseResponseBossApplicationDecision = { + code?: number + data?: BossApplicationDecision + message?: string + } + + type BaseResponseBossApplicationDecisionVO = { + code?: number + data?: BossApplicationDecisionVO + message?: string + } + + type BaseResponseCompany = { + code?: number + data?: Company + message?: string + } + + type BaseResponseCompanyVO = { + code?: number + data?: CompanyVO + message?: string + } + + type BaseResponseInterview = { + code?: number + data?: Interview + message?: string + } + + type BaseResponseInterviewVO = { + code?: number + data?: InterviewVO + message?: string + } + + type BaseResponseJobPosting = { + code?: number + data?: JobPosting + message?: string + } + + type BaseResponseJobPostingVO = { + code?: number + data?: JobPostingVO + message?: string + } + + type BaseResponseListUserVO = { + code?: number + data?: UserVO[] + message?: string + } + + type BaseResponseLoginUserVO = { + code?: number + data?: LoginUserVO + message?: string + } + + type BaseResponseLong = { + code?: number + data?: number + message?: string + } + + type BaseResponseString = { + code?: number + data?: string + message?: string + } + + type BaseResponsePageApplicationVO = { + code?: number + data?: PageApplicationVO + message?: string + } + + type BaseResponsePageBossApplicationDecisionVO = { + code?: number + data?: PageBossApplicationDecisionVO + message?: string + } + + type BaseResponsePageCompanyVO = { + code?: number + data?: PageCompanyVO + message?: string + } + + type BaseResponsePageInterviewVO = { + code?: number + data?: PageInterviewVO + message?: string + } + + type BaseResponsePageJobPostingVO = { + code?: number + data?: PageJobPostingVO + message?: string + } + + type BaseResponsePageResumeVO = { + code?: number + data?: PageResumeVO + message?: string + } + + type BaseResponsePageUserVO = { + code?: number + data?: PageUserVO + message?: string + } + + type BaseResponseResumeVO = { + code?: number + data?: ResumeVO + message?: string + } + + type BaseResponseUser = { + code?: number + data?: User + message?: string + } + + type BaseResponseUserVO = { + code?: number + data?: UserVO + message?: string + } + + type BossApplicationDecision = { + id?: number + applicationId?: number + bossId?: number + decision?: number + stage?: number + note?: string + decidedAt?: string + updatedAt?: string + } + + type BossApplicationDecisionAddRequest = { + applicationId?: number + bossId?: number + decision?: number + stage?: number + note?: string + decidedAt?: string + } + + type BossApplicationDecisionQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + applicationId?: number + bossId?: number + decision?: number + stage?: number + } + + type BossApplicationDecisionUpdateRequest = { + id?: number + decision?: number + stage?: number + note?: string + decidedAt?: string + } + + type BossApplicationDecisionVO = { + id?: number + applicationId?: number + bossId?: number + decision?: number + stage?: number + note?: string + decidedAt?: string + updatedAt?: string + } + + type Company = { + id?: number + name?: string + industry?: string + sizeRange?: string + website?: string + address?: string + intro?: string + status?: number + createdAt?: string + updatedAt?: string + } + + type CompanyAddRequest = { + name?: string + industry?: string + sizeRange?: string + website?: string + address?: string + intro?: string + status?: number + } + + type CompanyQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + name?: string + industry?: string + status?: number + } + + type CompanyUpdateRequest = { + id?: number + name?: string + industry?: string + sizeRange?: string + website?: string + address?: string + intro?: string + status?: number + } + + type CompanyVO = { + id?: number + name?: string + industry?: string + sizeRange?: string + website?: string + address?: string + intro?: string + status?: number + createdAt?: string + updatedAt?: string + } + + type DeleteRequest = { + id?: number + } + + type getApplicationByIdParams = { + id: number + } + + type getApplicationVOByIdParams = { + id: number + } + + type getCompanyByIdParams = { + id: number + } + + type getCompanyVOByIdParams = { + id: number + } + + type getDecisionByIdParams = { + id: number + } + + type getDecisionVOByIdParams = { + id: number + } + + type getInterviewByIdParams = { + id: number + } + + type getInterviewVOByIdParams = { + id: number + } + + type getJobByIdParams = { + id: number + } + + type getJobVOByIdParams = { + id: number + } + + type getResumeVOByIdParams = { + id: number + } + + type getUserByIdParams = { + id: number + } + + type getUserVOByIdParams = { + id: number + } + + type Interview = { + id?: number + applicationId?: number + bossId?: number + userId?: number + interviewTime?: string + mode?: number + location?: string + status?: number + note?: string + createdAt?: string + updatedAt?: string + } + + type InterviewAddRequest = { + applicationId?: number + bossId?: number + userId?: number + interviewTime?: string + mode?: number + location?: string + status?: number + note?: string + } + + type InterviewQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + applicationId?: number + bossId?: number + userId?: number + status?: number + } + + type InterviewUpdateRequest = { + id?: number + interviewTime?: string + mode?: number + location?: string + status?: number + note?: string + } + + type InterviewVO = { + id?: number + applicationId?: number + bossId?: number + userId?: number + interviewTime?: string + mode?: number + location?: string + status?: number + note?: string + createdAt?: string + updatedAt?: string + } + + type JobPosting = { + id?: number + bossId?: number + companyId?: number + title?: string + location?: string + jobType?: string + salaryMin?: number + salaryMax?: number + description?: string + requirement?: string + status?: number + publishAt?: string + createdAt?: string + updatedAt?: string + } + + type JobPostingAddRequest = { + bossId?: number + companyId?: number + title?: string + location?: string + jobType?: string + salaryMin?: number + salaryMax?: number + description?: string + requirement?: string + status?: number + } + + type JobPostingQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + bossId?: number + companyId?: number + title?: string + location?: string + jobType?: string + status?: number + } + + type JobPostingUpdateRequest = { + id?: number + title?: string + location?: string + jobType?: string + salaryMin?: number + salaryMax?: number + description?: string + requirement?: string + status?: number + } + + type JobPostingVO = { + id?: number + bossId?: number + companyId?: number + title?: string + location?: string + jobType?: string + salaryMin?: number + salaryMax?: number + description?: string + requirement?: string + status?: number + publishAt?: string + createdAt?: string + updatedAt?: string + } + + type LoginUserVO = { + id?: number + userAccount?: string + userName?: string + userAvatar?: string + userProfile?: string + userRole?: string + companyId?: number + editTime?: string + createdAt?: string + updatedAt?: string + } + + type OrderItem = { + column?: string + asc?: boolean + } + + type PageApplicationVO = { + records?: ApplicationVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageApplicationVO + searchCount?: PageApplicationVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageBossApplicationDecisionVO = { + records?: BossApplicationDecisionVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageBossApplicationDecisionVO + searchCount?: PageBossApplicationDecisionVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageCompanyVO = { + records?: CompanyVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageCompanyVO + searchCount?: PageCompanyVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageInterviewVO = { + records?: InterviewVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageInterviewVO + searchCount?: PageInterviewVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageJobPostingVO = { + records?: JobPostingVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageJobPostingVO + searchCount?: PageJobPostingVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageResumeVO = { + records?: ResumeVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageResumeVO + searchCount?: PageResumeVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type PageUserVO = { + records?: UserVO[] + total?: number + size?: number + current?: number + orders?: OrderItem[] + optimizeCountSql?: PageUserVO + searchCount?: PageUserVO + optimizeJoinOfCountSql?: boolean + maxLimit?: number + countId?: string + pages?: number + } + + type ResumeAddRequest = { + resumeTitle?: string + isDefault?: number + summary?: string + content?: string + attachmentUrl?: string + } + + type ResumeQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + userId?: number + resumeTitle?: string + isDefault?: number + } + + type ResumeUpdateRequest = { + id?: number + resumeTitle?: string + isDefault?: number + summary?: string + content?: string + attachmentUrl?: string + } + + type ResumeVO = { + id?: number + userId?: number + resumeTitle?: string + isDefault?: number + summary?: string + content?: string + attachmentUrl?: string + updatedAt?: string + createdAt?: string + } + + type User = { + id?: number + userAccount?: string + userPassword?: string + phone?: string + email?: string + userName?: string + userRole?: string + companyId?: number + status?: number + createdAt?: string + updatedAt?: string + isDelete?: number + deletedAt?: string + userProfile?: string + } + + type UserLoginRequest = { + usrAccount?: string + userPassword?: string + } + + type UserQueryRequest = { + current?: number + pageSize?: number + sortField?: string + sortOrder?: string + id?: number + userAccount?: string + userName?: string + userProfile?: string + } + + type UserRegisterRequest = { + usrAccount?: string + userPassword?: string + checkPassword?: string + userRole?: string + } + + type UserUpdateRequest = { + id?: number + userName?: string + userAvatar?: string + userProfile?: string + userRole?: string + } + + type UserVO = { + id?: number + userAccount?: string + phone?: string + email?: string + userName?: string + status?: number + userRole?: string + companyId?: number + userProfile?: string + createdAt?: string + updatedAt?: string + } +} diff --git a/BOSSFrontEnd/BOSS/src/api/api/userController.ts b/BOSSFrontEnd/BOSS/src/api/api/userController.ts new file mode 100644 index 0000000..f2b40a3 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/api/api/userController.ts @@ -0,0 +1,123 @@ +// @ts-ignore +/* eslint-disable */ +import request from '@/libs/request' + +/** 此处后端没有提供注释 GET /user/boss/list */ +export async function listBoss(options?: { [key: string]: any }) { + return request('/user/boss/list', { + method: 'GET', + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/delete */ +export async function deleteUser(body: API.DeleteRequest, options?: { [key: string]: any }) { + return request('/user/delete', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /user/get */ +export async function getUserById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getUserByIdParams, + options?: { [key: string]: any } +) { + return request('/user/get', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /user/get/login */ +export async function getLoginUser(options?: { [key: string]: any }) { + return request('/user/get/login', { + method: 'GET', + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 GET /user/get/vo */ +export async function getUserVoById( + // 叠加生成的Param类型 (非body参数swagger默认没有生成对象) + params: API.getUserVOByIdParams, + options?: { [key: string]: any } +) { + return request('/user/get/vo', { + method: 'GET', + params: { + ...params, + }, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/list/page/vo */ +export async function listUserVoByPage( + body: API.UserQueryRequest, + options?: { [key: string]: any } +) { + return request('/user/list/page/vo', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/login */ +export async function userLogin(body: API.UserLoginRequest, options?: { [key: string]: any }) { + return request('/user/login', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/logout */ +export async function userLogout(options?: { [key: string]: any }) { + return request('/user/logout', { + method: 'POST', + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/register */ +export async function userRegister( + body: API.UserRegisterRequest, + options?: { [key: string]: any } +) { + return request('/user/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} + +/** 此处后端没有提供注释 POST /user/update */ +export async function updateUser(body: API.UserUpdateRequest, options?: { [key: string]: any }) { + return request('/user/update', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + data: body, + ...(options || {}), + }) +} diff --git a/BOSSFrontEnd/BOSS/src/components/NavBar.vue b/BOSSFrontEnd/BOSS/src/components/NavBar.vue new file mode 100644 index 0000000..02adb4a --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/components/NavBar.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/libs/request.ts b/BOSSFrontEnd/BOSS/src/libs/request.ts new file mode 100644 index 0000000..f91d158 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/libs/request.ts @@ -0,0 +1,57 @@ +import { extend } from 'umi-request'; + +// 根据环境变量设置基础URL +const baseURL = import.meta.env.VITE_API_BASE_URL || '/api'; + +// 创建请求实例 +const request = extend({ + prefix: baseURL, // 设置统一的请求前缀 + credentials: 'include', // 默认携带cookie + headers: { + 'Content-Type': 'application/json', + }, + errorHandler: (error: any) => { + // 统一错误处理 + if (error.errno === 'ENOTFOUND') { + console.error('网络请求失败,请检查网络连接'); + } else if (error.response) { + // 服务端返回错误状态码 + const { status, data } = error.response; + console.error(`请求失败: ${status}`, data); + } else { + // 其他错误 + console.error('请求异常', error); + } + throw error; + }, +}); + +// 请求拦截器 +request.interceptors.request.use((url, options) => { + // 如果data是FormData,删除Content-Type,让浏览器自动设置multipart/form-data和boundary + if (options.data instanceof FormData) { + if (options.headers) { + delete options.headers['Content-Type']; + } + } + return { + url, + options, + }; +}); + +// 响应拦截器 +request.interceptors.response.use(async (response) => { + try { + const data = await response.clone().json(); + if (data && data.code !== 0) { + // 可以在这里处理业务错误 + console.error(data.message || '请求失败'); + } + } catch (e) { + // 响应不是JSON,忽略 + } + return response; +}); + +export default request; diff --git a/BOSSFrontEnd/BOSS/src/main.ts b/BOSSFrontEnd/BOSS/src/main.ts new file mode 100644 index 0000000..7996efb --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/main.ts @@ -0,0 +1,15 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import Antd from 'ant-design-vue'; +import 'ant-design-vue/dist/reset.css'; + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) +app.use(Antd) + +app.mount('#app') diff --git a/BOSSFrontEnd/BOSS/src/router/index.ts b/BOSSFrontEnd/BOSS/src/router/index.ts new file mode 100644 index 0000000..07b15c6 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/router/index.ts @@ -0,0 +1,111 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' +import LoginView from '../views/LoginView.vue' +import RegisterView from '../views/RegisterView.vue' +import { useUserStore } from '@/stores/user' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + redirect: '/home' + }, + { + path: '/home', + name: 'home', + component: HomeView, + }, + { + path: '/user/login', + name: 'login', + component: LoginView, + }, + { + path: '/user/register', + name: 'register', + component: RegisterView, + }, + { + path: '/users', + name: 'users', + component: () => import('../views/Users.vue'), + }, + { + path: '/bosses', + name: 'bosses', + component: () => import('../views/Bosses.vue'), + }, + { + path: '/user/resumes', + name: 'my-resumes', + component: () => import('../views/MyResumes.vue'), + }, + { + path: '/user/resume/edit/:id?', + name: 'resume-edit', + component: () => import('../views/ResumeEdit.vue'), + }, + { + path: '/jobs', + name: 'jobs', + component: () => import('../views/Jobs.vue'), + }, + { + path: '/user/applications', + name: 'my-applications', + component: () => import('../views/MyApplications.vue'), + }, + { + path: '/boss/applications', + name: 'boss-applications', + component: () => import('../views/BossApplications.vue'), + }, + { + path: '/boss/company', + name: 'boss-company', + component: () => import('../views/BossCompany.vue'), + }, + { + path: '/boss/job/edit/:id?', + name: 'job-edit', + component: () => import('../views/JobEdit.vue'), + }, + { + path: '/admin/applications', + name: 'admin-applications', + component: () => import('../views/AdminApplications.vue'), + }, + { + path: '/user/profile', + name: 'user-profile', + component: () => import('../views/Profile.vue'), + }, + ], +}) + +// 全局路由守卫 +router.beforeEach(async (to, from, next) => { + const userStore = useUserStore(); + const publicPaths = ['/user/login', '/user/register']; + + // 如果访问的是公开路径,直接放行 + if (publicPaths.includes(to.path)) { + next(); + return; + } + + // 如果没有用户信息(id不存在),尝试获取用户信息 + if (!userStore.loginUser.id) { + await userStore.fetchLoginUser(); + } + + // 再次检查,如果还是没有登录,重定向到登录页 + if (!userStore.loginUser.id) { + next('/user/login'); + } else { + next(); + } +}); + +export default router \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/services/api.ts b/BOSSFrontEnd/BOSS/src/services/api.ts new file mode 100644 index 0000000..e8936a8 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/services/api.ts @@ -0,0 +1,43 @@ +import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; + +// 创建 axios 实例 +const apiClient: AxiosInstance = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080/api', // 使用环境变量或默认值 + timeout: 10000, // 请求超时时间 + headers: { + 'Content-Type': 'application/json', + }, +}); + +// 请求拦截器 +apiClient.interceptors.request.use( + (config: AxiosRequestConfig) => { + // 可以在这里添加认证 token + const token = localStorage.getItem('token'); + if (token && config.headers) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +// 响应拦截器 +apiClient.interceptors.response.use( + (response: AxiosResponse) => { + return response; + }, + (error) => { + // 处理错误响应 + if (error.response?.status === 401) { + // 处理未授权情况 + localStorage.removeItem('token'); + // 可以重定向到登录页面 + } + return Promise.reject(error); + } +); + +export default apiClient; \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/stores/counter.ts b/BOSSFrontEnd/BOSS/src/stores/counter.ts new file mode 100644 index 0000000..b6757ba --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/BOSSFrontEnd/BOSS/src/stores/user.ts b/BOSSFrontEnd/BOSS/src/stores/user.ts new file mode 100644 index 0000000..8c87c91 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/stores/user.ts @@ -0,0 +1,44 @@ +import { defineStore } from 'pinia'; +import { ref } from 'vue'; +import { getLoginUser, userLogout } from '@/api/api/userController'; +import { message } from 'ant-design-vue'; +import { useRouter } from 'vue-router'; + +export const useUserStore = defineStore('user', () => { + const loginUser = ref({ + userName: '未登录', + userRole: 'guest', + }); + + const router = useRouter(); + + const fetchLoginUser = async () => { + try { + const resUser = await getLoginUser(); + if (resUser.code === 0 && resUser.data) { + loginUser.value = resUser.data; + return; + } + loginUser.value = { userName: '未登录', userRole: 'guest' }; + } catch (error) { + loginUser.value = { userName: '未登录', userRole: 'guest' }; + } + }; + + const logout = async () => { + try { + await userLogout(); + loginUser.value = { userName: '未登录', userRole: 'guest' }; + message.success('退出登录成功'); + router.push('/user/login'); + } catch (error) { + message.error('退出登录失败'); + } + }; + + return { + loginUser, + fetchLoginUser, + logout, + }; +}); \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/views/AdminApplications.vue b/BOSSFrontEnd/BOSS/src/views/AdminApplications.vue new file mode 100644 index 0000000..50217de --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/AdminApplications.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/BossApplications.vue b/BOSSFrontEnd/BOSS/src/views/BossApplications.vue new file mode 100644 index 0000000..cc23586 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/BossApplications.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/BossCompany.vue b/BOSSFrontEnd/BOSS/src/views/BossCompany.vue new file mode 100644 index 0000000..b891f36 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/BossCompany.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/Bosses.vue b/BOSSFrontEnd/BOSS/src/views/Bosses.vue new file mode 100644 index 0000000..eae806a --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/Bosses.vue @@ -0,0 +1,220 @@ + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/views/HomeView.vue b/BOSSFrontEnd/BOSS/src/views/HomeView.vue new file mode 100644 index 0000000..645f237 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/HomeView.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/JobEdit.vue b/BOSSFrontEnd/BOSS/src/views/JobEdit.vue new file mode 100644 index 0000000..fa78499 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/JobEdit.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/Jobs.vue b/BOSSFrontEnd/BOSS/src/views/Jobs.vue new file mode 100644 index 0000000..a297a05 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/Jobs.vue @@ -0,0 +1,308 @@ + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/src/views/LoginView.vue b/BOSSFrontEnd/BOSS/src/views/LoginView.vue new file mode 100644 index 0000000..7c3a661 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/LoginView.vue @@ -0,0 +1,194 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/MyApplications.vue b/BOSSFrontEnd/BOSS/src/views/MyApplications.vue new file mode 100644 index 0000000..90349f8 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/MyApplications.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/MyResumes.vue b/BOSSFrontEnd/BOSS/src/views/MyResumes.vue new file mode 100644 index 0000000..8d8c056 --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/MyResumes.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/Profile.vue b/BOSSFrontEnd/BOSS/src/views/Profile.vue new file mode 100644 index 0000000..207deaf --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/Profile.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/RegisterView.vue b/BOSSFrontEnd/BOSS/src/views/RegisterView.vue new file mode 100644 index 0000000..84a20af --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/RegisterView.vue @@ -0,0 +1,308 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/ResumeEdit.vue b/BOSSFrontEnd/BOSS/src/views/ResumeEdit.vue new file mode 100644 index 0000000..57ebf1e --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/ResumeEdit.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/BOSSFrontEnd/BOSS/src/views/Users.vue b/BOSSFrontEnd/BOSS/src/views/Users.vue new file mode 100644 index 0000000..2517f9f --- /dev/null +++ b/BOSSFrontEnd/BOSS/src/views/Users.vue @@ -0,0 +1,290 @@ + + + + + \ No newline at end of file diff --git a/BOSSFrontEnd/BOSS/tsconfig.app.json b/BOSSFrontEnd/BOSS/tsconfig.app.json new file mode 100644 index 0000000..913b8f2 --- /dev/null +++ b/BOSSFrontEnd/BOSS/tsconfig.app.json @@ -0,0 +1,12 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/BOSSFrontEnd/BOSS/tsconfig.json b/BOSSFrontEnd/BOSS/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/BOSSFrontEnd/BOSS/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/BOSSFrontEnd/BOSS/tsconfig.node.json b/BOSSFrontEnd/BOSS/tsconfig.node.json new file mode 100644 index 0000000..822562d --- /dev/null +++ b/BOSSFrontEnd/BOSS/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node24/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/BOSSFrontEnd/BOSS/vite.config.ts b/BOSSFrontEnd/BOSS/vite.config.ts new file mode 100644 index 0000000..1c42a91 --- /dev/null +++ b/BOSSFrontEnd/BOSS/vite.config.ts @@ -0,0 +1,27 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, + server: { + proxy: { + '/api': { + target: 'http://localhost:8081', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, + }, +})