├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── help ├── database.md ├── spring.md └── vue.md ├── images ├── 20181030192809.png ├── 20181030200933.png ├── 20181030201140.png ├── 20181030201718.png ├── 20181030201808.png ├── 20181030202432.png ├── 20191224164214.png ├── 20200116220840.jpg ├── 20220514212052.png ├── 20220514212233.png ├── idea.png └── sql1030192411.png ├── spring-boot.sh ├── spring-restful-api ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── Dockerfile ├── REST API │ ├── http-client.env.json │ ├── 文件上传API.http │ └── 认证授权API.http ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xaaef │ │ │ └── robin │ │ │ ├── SpringRestfulApplication.java │ │ │ ├── aspect │ │ │ ├── BindingResultAspect.java │ │ │ └── log │ │ │ │ ├── LogStorage.java │ │ │ │ ├── LogType.java │ │ │ │ ├── MysqlLogStorage.java │ │ │ │ ├── OperateLog.java │ │ │ │ └── OperateLogAspect.java │ │ │ ├── base │ │ │ ├── entity │ │ │ │ └── BaseEntity.java │ │ │ └── service │ │ │ │ ├── BaseService.java │ │ │ │ └── impl │ │ │ │ └── BaseServiceImpl.java │ │ │ ├── config │ │ │ ├── GlobalExceptionHandler.java │ │ │ ├── MybatisPlusConfiguration.java │ │ │ ├── SpringMvcConfiguration.java │ │ │ ├── SwaggerConfiguration.java │ │ │ ├── WebSecurityConfiguration.java │ │ │ ├── props │ │ │ │ └── CustomizeSwaggerProperties.java │ │ │ └── xss │ │ │ │ ├── XssFilterConfiguration.java │ │ │ │ ├── XssHttpServletRequestWrapper.java │ │ │ │ └── XssStringJsonDeserializer.java │ │ │ ├── constant │ │ │ ├── ConfigKey.java │ │ │ └── LoginConstant.java │ │ │ ├── controller │ │ │ ├── AuthController.java │ │ │ ├── ChinaAreaController.java │ │ │ ├── IndexController.java │ │ │ ├── LoginLogController.java │ │ │ ├── OperLogController.java │ │ │ ├── SysConfigController.java │ │ │ ├── SysDeptController.java │ │ │ ├── SysDictDataController.java │ │ │ ├── SysDictTypeController.java │ │ │ ├── SysPermissionController.java │ │ │ ├── SysRoleController.java │ │ │ ├── SysUserController.java │ │ │ └── UploadController.java │ │ │ ├── domain │ │ │ ├── Pagination.java │ │ │ └── TreeNode.java │ │ │ ├── entity │ │ │ ├── ChinaArea.java │ │ │ ├── LoginLog.java │ │ │ ├── OperLog.java │ │ │ ├── SysConfig.java │ │ │ ├── SysDept.java │ │ │ ├── SysDictData.java │ │ │ ├── SysDictType.java │ │ │ ├── SysNotice.java │ │ │ ├── SysPermission.java │ │ │ ├── SysRole.java │ │ │ ├── SysRoleProxy.java │ │ │ ├── SysUser.java │ │ │ └── SysUserSocial.java │ │ │ ├── enums │ │ │ ├── AdminFlagEnum.java │ │ │ ├── DefaultEnum.java │ │ │ ├── GenderEnum.java │ │ │ ├── GrantType.java │ │ │ ├── OAuth2Error.java │ │ │ ├── PermissionTypeEnum.java │ │ │ └── StatusEnum.java │ │ │ ├── exception │ │ │ └── JwtAuthException.java │ │ │ ├── jwt │ │ │ ├── JwtAccessDeniedHandler.java │ │ │ ├── JwtAuthenticationTokenFilter.java │ │ │ ├── JwtLoginUser.java │ │ │ ├── JwtSecurityUtils.java │ │ │ ├── JwtTokenProperties.java │ │ │ ├── JwtTokenUtils.java │ │ │ ├── JwtTokenValue.java │ │ │ └── StringGrantedAuthority.java │ │ │ ├── mapper │ │ │ ├── ChinaAreaMapper.java │ │ │ ├── LoginLogMapper.java │ │ │ ├── OperLogMapper.java │ │ │ ├── SysConfigMapper.java │ │ │ ├── SysDeptMapper.java │ │ │ ├── SysDictDataMapper.java │ │ │ ├── SysDictTypeMapper.java │ │ │ ├── SysNoticeMapper.java │ │ │ ├── SysPermissionMapper.java │ │ │ ├── SysRoleMapper.java │ │ │ ├── SysUserMapper.java │ │ │ └── SysUserSocialMapper.java │ │ │ ├── param │ │ │ ├── DictQueryParams.java │ │ │ ├── QueryParams.java │ │ │ └── UserQueryParams.java │ │ │ ├── service │ │ │ ├── ChinaAreaService.java │ │ │ ├── JwtTokenService.java │ │ │ ├── LoginLogService.java │ │ │ ├── OperLogService.java │ │ │ ├── SysConfigService.java │ │ │ ├── SysDeptService.java │ │ │ ├── SysDictDataService.java │ │ │ ├── SysDictTypeService.java │ │ │ ├── SysNoticeService.java │ │ │ ├── SysPermissionService.java │ │ │ ├── SysRoleService.java │ │ │ ├── SysUserService.java │ │ │ ├── SysUserSocialService.java │ │ │ ├── UserLoginService.java │ │ │ ├── VerifyCodeService.java │ │ │ └── impl │ │ │ │ ├── ChinaAreaServiceImpl.java │ │ │ │ ├── JwtTokenServiceImpl.java │ │ │ │ ├── LoginLogServiceImpl.java │ │ │ │ ├── OperLogServiceImpl.java │ │ │ │ ├── SysConfigServiceImpl.java │ │ │ │ ├── SysDeptServiceImpl.java │ │ │ │ ├── SysDictDataServiceImpl.java │ │ │ │ ├── SysDictTypeServiceImpl.java │ │ │ │ ├── SysNoticeServiceImpl.java │ │ │ │ ├── SysPermissionServiceImpl.java │ │ │ │ ├── SysRoleServiceImpl.java │ │ │ │ ├── SysUserServiceImpl.java │ │ │ │ ├── SysUserSocialServiceImpl.java │ │ │ │ ├── UserLoginServiceImpl.java │ │ │ │ └── VerifyCodeServiceImpl.java │ │ │ ├── util │ │ │ ├── ConvertUtils.java │ │ │ ├── FSTUtils.java │ │ │ ├── IdUtils.java │ │ │ ├── IpUtils.java │ │ │ ├── JsonResult.java │ │ │ ├── JsonUtils.java │ │ │ ├── MsgpackUtils.java │ │ │ ├── QiniuUtils.java │ │ │ ├── RedisCacheUtils.java │ │ │ ├── RegexUtils.java │ │ │ ├── RequestUtils.java │ │ │ ├── ServletUtils.java │ │ │ ├── SpringUtils.java │ │ │ ├── TimeUtils.java │ │ │ ├── TreeNodeUtils.java │ │ │ ├── VerifyCodeUtils.java │ │ │ └── useragent │ │ │ │ ├── Constants.java │ │ │ │ ├── UserAgent.java │ │ │ │ ├── UserAgentParser.java │ │ │ │ ├── browser │ │ │ │ ├── Browser.java │ │ │ │ ├── BrowserParser.java │ │ │ │ ├── BrowserPattern.java │ │ │ │ ├── Engine.java │ │ │ │ └── EngineEnum.java │ │ │ │ └── os │ │ │ │ ├── Os.java │ │ │ │ ├── OsParser.java │ │ │ │ ├── OsPattern.java │ │ │ │ └── PlatformEnum.java │ │ │ └── vo │ │ │ ├── BindingPermsVO.java │ │ │ ├── BindingRolesVO.java │ │ │ ├── ButtonVO.java │ │ │ ├── LoginUserVO.java │ │ │ ├── MenuVO.java │ │ │ ├── ResetPasswordVO.java │ │ │ ├── SysUserVO.java │ │ │ ├── UpdatePasswordVO.java │ │ │ ├── UpdatePermsVO.java │ │ │ └── UserIdAndNicknameVO.java │ └── resources │ │ ├── application-dev.yml │ │ ├── application-prod.yml │ │ ├── application.yml │ │ ├── images │ │ └── watermark.png │ │ ├── logback-spring.xml │ │ ├── mapper │ │ ├── ChinaAreaMapper.xml │ │ ├── LoginLogMapper.xml │ │ ├── OperLogMapper.xml │ │ ├── SysConfigMapper.xml │ │ ├── SysDeptMapper.xml │ │ ├── SysDictDataMapper.xml │ │ ├── SysDictTypeMapper.xml │ │ ├── SysNoticeMapper.xml │ │ ├── SysPermissionMapper.xml │ │ ├── SysRoleMapper.xml │ │ ├── SysUserMapper.xml │ │ └── SysUserSocialMapper.xml │ │ └── useragent │ │ ├── browser.yml │ │ └── os.yml │ └── test │ └── java │ └── com │ └── xaaef │ └── robin │ └── NoSpringTests.java ├── spring_admin_vue.sql └── vue-admin-template ├── .editorconfig ├── .env.development ├── .env.production ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── README.md ├── babel.config.js ├── jest.config.js ├── jsconfig.json ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── api │ ├── chinaArea.js │ ├── fileUpload.js │ ├── sysDept.js │ ├── sysLog.js │ ├── sysPermission.js │ ├── sysRole.js │ └── sysUser.js ├── assets │ ├── 401_images │ │ └── 401.gif │ ├── 404_images │ │ ├── 404.png │ │ └── 404_cloud.png │ └── images │ │ └── logo.png ├── components │ ├── BackToTop │ │ └── index.vue │ ├── Breadcrumb │ │ └── index.vue │ ├── Charts │ │ ├── Keyboard.vue │ │ ├── LineMarker.vue │ │ ├── MixChart.vue │ │ └── mixins │ │ │ └── resize.js │ ├── Copyright │ │ └── index.vue │ ├── DragSelect │ │ └── index.vue │ ├── Dropzone │ │ └── index.vue │ ├── ErrorLog │ │ └── index.vue │ ├── GithubCorner │ │ └── index.vue │ ├── Hamburger │ │ └── index.vue │ ├── HeaderSearch │ │ └── index.vue │ ├── PanThumb │ │ └── index.vue │ ├── Screenfull │ │ └── index.vue │ ├── ShowUserAvatar │ │ └── index.vue │ ├── SizeSelect │ │ └── index.vue │ ├── SvgIcon │ │ └── index.vue │ ├── TextHoverEffect │ │ └── Mallki.vue │ └── UserAvatar │ │ └── index.vue ├── directive │ └── index.js ├── filters │ └── index.js ├── icons │ ├── index.js │ ├── svg │ │ ├── dashboard.svg │ │ ├── exit-fullscreen.svg │ │ ├── eye-open.svg │ │ ├── eye.svg │ │ ├── fullscreen.svg │ │ ├── link.svg │ │ ├── message.svg │ │ ├── money.svg │ │ ├── password.svg │ │ ├── peoples.svg │ │ ├── pre.svg │ │ ├── pre_dept.svg │ │ ├── pre_perm.svg │ │ ├── pre_role.svg │ │ ├── pre_user.svg │ │ ├── search.svg │ │ ├── shopping.svg │ │ ├── size.svg │ │ ├── sys.svg │ │ ├── sys_china_area.svg │ │ ├── sys_dictionary.svg │ │ ├── sys_login_log.svg │ │ ├── sys_logs.svg │ │ ├── sys_oper_log.svg │ │ ├── sys_swagger2.svg │ │ ├── sys_wechat.svg │ │ └── user.svg │ └── svgo.yml ├── layout │ ├── components │ │ ├── AppMain.vue │ │ ├── Navbar.vue │ │ ├── Settings │ │ │ └── index.vue │ │ ├── Sidebar │ │ │ ├── FixiOSBug.js │ │ │ ├── Item.vue │ │ │ ├── Link.vue │ │ │ ├── Logo.vue │ │ │ ├── SidebarItem.vue │ │ │ └── index.vue │ │ ├── TagsView │ │ │ ├── ScrollPane.vue │ │ │ └── index.vue │ │ └── index.js │ ├── index.vue │ └── mixin │ │ └── ResizeHandler.js ├── main.js ├── permission.js ├── router │ └── index.js ├── settings.js ├── store │ ├── getters.js │ ├── index.js │ └── modules │ │ ├── app.js │ │ ├── errorLog.js │ │ ├── permission.js │ │ ├── settings.js │ │ ├── tagsView.js │ │ └── user.js ├── styles │ ├── element-ui.scss │ ├── index.scss │ ├── mixin.scss │ ├── sidebar.scss │ ├── transition.scss │ └── variables.scss ├── utils │ ├── auth.js │ ├── get-page-title.js │ ├── index.js │ ├── open-window.js │ ├── regular.js │ ├── request.js │ └── validate.js └── views │ ├── dashboard │ ├── components │ │ ├── BarChart.vue │ │ ├── BoxCard.vue │ │ ├── LineChart.vue │ │ ├── PanelGroup.vue │ │ ├── PieChart.vue │ │ ├── RaddarChart.vue │ │ ├── TodoList │ │ │ ├── Todo.vue │ │ │ ├── index.scss │ │ │ └── index.vue │ │ ├── TransactionTable.vue │ │ └── mixins │ │ │ └── resize.js │ └── index.vue │ ├── error │ ├── 401 │ │ └── index.vue │ └── 404 │ │ └── index.vue │ ├── login │ └── index.vue │ ├── pre │ ├── dept │ │ └── index.vue │ ├── perm │ │ └── index.vue │ ├── role │ │ └── index.vue │ └── user │ │ └── index.vue │ ├── redirect │ └── index.vue │ ├── sys │ ├── chinaArea │ │ └── index.vue │ ├── dictionary │ │ └── index.vue │ ├── loginLog │ │ └── index.vue │ ├── notice │ │ └── index.vue │ ├── operLog │ │ └── index.vue │ ├── swagger │ │ └── index.vue │ └── wechat │ │ └── index.vue │ └── userinfo │ └── index.vue ├── tests └── unit │ ├── .eslintrc.js │ ├── components │ ├── Breadcrumb.spec.js │ ├── Hamburger.spec.js │ └── SvgIcon.spec.js │ └── utils │ ├── formatTime.spec.js │ ├── param2Obj.spec.js │ ├── parseTime.spec.js │ └── validate.spec.js └── vue.config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sql linguist-language=java 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | README.md 2 | target/ 3 | 4 | **/node_modules/ 5 | !.mvn/wrapper/maven-wrapper.jar 6 | !**/src/main/** 7 | !**/src/test/** 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /help/database.md: -------------------------------------------------------------------------------- 1 | 2 | ## 先从数据库开始 3 | 4 | 大部分的权限管理系统都是5张表结构(同样我们这里也采用这种方式) 5 | 6 | ![](../images/sql1030192411.png) 7 | 8 | ### **t_sys_user -----> t_sys_user_role -----> t_sys_role -----> t_sys_role_permission ----> t_sys_permission** 9 | 10 | 这里我们主要看权限表(t_sys_permission ) 11 | 12 | ![](../images/20181030192809.png) 13 | 14 | 最重要的就是resources和type字段,这两个字段在后面和vue.js整合的时候会用到, 15 | 16 | ### type字段,只有两个类型,是按钮还是菜单 17 | -------------------------------------------------------------------------------- /images/20181030192809.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030192809.png -------------------------------------------------------------------------------- /images/20181030200933.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030200933.png -------------------------------------------------------------------------------- /images/20181030201140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030201140.png -------------------------------------------------------------------------------- /images/20181030201718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030201718.png -------------------------------------------------------------------------------- /images/20181030201808.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030201808.png -------------------------------------------------------------------------------- /images/20181030202432.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20181030202432.png -------------------------------------------------------------------------------- /images/20191224164214.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20191224164214.png -------------------------------------------------------------------------------- /images/20200116220840.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20200116220840.jpg -------------------------------------------------------------------------------- /images/20220514212052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20220514212052.png -------------------------------------------------------------------------------- /images/20220514212233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/20220514212233.png -------------------------------------------------------------------------------- /images/idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/idea.png -------------------------------------------------------------------------------- /images/sql1030192411.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/images/sql1030192411.png -------------------------------------------------------------------------------- /spring-restful-api/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring-restful-api/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/spring-restful-api/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring-restful-api/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /spring-restful-api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:11.0.13_8-jre 2 | 3 | MAINTAINER Wang Chen Chen<932560435@qq.com> 4 | 5 | ENV VERSION 1.1 6 | # 挂载容器目录 7 | # tmp: 临时文件目录,内嵌tomcat启动时,用到 8 | # logs: spring-boot 日志输出的目录 9 | # config: spring-boot 外部化配置文件目录 10 | VOLUME ["/tmp","/logs","/config"] 11 | 12 | # 对应pom.xml文件中的dockerfile-maven-plugin插件JAR_FILE的值 13 | ARG JAR_FILE 14 | 15 | # 复制打包 完成后的jar文件,名字修改成 app.jar 16 | COPY ${JAR_FILE} app.jar 17 | 18 | # 设置编码 19 | ENV LANG C.UTF-8 20 | 21 | # 设置环境变量 22 | ENV CONSUL_SERVER_PORT=8500 23 | 24 | # JVM参数 25 | ENV JVM_OPTS="-server -Xms2048M -Xmx2048M -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError" 26 | 27 | # spring 启动环境 28 | ENV SPRING_ENV="prod" 29 | 30 | # 服务暴露端口PORT 31 | EXPOSE 18888 32 | 33 | # 启动 Spring Boot App 命令 34 | ENTRYPOINT java ${JVM_OPTS} -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=${SPRING_ENV} 35 | -------------------------------------------------------------------------------- /spring-restful-api/REST API/http-client.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "baseUrl": "http://localhost:18888" 4 | }, 5 | "prod": { 6 | "baseUrl": "https://api.mhtled.com" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /spring-restful-api/REST API/文件上传API.http: -------------------------------------------------------------------------------- 1 | ### 图片上传 2 | POST {{baseUrl}}/upload/image 3 | Authorization: Bearer {{tokenValue}} 4 | Content-Type: multipart/form-data; boundary=WebAppBoundary 5 | 6 | --WebAppBoundary 7 | Content-Disposition: form-data; name="file"; filename="tR9669GlNMU-343X.bin" 8 | Content-Type: multipart/form-data 9 | 10 | < C:\\Users\\demo\\Desktop\\地图和头像\\tR9669GlNMU-343X.bin 11 | --WebAppBoundary-- 12 | 13 | 14 | 15 | 16 | ### 头像上传 17 | POST {{baseUrl}}/upload/avatar 18 | Authorization: Bearer {{tokenValue}} 19 | Content-Type: multipart/form-data; boundary=WebAppBoundary 20 | 21 | --WebAppBoundary 22 | Content-Disposition: form-data; name="file"; filename="avatar-4.jpg" 23 | Content-Type: multipart/form-data 24 | 25 | < C:\\Users\\demo\\Desktop\\地图和头像\\avatar-4.jpg 26 | --WebAppBoundary-- 27 | 28 | 29 | 30 | 31 | ### 删除图片 32 | DELETE {{baseUrl}}/upload/delete?url=https://images.xaaef.com/20210728105923.png 33 | Authorization: Bearer {{tokenValue}} 34 | -------------------------------------------------------------------------------- /spring-restful-api/REST API/认证授权API.http: -------------------------------------------------------------------------------- 1 | ## 安全认证 2 | 3 | ## 验证码一定要在浏览器获取 codeKey 要是随机数。在登录的时候会用到 codeKey 4 | GET {{baseUrl}}/auth/captcha/codes/5jXzuwcoUzbtnHNh 5 | 6 | ### 密码模式登录 7 | POST {{baseUrl}}/auth/login 8 | Content-Type: application/json 9 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 10 | 11 | { 12 | "username": "admin", 13 | "password": "admin", 14 | "codeKey": "5jXzuwcoUzbtnHNh", 15 | "codeText": "9jps" 16 | } 17 | 18 | > {% 19 | client.global.set("tokenValue", response.body.data.access_token); 20 | client.global.set("refreshToken", response.body.data.refresh_token); 21 | %} 22 | 23 | ### 退出登录 24 | POST {{baseUrl}}/auth/logout 25 | Content-Type: application/json 26 | Authorization: Bearer {{tokenValue}} 27 | 28 | ### 刷新token 29 | GET {{baseUrl}}/auth/refresh 30 | Content-Type: application/json 31 | Authorization: Bearer {{tokenValue}} 32 | 33 | ### 获取登录的用户信息 34 | GET {{baseUrl}}/user/info 35 | Content-Type: application/json 36 | Authorization: Bearer {{tokenValue}} 37 | 38 | 39 | 40 | ### 首页 测试 @PreAuthorize("hasAuthority('home:get')") 41 | GET {{baseUrl}}/home 42 | Content-Type: application/json 43 | Authorization: Bearer {{tokenValue}} 44 | 45 | 46 | ### 首页 测试 @PreAuthorize("hasAuthority('index:get')") 47 | GET {{baseUrl}}/index 48 | Content-Type: application/json 49 | Authorization: Bearer {{tokenValue}} 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/SpringRestfulApplication.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cache.annotation.EnableCaching; 7 | import org.springframework.scheduling.annotation.EnableAsync; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | 10 | 11 | @EnableAsync 12 | @EnableCaching 13 | @EnableScheduling 14 | @MapperScan("com.xaaef.robin.mapper") 15 | @SpringBootApplication 16 | public class SpringRestfulApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(SpringRestfulApplication.class, args); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/aspect/BindingResultAspect.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.aspect; 2 | 3 | import com.xaaef.robin.util.JsonResult; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | import org.springframework.core.annotation.Order; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.validation.BindingResult; 11 | 12 | /** 13 | *

14 | * Hibernate-Validator 错误结果处理切面 15 | *

16 | * 17 | * @author Wang Chen Chen <932560435@qq.com> 18 | * @version 2.0 19 | * @date 2019/4/18 11:45 20 | */ 21 | 22 | @Aspect 23 | @Component 24 | @Order(2) 25 | public class BindingResultAspect { 26 | 27 | @Pointcut("execution(public * com.xaaef.robin.*.controller..*.*(..))") 28 | public void BindingResult1() { 29 | } 30 | 31 | @Pointcut("execution(public * com.xaaef.robin.controller..*.*(..))") 32 | public void BindingResult2() { 33 | } 34 | 35 | @Around("BindingResult1() || BindingResult2()") 36 | public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { 37 | var args = joinPoint.getArgs(); 38 | for (Object arg : args) { 39 | if (arg instanceof BindingResult) { 40 | BindingResult result = (BindingResult) arg; 41 | if (result.hasErrors()) { 42 | var fieldError = result.getFieldError(); 43 | if (fieldError != null) { 44 | return JsonResult.fail(fieldError.getDefaultMessage()); 45 | } else { 46 | return JsonResult.fail("请求参数错误!"); 47 | } 48 | } 49 | } 50 | } 51 | return joinPoint.proceed(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/aspect/log/LogType.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.aspect.log; 2 | 3 | /** 4 | *

5 | * 操作类型 6 | *

7 | * 8 | * @author Wang Chen Chen 9 | * @version 1.0.1 10 | * @date 2021/8/10 15:01 11 | */ 12 | 13 | public enum LogType { 14 | 15 | // 新增 16 | INSERT, 17 | 18 | // 删除 19 | DELETE, 20 | 21 | // 修改 22 | UPDATE, 23 | 24 | // 查询 25 | SELECT, 26 | 27 | // 执行 28 | EXECUTE, 29 | 30 | } 31 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/aspect/log/MysqlLogStorage.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.aspect.log; 2 | 3 | import com.xaaef.robin.entity.LoginLog; 4 | import com.xaaef.robin.entity.OperLog; 5 | import com.xaaef.robin.service.LoginLogService; 6 | import com.xaaef.robin.service.OperLogService; 7 | import lombok.AllArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.scheduling.annotation.Async; 10 | import org.springframework.stereotype.Component; 11 | 12 | 13 | /** 14 | *

15 | * 操作日志 16 | *

17 | * 18 | * @author Wang Chen Chen 19 | * @version 1.0.1 20 | * @date 2021/8/17 16:18 21 | */ 22 | 23 | @Slf4j 24 | @Component 25 | @AllArgsConstructor 26 | public class MysqlLogStorage implements LogStorage { 27 | 28 | private final LoginLogService loginLogService; 29 | 30 | private final OperLogService operLogService; 31 | 32 | @Async 33 | @Override 34 | public void asyncLoginSave(LoginLog loginLog) { 35 | loginLogService.save(loginLog); 36 | } 37 | 38 | 39 | @Async 40 | @Override 41 | public void asyncOperateSave(OperLog operLog) { 42 | operLogService.save(operLog); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/aspect/log/OperateLog.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.aspect.log; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | *

7 | * 操作日志 8 | *

9 | * 10 | * @author Wang Chen Chen 11 | * @version 1.0.1 12 | * @date 2021/8/10 15:00 13 | */ 14 | 15 | @Documented 16 | @Target(ElementType.METHOD) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface OperateLog { 19 | 20 | String title() default ""; 21 | 22 | LogType type() default LogType.SELECT; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/base/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.base.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | *

12 | * 通用父实体类 13 | *

14 | * 15 | * @author Wang Chen Chen 16 | * @version 1.0 17 | * @date 2021/7/5 9:31 18 | */ 19 | 20 | @Getter 21 | @Setter 22 | public class BaseEntity implements java.io.Serializable { 23 | 24 | /** 25 | * 创建时间 26 | * 27 | * @date 2019/12/11 21:12 28 | */ 29 | @TableField(fill = FieldFill.INSERT) 30 | protected LocalDateTime createTime; 31 | 32 | /** 33 | * 创建人 id 34 | * 35 | * @date 2019/12/11 21:12 36 | */ 37 | @TableField(fill = FieldFill.INSERT) 38 | protected Long createUser; 39 | 40 | /** 41 | * 最后一次修改时间 42 | * 43 | * @date 2019/12/11 21:12 44 | */ 45 | @TableField(fill = FieldFill.INSERT_UPDATE) 46 | protected LocalDateTime lastUpdateTime; 47 | 48 | /** 49 | * 最后一次修改人 id 50 | * 51 | * @date 2019/12/11 21:12 52 | */ 53 | @TableField(fill = FieldFill.INSERT_UPDATE) 54 | protected Long lastUpdateUser; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/config/props/CustomizeSwaggerProperties.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.config.props; 2 | 3 | import lombok.*; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | * All rights Reserved, Designed By www.xaaef.com 8 | *

9 | *

10 | * 11 | * @author Wang Chen Chen<932560435@qq.com> 12 | * @version 1.0.0 13 | * @date 2020/7/2515:30 14 | */ 15 | 16 | 17 | @Getter 18 | @Setter 19 | @ToString 20 | @Builder 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @ConfigurationProperties(prefix = "customize.swagger") 24 | public class CustomizeSwaggerProperties { 25 | 26 | /** 27 | * 标题 28 | */ 29 | private String title; 30 | 31 | /** 32 | * 文档描述 33 | */ 34 | private String description; 35 | 36 | /** 37 | * 版本 38 | */ 39 | private String version = "3.0"; 40 | 41 | /** 42 | * 名称 43 | */ 44 | private String name; 45 | 46 | /** 47 | * URL地址 48 | */ 49 | private String url; 50 | 51 | /** 52 | * 邮箱 53 | */ 54 | private String email; 55 | 56 | /** 57 | * 服务地址 58 | */ 59 | private String serviceUrl; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/config/xss/XssFilterConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.config.xss; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.module.SimpleModule; 9 | import com.xaaef.robin.util.JsonUtils; 10 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.context.annotation.Primary; 14 | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; 15 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 16 | import org.springframework.web.util.HtmlUtils; 17 | 18 | import javax.servlet.*; 19 | import javax.servlet.http.HttpServletRequest; 20 | import java.io.IOException; 21 | 22 | 23 | /** 24 | *

25 | * 26 | *

27 | * 28 | * @author WangChenChen 29 | * @version 1.0 30 | * @date 2022/3/25 9:28 31 | */ 32 | 33 | 34 | @Configuration 35 | public class XssFilterConfiguration { 36 | 37 | @Bean 38 | public FilterRegistrationBean xssFilterRegister() { 39 | var registration = new FilterRegistrationBean<>(); 40 | registration.setFilter((servletRequest, servletResponse, filterChain) -> { 41 | var xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest); 42 | filterChain.doFilter(xssRequest, servletResponse); 43 | }); 44 | registration.addUrlPatterns("/*"); 45 | registration.setName("XssFilter"); 46 | registration.setOrder(1); 47 | return registration; 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/config/xss/XssStringJsonDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.config.xss; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.databind.DeserializationContext; 5 | import com.fasterxml.jackson.databind.JsonDeserializer; 6 | import org.springframework.web.util.HtmlUtils; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | *

12 | * 13 | *

14 | * 15 | * @author WangChenChen 16 | * @version 1.0 17 | * @date 2022/3/25 9:40 18 | */ 19 | 20 | 21 | public class XssStringJsonDeserializer extends JsonDeserializer { 22 | 23 | @Override 24 | public Class handledType() { 25 | return String.class; 26 | } 27 | 28 | @Override 29 | public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 30 | return HtmlUtils.htmlEscape(jsonParser.getValueAsString()); 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/constant/ConfigKey.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.constant; 2 | 3 | /** 4 | *

5 | * 全局配置文件 key 6 | *

7 | * 8 | * @author Wang Chen Chen 9 | * @version 1.0.1 10 | * @date 2021/7/16 15:15 11 | */ 12 | 13 | public class ConfigKey { 14 | 15 | /** 16 | * 用户默认密码 17 | */ 18 | public static final String USER_DEFAULT_PASSWORD = "user_default_password"; 19 | 20 | /** 21 | * 默认logo 22 | */ 23 | public static final String DEFAULT_LOGO = "default_logo"; 24 | 25 | /** 26 | * 获取法定节假日的接口 27 | */ 28 | public static final String LEGAL_HOLIDAY_URL = "legal_holiday_url"; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/constant/LoginConstant.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.constant; 2 | 3 | public class LoginConstant { 4 | 5 | /** 6 | * 验证码 redis key 7 | */ 8 | public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; 9 | 10 | /** 11 | * 登录用户 redis key 12 | */ 13 | public static final String LOGIN_TOKEN_KEY = "login_tokens:"; 14 | 15 | /** 16 | * 在线用户,令牌前缀 17 | */ 18 | public static final String ONLINE_USER_KEY = "online_user:"; 19 | 20 | /** 21 | * 强制下线,令牌前缀 22 | */ 23 | public static final String FORCED_OFFLINE_KEY = "forced_offline_user:"; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.controller; 2 | 3 | import com.xaaef.robin.util.JsonResult; 4 | import io.swagger.annotations.Api; 5 | import io.swagger.annotations.ApiOperation; 6 | import lombok.AllArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | 12 | /** 13 | *

14 | * 首页 控制器 15 | *

16 | * 17 | * @author Wang Chen Chen <932560435@qq.com> 18 | * @version 3.0 19 | */ 20 | 21 | 22 | @Slf4j 23 | @Api(tags = "[ 首页 ]") 24 | @RestController 25 | @AllArgsConstructor 26 | public class IndexController { 27 | 28 | @PreAuthorize("hasAuthority('home:get')") 29 | @ApiOperation(value = "home", notes = "home") 30 | @GetMapping(value = {"home",}) 31 | public JsonResult home() { 32 | return JsonResult.success("home"); 33 | } 34 | 35 | 36 | @PreAuthorize("hasAuthority('index:get')") 37 | @ApiOperation(value = "index", notes = "index") 38 | @GetMapping(value = {"index"}) 39 | public JsonResult index() { 40 | return JsonResult.success("index"); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/controller/LoginLogController.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.controller; 2 | 3 | import com.xaaef.robin.aspect.log.LogType; 4 | import com.xaaef.robin.aspect.log.OperateLog; 5 | import com.xaaef.robin.domain.Pagination; 6 | import com.xaaef.robin.entity.LoginLog; 7 | import com.xaaef.robin.param.QueryParams; 8 | import com.xaaef.robin.service.LoginLogService; 9 | import com.xaaef.robin.util.JsonResult; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import lombok.AllArgsConstructor; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.List; 17 | 18 | 19 | /** 20 | *

21 | * 用户登录日志 Controller 22 | *

23 | * 24 | * @author Wang Chen Chen<932560435@qq.com> 25 | * @version 2.0 26 | * @date 2019/12/25 22:13 27 | */ 28 | 29 | 30 | @Slf4j 31 | @Api(tags = "[ 系统 ] 登录日志") 32 | @RestController 33 | @AllArgsConstructor 34 | @RequestMapping("/login/log") 35 | public class LoginLogController { 36 | 37 | private LoginLogService baseService; 38 | 39 | @ApiOperation(value = "分页查询", notes = "根据关键字搜索") 40 | @GetMapping("/query") 41 | public JsonResult> query(QueryParams params) { 42 | var all = baseService.pageKeywords(params); 43 | return JsonResult.success(all.getTotal(), all.getRecords()); 44 | } 45 | 46 | @ApiOperation(value = "批量删除", notes = "只需要id即可") 47 | @OperateLog(title = "[登录日志] 批量删除", type = LogType.DELETE) 48 | @DeleteMapping("batch") 49 | public JsonResult delete(@RequestBody List ids) { 50 | boolean b = baseService.removeByIds(ids); 51 | return JsonResult.success(b); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/controller/OperLogController.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.controller; 2 | 3 | import com.xaaef.robin.aspect.log.LogType; 4 | import com.xaaef.robin.aspect.log.OperateLog; 5 | import com.xaaef.robin.domain.Pagination; 6 | import com.xaaef.robin.entity.OperLog; 7 | import com.xaaef.robin.param.QueryParams; 8 | import com.xaaef.robin.service.OperLogService; 9 | import com.xaaef.robin.util.JsonResult; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import lombok.AllArgsConstructor; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.List; 17 | 18 | 19 | /** 20 | *

21 | * 用户操作日志 Controller 22 | *

23 | * 24 | * @author Wang Chen Chen<932560435@qq.com> 25 | * @version 2.0 26 | * @date 2019/12/25 22:13 27 | */ 28 | 29 | 30 | @Slf4j 31 | @Api(tags = "[ 系统 ] 操作日志") 32 | @RestController 33 | @AllArgsConstructor 34 | @RequestMapping("/oper/log") 35 | public class OperLogController { 36 | 37 | private OperLogService baseService; 38 | 39 | @ApiOperation(value = "分页查询", notes = "根据关键字搜索") 40 | @GetMapping("/query") 41 | public JsonResult> query(QueryParams params) { 42 | var all = baseService.pageKeywords(params); 43 | return JsonResult.success(all.getTotal(), all.getRecords()); 44 | } 45 | 46 | 47 | @ApiOperation(value = "删除", notes = "只需要id即可") 48 | @OperateLog(title = "[操作日志] 删除", type = LogType.DELETE) 49 | @DeleteMapping("batch") 50 | public JsonResult delete(@RequestBody List ids) { 51 | boolean b = baseService.removeByIds(ids); 52 | return JsonResult.success(b); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/domain/Pagination.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * 返回分页 13 | *

14 | * 15 | * @author WangChenChen 16 | * @version 1.0.1 17 | * @date 2021/10/14 14:00 18 | */ 19 | 20 | @Getter 21 | @Setter 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | public class Pagination { 25 | 26 | /** 27 | * 总共,有多少条 28 | */ 29 | private Long total; 30 | 31 | /** 32 | * 数据 33 | */ 34 | private List list; 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/domain/TreeNode.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | *

9 | * 树节点 10 | *

11 | * 12 | * @author Wang Chen Chen 13 | * @version 1.0 14 | * @date 2021/7/5 9:31 15 | */ 16 | 17 | public interface TreeNode extends java.io.Serializable { 18 | 19 | Long getId(); 20 | 21 | Long getParentId(); 22 | 23 | Integer getSort(); 24 | 25 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 26 | List getChildren(); 27 | 28 | void setChildren(List list); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/LoginLog.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Builder; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | /** 15 | * 登录日志记录 16 | * 17 | * @TableName login_log 18 | */ 19 | 20 | @TableName(value = "login_log") 21 | @Data 22 | @Builder 23 | @AllArgsConstructor 24 | @NoArgsConstructor 25 | public class LoginLog implements Serializable { 26 | 27 | /** 28 | * ID 29 | */ 30 | @TableId 31 | private String messageId; 32 | 33 | /** 34 | * 登录类型 35 | */ 36 | private String grantType; 37 | 38 | /** 39 | * 用户ID 40 | */ 41 | private Long userId; 42 | 43 | /** 44 | * 用户昵称 45 | */ 46 | private String nickname; 47 | 48 | /** 49 | * 用户名 50 | */ 51 | private String username; 52 | 53 | /** 54 | * 头像 55 | */ 56 | private String avatar; 57 | 58 | /** 59 | * 请求IP 60 | */ 61 | private String requestIp; 62 | 63 | /** 64 | * 操作真实地址 65 | */ 66 | private String address; 67 | 68 | /** 69 | * 操作系统类型 70 | */ 71 | private String osName; 72 | 73 | /** 74 | * 浏览器 75 | */ 76 | private String browser; 77 | 78 | /** 79 | * 创建时间 80 | */ 81 | private LocalDateTime createTime; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysConfig.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | import com.xaaef.robin.base.entity.BaseEntity; 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | /** 17 | * [ 通用 ] 参数配置表 18 | * 19 | * @TableName sys_config 20 | */ 21 | 22 | @TableName(value = "sys_config") 23 | @Data 24 | @Builder 25 | @AllArgsConstructor 26 | @NoArgsConstructor 27 | public class SysConfig extends BaseEntity implements Serializable { 28 | /** 29 | * 参数主键 30 | */ 31 | @TableId(type = IdType.AUTO) 32 | private Long configId; 33 | 34 | /** 35 | * 参数名称 36 | */ 37 | private String configName; 38 | 39 | /** 40 | * 参数键名 41 | */ 42 | private String configKey; 43 | 44 | /** 45 | * 参数键值 46 | */ 47 | private String configValue; 48 | 49 | /** 50 | * 系统内置(1.是 0.否) 51 | */ 52 | private Integer configType; 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysDept.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import com.xaaef.robin.domain.TreeNode; 13 | import lombok.AllArgsConstructor; 14 | import lombok.Builder; 15 | import lombok.Data; 16 | import lombok.NoArgsConstructor; 17 | 18 | /** 19 | * [ 权限 ] 部门表 20 | * 21 | * @TableName sys_dept 22 | */ 23 | 24 | 25 | @TableName(value = "sys_dept") 26 | @Data 27 | @Builder 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | public class SysDept extends BaseEntity implements Serializable, TreeNode { 31 | 32 | /** 33 | * 部门 ID 34 | */ 35 | @TableId(type = IdType.AUTO) 36 | private Long deptId; 37 | 38 | /** 39 | * 父主键 40 | */ 41 | private Long parentId; 42 | 43 | /** 44 | * 部门名 45 | */ 46 | private String deptName; 47 | 48 | /** 49 | * 部门领导名称 50 | */ 51 | private String leader; 52 | 53 | /** 54 | * 领导手机号码 55 | */ 56 | private String leaderMobile; 57 | 58 | /** 59 | * 排序 60 | */ 61 | private Integer sort; 62 | 63 | /** 64 | * 部门描述 65 | */ 66 | private String description; 67 | 68 | 69 | @TableField(exist = false) 70 | private List children; 71 | 72 | 73 | @Override 74 | public Long getId() { 75 | return this.deptId; 76 | } 77 | 78 | @Override 79 | public List getChildren() { 80 | return this.children; 81 | } 82 | 83 | @Override 84 | public void setChildren(List list) { 85 | this.children = list; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysDictData.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * [ 通用 ] 字典数据表 19 | * 20 | * @TableName sys_dict_data 21 | */ 22 | 23 | @TableName(value = "sys_dict_data") 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class SysDictData extends BaseEntity implements Serializable { 29 | /** 30 | * 字典编码 31 | */ 32 | @TableId(type = IdType.AUTO) 33 | private Long dictCode; 34 | 35 | /** 36 | * 字典排序 37 | */ 38 | private Integer dictSort; 39 | 40 | /** 41 | * 字典标签 42 | */ 43 | private String dictLabel; 44 | 45 | /** 46 | * 字典键值 47 | */ 48 | private String dictValue; 49 | 50 | /** 51 | * 字典类型 52 | */ 53 | private String typeKey; 54 | 55 | /** 56 | * 样式属性(其他样式扩展) 57 | */ 58 | private String cssClass; 59 | 60 | /** 61 | * 表格回显样式 62 | */ 63 | private String listClass; 64 | 65 | /** 66 | * 是否默认(1.是 0.否) 67 | */ 68 | private Integer isDefault; 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysDictType.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * [ 通用 ] 字典类型表 19 | * 20 | * @TableName sys_dict_type 21 | */ 22 | 23 | @TableName(value = "sys_dict_type") 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class SysDictType extends BaseEntity implements Serializable { 29 | /** 30 | * 字典类型 ID 31 | */ 32 | @TableId(type = IdType.AUTO) 33 | private Long typeId; 34 | 35 | /** 36 | * 字典类型名 37 | */ 38 | private String typeName; 39 | 40 | /** 41 | * 字典类型关键字 42 | */ 43 | private String typeKey; 44 | 45 | /** 46 | * 部门描述 47 | */ 48 | private String description; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysNotice.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * [ 通用 ] 通知公告表 19 | * 20 | * @TableName sys_notice 21 | */ 22 | 23 | @TableName(value = "sys_notice") 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class SysNotice extends BaseEntity implements Serializable { 29 | /** 30 | * 公告ID 31 | */ 32 | @TableId(type = IdType.AUTO) 33 | private Long id; 34 | 35 | /** 36 | * 标题 37 | */ 38 | private String title; 39 | 40 | /** 41 | * 公告类型 [ 0.危险 1.紧急 2.警告 3.通知 ] 42 | */ 43 | private Integer category; 44 | 45 | /** 46 | * 发布时间 47 | */ 48 | private LocalDateTime releaseTime; 49 | 50 | /** 51 | * 内容 52 | */ 53 | private String content; 54 | 55 | /** 56 | * 谁可以查看此公告 [ 0.此商户下的用户 1.全部的用户 ] 57 | */ 58 | private Integer viewRange; 59 | 60 | /** 61 | * 状态 【0.已经过期 1.正常 】 62 | */ 63 | private Integer status; 64 | 65 | /** 66 | * 过期时间 67 | */ 68 | private LocalDateTime expired; 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysRole.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * [ 权限 ] 角色表 19 | * 20 | * @TableName sys_role 21 | */ 22 | 23 | @TableName(value = "sys_role") 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class SysRole extends BaseEntity implements Serializable { 29 | /** 30 | * 角色id 31 | */ 32 | @TableId(type = IdType.AUTO) 33 | private Long roleId; 34 | 35 | /** 36 | * 角色名 37 | */ 38 | private String roleName; 39 | 40 | /** 41 | * 部门描述 42 | */ 43 | private String description; 44 | } 45 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysRoleProxy.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.xaaef.robin.base.entity.BaseEntity; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.io.Serializable; 12 | 13 | /** 14 | * [ 权限 ] 角色表 15 | * 16 | * @TableName sys_role 17 | */ 18 | 19 | @Data 20 | @Builder 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | public class SysRoleProxy implements Serializable { 24 | /** 25 | * 用户id 26 | */ 27 | private Long userId; 28 | 29 | /** 30 | * 角色id 31 | */ 32 | private Long roleId; 33 | 34 | /** 35 | * 角色名 36 | */ 37 | private String roleName; 38 | 39 | /** 40 | * 部门描述 41 | */ 42 | private String description; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/entity/SysUserSocial.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | import com.xaaef.robin.base.entity.BaseEntity; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.NoArgsConstructor; 16 | 17 | /** 18 | * [ 权限 ] 用户社交平台登录 19 | * 20 | * @TableName sys_user_social 21 | */ 22 | 23 | @TableName(value = "sys_user_social") 24 | @Data 25 | @Builder 26 | @AllArgsConstructor 27 | @NoArgsConstructor 28 | public class SysUserSocial extends BaseEntity implements Serializable { 29 | 30 | /** 31 | * 用户社交ID 32 | */ 33 | @TableId(type = IdType.AUTO) 34 | private Long socialId; 35 | 36 | /** 37 | * 用户唯一ID 38 | */ 39 | private Long userId; 40 | 41 | /** 42 | * 社交账号唯一ID 43 | */ 44 | private String openId; 45 | 46 | /** 47 | * we_chat. 微信 tencent_qq. 腾讯QQ 48 | */ 49 | private String socialType; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/AdminFlagEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | 10 | /** 11 | *

12 | * 0.普通用户 13 | * 1.管理员 ( 管理员是禁止被删除 ) 14 | *

15 | * 16 | * @author Wang Chen Chen 17 | * @version 1.0 18 | * @date 2021/7/5 9:31 19 | */ 20 | 21 | 22 | @Getter 23 | @ToString 24 | public enum AdminFlagEnum { 25 | 26 | USER(0, "用户"), 27 | 28 | ADMIN(1, "管理员"); 29 | 30 | AdminFlagEnum(int code, String description) { 31 | this.code = code; 32 | this.description = description; 33 | } 34 | 35 | @EnumValue 36 | @JsonValue 37 | private final int code; 38 | 39 | private final String description; 40 | 41 | /** 42 | * 用于 spring mvc 实体参数绑定 43 | */ 44 | @JsonCreator 45 | public static AdminFlagEnum create(Integer value) { 46 | for (var v : values()) { 47 | if (v.code == value) { 48 | return v; 49 | } 50 | } 51 | return USER; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/DefaultEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | *

11 | * 默认 12 | * 1.是 13 | * 0.否 14 | *

15 | * 16 | * @author Wang Chen Chen 17 | * @version 1.0 18 | * @date 2021/7/5 9:31 19 | */ 20 | 21 | @Getter 22 | @ToString 23 | public enum DefaultEnum { 24 | 25 | YES(1, "是"), 26 | 27 | NO(0, "否"); 28 | 29 | DefaultEnum(int code, String description) { 30 | this.code = code; 31 | this.description = description; 32 | } 33 | 34 | @EnumValue 35 | @JsonValue 36 | private final int code; 37 | 38 | private final String description; 39 | 40 | /** 41 | * 用于 spring mvc 实体参数绑定 42 | */ 43 | @JsonCreator 44 | public static DefaultEnum create(Integer value) { 45 | for (var v : values()) { 46 | if (v.code == value) { 47 | return v; 48 | } 49 | } 50 | return NO; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/GenderEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | *

11 | * 性别 12 | * 0.女 13 | * 1.男 14 | * 2.未知 15 | *

16 | * 17 | * @author Wang Chen Chen 18 | * @version 1.0 19 | * @date 2021/7/5 9:31 20 | */ 21 | 22 | @Getter 23 | @ToString 24 | public enum GenderEnum { 25 | 26 | FEMALE(0, "女"), 27 | 28 | MALE(1, "男"), 29 | 30 | UNKNOWN(2, "未知"); 31 | 32 | GenderEnum(int code, String description) { 33 | this.code = code; 34 | this.description = description; 35 | } 36 | 37 | @EnumValue 38 | @JsonValue 39 | private final int code; 40 | 41 | private final String description; 42 | 43 | /** 44 | * 用于 spring mvc 实体参数绑定 45 | */ 46 | @JsonCreator 47 | public static GenderEnum create(Integer value) { 48 | for (var v : values()) { 49 | if (v.code == value) { 50 | return v; 51 | } 52 | } 53 | return UNKNOWN; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/GrantType.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | 8 | /** 9 | *

10 | * password : 密码模式 11 | * we_chat : 微信登陆模式 12 | * tencent_qq : 腾讯 QQ 登陆模式 13 | * sms : 手机短信模式 14 | *

15 | * 16 | * @author Wang Chen Chen 17 | * @version 1.0.1 18 | * @date 2021/7/5 9:31 19 | */ 20 | 21 | @Getter 22 | @ToString 23 | public enum GrantType { 24 | 25 | PASSWORD("password", "密码 登录模式"), 26 | 27 | WECHAT("we_chat", "微信登录 模式"), 28 | 29 | TENCENT_QQ("tencent_qq", "腾讯QQ登录 模式"), 30 | 31 | SEND_SMS("send_sms", "发送短信"), 32 | 33 | SMS("sms", "手机短信登录 模式"); 34 | 35 | GrantType(String code, String description) { 36 | this.code = code; 37 | this.description = description; 38 | } 39 | 40 | @JsonValue 41 | private final String code; 42 | 43 | private final String description; 44 | 45 | @JsonCreator 46 | public static GrantType get(String value) { 47 | for (var v : values()) { 48 | if (v.code.equalsIgnoreCase(value)) { 49 | return v; 50 | } 51 | } 52 | return PASSWORD; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/OAuth2Error.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | *

7 | * 认证状态 8 | *

9 | * 10 | * @author Wang Chen Chen 11 | * @version 1.0.1 12 | * @date 2021/7/5 9:31 13 | */ 14 | 15 | @Getter 16 | public enum OAuth2Error { 17 | 18 | /** 19 | * 认证错误,不知道啥原因 20 | */ 21 | OAUTH2_EXCEPTION(400004, "认证错误!"), 22 | 23 | 24 | /** 25 | * access_token 不存在 26 | */ 27 | ACCESS_TOKEN_INVALID(400010, "access_token 不存在"), 28 | 29 | 30 | /** 31 | * access_token 过期 32 | */ 33 | ACCESS_TOKEN_EXPIRED(400011, "access_token 已过期"), 34 | 35 | 36 | /** 37 | * token 格式错误 38 | */ 39 | TOKEN_FORMAT_ERROR(400012, "access_token 格式错误"), 40 | 41 | 42 | /** 43 | * 用户不存在 44 | */ 45 | USER_INVALID(400020, "用户或者密码错误"), 46 | 47 | 48 | /** 49 | * 当前用户被锁定 50 | */ 51 | USER_LOCKING(400023, "此用户被锁定"), 52 | 53 | /** 54 | * 用户手机号不存在 55 | */ 56 | USER_MOBILE_INVALID(400024, "用户手机号不存在"), 57 | 58 | /** 59 | * 授权类型错误 60 | */ 61 | AUTHORIZATION_GRANT_TYPE(400033, "授权类型错误"), 62 | 63 | /** 64 | * 请求参数解析错误 65 | */ 66 | REQUEST_PARAM_VALIDATE(400044, "请求参数解析错误"), 67 | 68 | /** 69 | * 验证码错误 70 | */ 71 | VERIFICATION_CODE_ERROR(400045, "验证码错误"), 72 | 73 | /** 74 | * 权限不足 75 | */ 76 | ACCESS_DENIED(400061, "请求访问,权限不足"); 77 | 78 | OAuth2Error(Integer status, String error) { 79 | this.status = status; 80 | this.error = error; 81 | } 82 | 83 | /** 84 | * 状态信息 85 | */ 86 | private final Integer status; 87 | 88 | /** 89 | * 错误消息 90 | */ 91 | private final String error; 92 | 93 | } 94 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/PermissionTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | *

11 | * 菜单的类型 12 | * 0.菜单 13 | * 1.按钮 14 | *

15 | * 16 | * @author Wang Chen Chen 17 | * @version 1.0 18 | * @date 2021/7/5 9:31 19 | */ 20 | 21 | @Getter 22 | @ToString 23 | public enum PermissionTypeEnum { 24 | 25 | MENU(0, "菜单"), 26 | 27 | BUTTON(1, "按钮"); 28 | 29 | PermissionTypeEnum(int code, String description) { 30 | this.code = code; 31 | this.description = description; 32 | } 33 | 34 | @EnumValue 35 | @JsonValue 36 | private final int code; 37 | 38 | private final String description; 39 | 40 | 41 | /** 42 | * 用于 spring mvc 实体参数绑定 43 | */ 44 | @JsonCreator 45 | public static PermissionTypeEnum create(Integer value) { 46 | for (var v : values()) { 47 | if (v.code == value) { 48 | return v; 49 | } 50 | } 51 | return MENU; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/enums/StatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | *

11 | * 0.禁用 12 | * 1.正常 13 | *

14 | * 15 | * @author Wang Chen Chen 16 | * @version 1.0 17 | * @date 2021/7/5 9:31 18 | */ 19 | 20 | 21 | @Getter 22 | @ToString 23 | public enum StatusEnum { 24 | 25 | DISABLE(0, "禁用"), 26 | 27 | NORMAL(1, "正常"); 28 | 29 | StatusEnum(int code, String description) { 30 | this.code = code; 31 | this.description = description; 32 | } 33 | 34 | @EnumValue 35 | @JsonValue 36 | private final int code; 37 | 38 | private final String description; 39 | 40 | 41 | /** 42 | * 用于 spring mvc 实体参数绑定 43 | */ 44 | @JsonCreator 45 | public static StatusEnum create(Integer value) { 46 | for (var v : values()) { 47 | if (v.code == value) { 48 | return v; 49 | } 50 | } 51 | return NORMAL; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/exception/JwtAuthException.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.exception; 2 | 3 | import com.xaaef.robin.enums.OAuth2Error; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import org.springframework.security.core.AuthenticationException; 8 | 9 | import static com.xaaef.robin.enums.OAuth2Error.OAUTH2_EXCEPTION; 10 | 11 | 12 | /** 13 | *

14 | * 认证异常 15 | *

16 | * 17 | * @author Wang Chen Chen 18 | * @version 1.0.1 19 | * @date 2021/7/5 9:31 20 | */ 21 | 22 | @Getter 23 | @Setter 24 | @ToString 25 | public class JwtAuthException extends AuthenticationException { 26 | 27 | private Integer status; 28 | 29 | 30 | public Integer getStatus() { 31 | return status; 32 | } 33 | 34 | 35 | public void setStatus(Integer status) { 36 | this.status = status; 37 | } 38 | 39 | 40 | public JwtAuthException(int status, String message) { 41 | super(message); 42 | this.status = status; 43 | } 44 | 45 | 46 | public JwtAuthException(String message) { 47 | this(OAUTH2_EXCEPTION.getStatus(), message); 48 | } 49 | 50 | 51 | public JwtAuthException(OAuth2Error status) { 52 | this(status.getStatus(), status.getError()); 53 | } 54 | 55 | 56 | public JwtAuthException() { 57 | this(OAUTH2_EXCEPTION.getError()); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/jwt/JwtAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.jwt; 2 | 3 | import com.xaaef.robin.enums.OAuth2Error; 4 | import com.xaaef.robin.util.JsonResult; 5 | import com.xaaef.robin.util.JsonUtils; 6 | import com.xaaef.robin.util.ServletUtils; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.security.access.AccessDeniedException; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.security.web.access.AccessDeniedHandler; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.servlet.ServletException; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | import java.io.IOException; 18 | 19 | 20 | @Component 21 | public class JwtAccessDeniedHandler implements AccessDeniedHandler, AuthenticationEntryPoint { 22 | 23 | /** 24 | * 权限不足, 25 | */ 26 | @Override 27 | public void handle(HttpServletRequest request, 28 | HttpServletResponse response, 29 | AccessDeniedException e) throws IOException { 30 | String msg = String.format("请求访问:%s,权限不足,请联系管理员", request.getRequestURI()); 31 | ServletUtils.renderError(response, OAuth2Error.ACCESS_DENIED.getStatus(), msg); 32 | } 33 | 34 | 35 | /** 36 | * 未认证 37 | */ 38 | @Override 39 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 40 | String msg = String.format("请求访问:%s,认证失败,无法访问系统资源", request.getRequestURI()); 41 | ServletUtils.renderError(response, OAuth2Error.OAUTH2_EXCEPTION.getStatus(), msg); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/jwt/JwtTokenProperties.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.jwt; 2 | 3 | import lombok.*; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | *

10 | *

11 | * 12 | * @author Wang Chen Chen<932560435@qq.com> 13 | * @version 1.0.0 14 | * @date 2020/7/2515:30 15 | */ 16 | 17 | @Getter 18 | @Setter 19 | @ToString 20 | @Builder 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @ConfigurationProperties(prefix = "jwt.token") 24 | public class JwtTokenProperties { 25 | 26 | /** 27 | * token 在请求头中的名称 28 | */ 29 | private String tokenHeader = "Authorization"; 30 | 31 | /** 32 | * token 类型 33 | */ 34 | private String tokenType = "Bearer "; 35 | 36 | /** 37 | * token 缓存 过期时间 单位(秒) 38 | */ 39 | private Integer tokenExpired = 3600; 40 | 41 | /** 42 | * 短信验证码过期时间 单位(秒) 43 | */ 44 | private Integer smsCodeExpired = 600; 45 | 46 | /** 47 | * 用户被挤下线,提示的过期时间 单位(秒) 48 | */ 49 | private Integer promptExpired = 600; 50 | 51 | /** 52 | * 秘钥 53 | */ 54 | private String secret = "2N321lIkh$*!IfNt4&5!YZykD$7@ApaM8r@b@r@&4CZ7eqKe!s"; 55 | 56 | /** 57 | * 单点登录,是否启用 58 | */ 59 | private Boolean sso = Boolean.TRUE; 60 | 61 | /** 62 | * 需要排除的URL 63 | */ 64 | private String[] excludePath; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/jwt/JwtTokenValue.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.jwt; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | 8 | /** 9 | *

10 | * token 返回值 11 | *

12 | * 13 | * @author Wang Chen Chen<932560435@qq.com> 14 | * @version 2.0 15 | * @date 2019/12/12 23:29 16 | */ 17 | 18 | 19 | @Getter 20 | @Setter 21 | @Builder 22 | public class JwtTokenValue implements java.io.Serializable { 23 | 24 | /** 25 | * 请求头的值 26 | */ 27 | private String header; 28 | 29 | /** 30 | * 表示访问令牌,必选项。 31 | */ 32 | @JsonProperty("access_token") 33 | private String accessToken; 34 | 35 | /** 36 | * 表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 37 | */ 38 | @JsonProperty("token_type") 39 | private String tokenType; 40 | 41 | /** 42 | * 表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。 43 | */ 44 | @JsonProperty("expires_in") 45 | private Integer expiresIn; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/jwt/StringGrantedAuthority.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.jwt; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.NoArgsConstructor; 5 | import org.springframework.security.core.GrantedAuthority; 6 | 7 | /** 8 | *

9 | * 10 | *

11 | * 12 | * @author WangChenChen 13 | * @version 1.0 14 | * @date 2022/3/22 18:05 15 | */ 16 | 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class StringGrantedAuthority implements GrantedAuthority { 20 | 21 | private String authority; 22 | 23 | public void setAuthority(String authority) { 24 | this.authority = authority; 25 | } 26 | 27 | @Override 28 | public String getAuthority() { 29 | return this.authority; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/ChinaAreaMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.ChinaArea; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【cn_area([ 通用 ] 中国行政地区表)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.CnArea 11 | */ 12 | 13 | public interface ChinaAreaMapper extends BaseMapper { 14 | 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/LoginLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.LoginLog; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【login_log(登录日志记录)】的数据库操作Mapper 9 | * @createDate 2022-03-24 11:22:11 10 | * @Entity com.xaaef.robin.entity.LoginLog 11 | */ 12 | 13 | public interface LoginLogMapper extends BaseMapper { 14 | 15 | } 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/OperLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.OperLog; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【oper_log(用户操作日志)】的数据库操作Mapper 9 | * @createDate 2022-03-24 11:22:11 10 | * @Entity com.xaaef.robin.entity.OperLog 11 | */ 12 | 13 | public interface OperLogMapper extends BaseMapper { 14 | 15 | } 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysConfig; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_config([ 通用 ] 参数配置表)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.SysConfig 11 | */ 12 | public interface SysConfigMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysDept; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Delete; 6 | import org.apache.ibatis.annotations.Insert; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.util.Set; 11 | 12 | /** 13 | * @author WangChenChen 14 | * @description 针对表【sys_dept([ 权限 ] 部门表)】的数据库操作Mapper 15 | * @createDate 2022-03-22 09:59:32 16 | * @Entity com.xaaef.robin.entity.SysDept 17 | */ 18 | public interface SysDeptMapper extends BaseMapper { 19 | 20 | 21 | // 删除 部门 的所有权限 22 | @Delete("DELETE FROM sys_dept_permission WHERE dept_id = #{id}") 23 | int deleteHaveMenus(Long id); 24 | 25 | 26 | // 部门 添加 权限 27 | int insertByPerms(@Param("id") Long id, @Param("items") Set items); 28 | 29 | 30 | } 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysDictDataMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysDictData; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_dict_data([ 通用 ] 字典数据表)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.SysDictData 11 | */ 12 | public interface SysDictDataMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysDictTypeMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysDictType; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_dict_type([ 通用 ] 字典类型表)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.SysDictType 11 | */ 12 | public interface SysDictTypeMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysNoticeMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysNotice; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_notice([ 通用 ] 通知公告表)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.SysNotice 11 | */ 12 | public interface SysNoticeMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysPermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysPermission; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author WangChenChen 12 | * @description 针对表【sys_permission([ 权限 ] 菜单权限表)】的数据库操作Mapper 13 | * @createDate 2022-03-22 09:59:32 14 | * @Entity com.xaaef.robin.entity.SysPermission 15 | */ 16 | 17 | public interface SysPermissionMapper extends BaseMapper { 18 | 19 | /** 20 | * 根据 用户ID 获取拥有的权限 21 | */ 22 | List listByUserId(Long userId); 23 | 24 | 25 | /** 26 | * 根据 用户ID 获取拥有的权限 27 | */ 28 | Set listSimpleByUserId(Long userId); 29 | 30 | 31 | /** 32 | * 判断是否某个权限,是否还被其他角色引用 33 | */ 34 | @Select("SELECT COUNT(*) FROM sys_role_permission WHERE role_id = #{roleId}") 35 | long roleReference(Long roleId); 36 | 37 | 38 | // 查询部门所有权限 39 | @Select("SELECT m.permission_id, m.parent_id, m.title, m.perms FROM sys_permission AS m " + 40 | "LEFT JOIN sys_dept_permission AS dm ON dm.permission_id = m.permission_id " + 41 | "WHERE dm.dept_id = #{deptId}") 42 | List selectByDeptId(Long deptId); 43 | 44 | 45 | // 查询角色所有权限 46 | @Select("SELECT m.permission_id, m.parent_id, m.title, m.perms FROM sys_permission AS m " + 47 | "LEFT JOIN sys_role_permission AS rm ON rm.permission_id = m.permission_id " + 48 | "WHERE rm.role_id = #{roleId}") 49 | List selectByRoleId(Long roleId); 50 | 51 | 52 | } 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysRole; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.xaaef.robin.entity.SysRoleProxy; 6 | import org.apache.ibatis.annotations.*; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * @author WangChenChen 13 | * @description 针对表【sys_role([ 权限 ] 角色表)】的数据库操作Mapper 14 | * @createDate 2022-03-22 09:59:32 15 | * @Entity com.xaaef.robin.entity.SysRole 16 | */ 17 | 18 | public interface SysRoleMapper extends BaseMapper { 19 | 20 | /** 21 | * 查询用户的角色 22 | * 23 | * @author WangChenChen 24 | * @date 2022/3/22 18:14 25 | */ 26 | Set listByUserId(Long userId); 27 | 28 | 29 | /** 30 | * 查询用户的角色 31 | * 32 | * @author WangChenChen 33 | * @date 2022/3/22 18:14 34 | */ 35 | Set listByUserIds(@Param("userIds") Set userIds); 36 | 37 | 38 | // 角色添加 菜单权限 39 | int insertByMenus(@Param("roleId") Long roleId, 40 | @Param("items") Set items); 41 | 42 | 43 | // 是否还有 用户 引用此角色 44 | @Select("SELECT COUNT(*) FROM sys_user_role WHERE role_id = #{roleId}") 45 | int userReference(Long roleId); 46 | 47 | 48 | // 删除 角色 的所有权限 49 | @Delete("DELETE FROM sys_role_permission WHERE role_id = #{roleId}") 50 | int deleteHaveMenus(Long roleId); 51 | 52 | 53 | } 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 5 | import com.xaaef.robin.entity.SysUser; 6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 7 | import com.xaaef.robin.param.UserQueryParams; 8 | import org.apache.ibatis.annotations.Delete; 9 | import org.apache.ibatis.annotations.Insert; 10 | import org.apache.ibatis.annotations.Param; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * @author WangChenChen 16 | * @description 针对表【sys_user([ 权限 ] 用户表)】的数据库操作Mapper 17 | * @createDate 2022-03-22 09:59:32 18 | * @Entity com.xaaef.robin.entity.SysUser 19 | */ 20 | public interface SysUserMapper extends BaseMapper { 21 | 22 | /** 23 | * 根据用户 keywords 获取用户信息 24 | * 25 | * @param params 26 | * @author Wang Chen Chen 27 | * @date 2021/7/5 11:46 28 | */ 29 | IPage selectKeywordsList(Page page, @Param("params") UserQueryParams params); 30 | 31 | 32 | /** 33 | * 删除某个用户,拥有的角色 34 | * 35 | * @param userId 36 | * @return Long 37 | * @date 2019/12/14 0:25 38 | */ 39 | @Delete("delete from sys_user_role where user_id = #{userId}") 40 | int deleteHaveRoles(Long userId); 41 | 42 | 43 | /** 44 | * 用户关联多个角色 45 | * 46 | * @param userId 47 | * @param Set 48 | * @date 2019/12/14 0:25 49 | */ 50 | int insertByRoles(@Param("userId") Long userId, @Param("roles") Set roles); 51 | 52 | } 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/mapper/SysUserSocialMapper.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.mapper; 2 | 3 | import com.xaaef.robin.entity.SysUserSocial; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_user_social([ 权限 ] 用户社交平台登录)】的数据库操作Mapper 9 | * @createDate 2022-03-22 09:59:32 10 | * @Entity com.xaaef.robin.entity.SysUserSocial 11 | */ 12 | public interface SysUserSocialMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/param/DictQueryParams.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.param; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.ToString; 6 | 7 | 8 | /** 9 | *

10 | * 字典查询,参数 11 | *

12 | * 13 | * @author Wang Chen Chen <932560435@qq.com> 14 | * @version 2.0 15 | * @date 2019/4/18 11:45 16 | */ 17 | 18 | @Data 19 | @ToString 20 | @EqualsAndHashCode 21 | public class DictQueryParams extends QueryParams { 22 | 23 | /** 24 | * 字典类型 25 | */ 26 | private String dictTypeKey; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/param/QueryParams.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.param; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | *

12 | * 基础参数传递 13 | *

14 | * 15 | * @author Wang Chen Chen<932560435@qq.com> 16 | * @date 2021/10/21 21:38 17 | */ 18 | 19 | @Getter 20 | @Setter 21 | @ToString 22 | @AllArgsConstructor 23 | public class QueryParams implements java.io.Serializable { 24 | 25 | public static QueryParams build() { 26 | return new QueryParams(); 27 | } 28 | 29 | public static QueryParams build(Integer pageNum, Integer pageSize) { 30 | return new QueryParams(pageNum, pageSize, null, null, null); 31 | } 32 | 33 | public static QueryParams build(Integer pageNum, Integer pageSize, String keywords) { 34 | return new QueryParams(pageNum, pageSize, keywords, null, null); 35 | } 36 | 37 | public QueryParams() { 38 | this.pageNum = 1; 39 | this.pageSize = 10; 40 | } 41 | 42 | /** 43 | * 当前第几页 44 | */ 45 | private Integer pageNum; 46 | 47 | /** 48 | * 每页多少条数据 49 | */ 50 | private Integer pageSize; 51 | 52 | /** 53 | * 搜索,关键字 54 | */ 55 | private String keywords; 56 | 57 | /** 58 | * 开始时间 59 | */ 60 | private LocalDateTime startTime; 61 | 62 | /** 63 | * 结束时间 64 | */ 65 | private LocalDateTime endTime; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/param/UserQueryParams.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.param; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | 8 | /** 9 | *

10 | * 用户查询的参数 11 | *

12 | * 13 | * @author Wang Chen Chen <932560435@qq.com> 14 | * @version 2.0 15 | * @date 2019/4/18 11:45 16 | */ 17 | 18 | @Getter 19 | @Setter 20 | @ToString 21 | public class UserQueryParams extends QueryParams { 22 | 23 | /** 24 | * 角色 ID 25 | */ 26 | private Long roleId; 27 | 28 | /** 29 | * 部门 ID 30 | */ 31 | private Long deptId; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/ChinaAreaService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; 5 | import com.xaaef.robin.entity.ChinaArea; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | import com.xaaef.robin.param.QueryParams; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author WangChenChen 13 | * @description 针对表【cn_area([ 通用 ] 中国行政地区表)】的数据库操作Service 14 | * @createDate 2022-03-22 09:59:32 15 | */ 16 | 17 | public interface ChinaAreaService extends IService { 18 | 19 | /** 20 | * 分页查询 21 | * 22 | * @author Wang Chen Chen 23 | * @date 2021/8/25 9:41 24 | */ 25 | IPage pageKeywords(QueryParams params); 26 | 27 | 28 | /** 29 | * 根据 条件 查询全部 30 | * 31 | * @author Wang Chen Chen 32 | * @date 2021/8/25 9:41 33 | */ 34 | List list(SFunction column, Object value); 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/JwtTokenService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.exception.JwtAuthException; 4 | import com.xaaef.robin.jwt.JwtLoginUser; 5 | import com.xaaef.robin.jwt.JwtTokenValue; 6 | 7 | import java.util.Set; 8 | 9 | 10 | /** 11 | *

12 | * 服务端 token 认证 13 | *

14 | * 15 | * @author Wang Chen Chen 16 | * @version 1.0.1 17 | * @date 2021/7/12 16:28 18 | */ 19 | 20 | 21 | public interface JwtTokenService { 22 | 23 | /** 24 | * 设置登录的用户 到redis中 25 | * 26 | * @param loginId 27 | * @param loginUser 28 | */ 29 | void setLoginUser(String loginId, JwtLoginUser loginUser); 30 | 31 | 32 | /** 33 | * 校验 token 值是否正确 34 | *

35 | * 例: Bearer eyJhbGciOiJIUzUxMiJ9.eyJqdG6IjE2NDPuFA 36 | * 37 | * @param bearerToken 38 | * @author Wang Chen Chen 39 | * @date 2021/7/12 16:29 40 | */ 41 | JwtLoginUser validate(String bearerToken) throws JwtAuthException; 42 | 43 | 44 | /** 45 | * 刷新 token 46 | */ 47 | JwtTokenValue refresh(); 48 | 49 | 50 | /** 51 | * 退出登录 52 | */ 53 | void logout(); 54 | 55 | 56 | /** 57 | * 获取 所有的在线用户 58 | * 59 | * @return String 用户名称 60 | * @author Wang Chen Chen 61 | * @date 2021/7/12 16:29 62 | */ 63 | Set getOnlineUsers(); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/LoginLogService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.xaaef.robin.entity.LoginLog; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.xaaef.robin.param.QueryParams; 7 | 8 | /** 9 | * @author WangChenChen 10 | * @description 针对表【login_log(登录日志记录)】的数据库操作Service 11 | * @createDate 2022-03-24 11:22:11 12 | */ 13 | 14 | 15 | public interface LoginLogService extends IService { 16 | 17 | /** 18 | * 分页查询 19 | * 20 | * @author Wang Chen Chen 21 | * @date 2021/8/25 9:41 22 | */ 23 | IPage pageKeywords(QueryParams params); 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/OperLogService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.xaaef.robin.entity.OperLog; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | import com.xaaef.robin.param.QueryParams; 7 | 8 | /** 9 | * @author WangChenChen 10 | * @description 针对表【oper_log(用户操作日志)】的数据库操作Service 11 | * @createDate 2022-03-24 11:22:11 12 | */ 13 | 14 | public interface OperLogService extends IService { 15 | 16 | 17 | /** 18 | * 分页查询 19 | * 20 | * @author Wang Chen Chen 21 | * @date 2021/8/25 9:41 22 | */ 23 | IPage pageKeywords(QueryParams params); 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysDeptService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.base.service.BaseService; 4 | import com.xaaef.robin.entity.SysDept; 5 | import com.xaaef.robin.vo.UpdatePermsVO; 6 | 7 | import java.util.Set; 8 | 9 | /** 10 | * @author WangChenChen 11 | * @description 针对表【sys_dept([ 权限 ] 部门表)】的数据库操作Service 12 | * @createDate 2022-03-22 09:59:32 13 | */ 14 | 15 | 16 | public interface SysDeptService extends BaseService { 17 | 18 | /** 19 | * 已经拥有的菜单 20 | * 21 | * @throws 22 | * @author Wang Chen Chen<932560435@qq.com> 23 | * @create 2021/7/24 14:49 24 | */ 25 | UpdatePermsVO listHavePerms(Long deptId); 26 | 27 | 28 | /** 29 | * 修改 部门 菜单 30 | * 31 | * @author Wang Chen Chen 32 | * @date 2021/7/23 15:19 33 | */ 34 | boolean updatePerms(Long id, Set items); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysDictDataService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.xaaef.robin.base.service.BaseService; 5 | import com.xaaef.robin.entity.SysDictData; 6 | import com.xaaef.robin.param.DictQueryParams; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author WangChenChen 12 | * @description 针对表【sys_dict_data([ 通用 ] 字典数据表)】的数据库操作Service 13 | * @createDate 2022-03-22 09:59:32 14 | */ 15 | 16 | public interface SysDictDataService extends BaseService { 17 | 18 | /** 19 | * 分页查询 20 | * 21 | * @author WangChenChen 22 | * @date 2022/3/22 11:09 23 | */ 24 | IPage pageKeywords(DictQueryParams params); 25 | 26 | 27 | /** 28 | * 根据关键字查询 29 | * 30 | * @author Wang Chen Chen 31 | * @date 2021/8/24 18:24 32 | */ 33 | List listByKey(String dictTypeKey); 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysDictTypeService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.base.service.BaseService; 4 | import com.xaaef.robin.entity.SysDictType; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_dict_type([ 通用 ] 字典类型表)】的数据库操作Service 9 | * @createDate 2022-03-22 09:59:32 10 | */ 11 | public interface SysDictTypeService extends BaseService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysNoticeService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.base.service.BaseService; 4 | import com.xaaef.robin.entity.SysNotice; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_notice([ 通用 ] 通知公告表)】的数据库操作Service 9 | * @createDate 2022-03-22 09:59:32 10 | */ 11 | public interface SysNoticeService extends BaseService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysPermissionService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; 4 | import com.xaaef.robin.base.service.BaseService; 5 | import com.xaaef.robin.entity.SysPermission; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | /** 13 | * @author WangChenChen 14 | * @description 针对表【sys_permission([ 权限 ] 菜单权限表)】的数据库操作Service 15 | * @createDate 2022-03-22 09:59:32 16 | */ 17 | 18 | public interface SysPermissionService extends BaseService { 19 | 20 | 21 | /** 22 | * 根据用户ID 获取全部的权限 23 | * 24 | * @author WangChenChen 25 | * @date 2022/3/22 17:42 26 | */ 27 | List listByUserId(Long userId); 28 | 29 | 30 | /** 31 | * 根据用户ID 获取全部的权限 字符串 32 | * 33 | * @author WangChenChen 34 | * @date 2022/3/22 17:42 35 | */ 36 | Set listSimpleByUserId(Long userId); 37 | 38 | 39 | /** 40 | * 判断是否某个权限,是否还被其他角色引用 41 | */ 42 | boolean roleReference(Long roleId); 43 | 44 | 45 | /** 46 | * 判断是否某个权限下,是否还有拥有子权限 47 | */ 48 | boolean haveChildren(Long pid); 49 | 50 | 51 | /** 52 | * 获取 此部门 的所有菜单权限 53 | * 54 | * @author Wang Chen Chen 55 | * @date 2021/7/21 16:55 56 | */ 57 | List listByDeptId(Long deptId); 58 | 59 | 60 | /** 61 | * 获取 此角色 的所有菜单权限 62 | * 63 | * @author Wang Chen Chen 64 | * @date 2021/7/21 16:55 65 | */ 66 | List listByRoleId(Long roleId); 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysRoleService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.base.service.BaseService; 4 | import com.xaaef.robin.entity.SysRole; 5 | import com.xaaef.robin.vo.UpdatePermsVO; 6 | 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | /** 11 | * @author WangChenChen 12 | * @description 针对表【sys_role([ 权限 ] 角色表)】的数据库操作Service 13 | * @createDate 2022-03-22 09:59:32 14 | */ 15 | 16 | public interface SysRoleService extends BaseService { 17 | 18 | /** 19 | * 查询用户的角色 20 | * 21 | * @author WangChenChen 22 | * @date 2022/3/22 18:14 23 | */ 24 | Set listByUserId(Long userId); 25 | 26 | /** 27 | * 查询用户的角色 28 | * 29 | * @author WangChenChen 30 | * @date 2022/3/22 18:14 31 | */ 32 | Map> listByUserIds(Set userIds); 33 | 34 | /** 35 | * 已经拥有的权限 36 | */ 37 | UpdatePermsVO listHavePerms(Long roleId); 38 | 39 | /** 40 | * 修改 角色 权限 41 | * 42 | * @author Wang Chen Chen 43 | * @date 2021/7/23 15:19 44 | */ 45 | boolean updatePerms(Long id, Set items); 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/SysUserSocialService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.base.service.BaseService; 4 | import com.xaaef.robin.entity.SysUserSocial; 5 | 6 | /** 7 | * @author WangChenChen 8 | * @description 针对表【sys_user_social([ 权限 ] 用户社交平台登录)】的数据库操作Service 9 | * @createDate 2022-03-22 09:59:32 10 | */ 11 | public interface SysUserSocialService extends BaseService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/UserLoginService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import com.xaaef.robin.exception.JwtAuthException; 4 | import com.xaaef.robin.jwt.JwtTokenValue; 5 | import com.xaaef.robin.vo.LoginUserVO; 6 | import org.springframework.security.core.AuthenticationException; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | /** 11 | *

12 | * 用户 登录 Service 接口 13 | *

14 | * 15 | * @author Wang Chen Chen <932560435@qq.com> 16 | * @version 2.0 17 | * @date 2019/4/18 11:45 18 | */ 19 | 20 | 21 | public interface UserLoginService { 22 | 23 | /** 24 | * 用户登录 25 | * 26 | * @param user 27 | * @return String token 值 28 | * @throws AuthenticationException 29 | */ 30 | JwtTokenValue login(LoginUserVO user, HttpServletRequest request) throws JwtAuthException; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/VerifyCodeService.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | /** 6 | *

7 | * 验证码 8 | *

9 | * 10 | * @author Wang Chen Chen<932560435@qq.com> 11 | * @version 1.0 12 | * @createTime 2020/3/5 0005 11:28 13 | */ 14 | 15 | public interface VerifyCodeService { 16 | 17 | /** 18 | * 随机获取图形验证码 19 | * 20 | * @param codeKey 21 | * @return ImageVerifyCode 22 | * @author Wang Chen Chen<932560435@qq.com> 23 | * @createTime 2020/3/5 0005 11:31 24 | */ 25 | BufferedImage randomImageVerifyCode(String codeKey); 26 | 27 | /** 28 | * 删除在 redis 中缓存的。图形验证码值 29 | * 30 | * @param codeKey 31 | * @return ImageVerifyCode 32 | * @author Wang Chen Chen<932560435@qq.com> 33 | * @createTime 2020/3/5 0005 11:31 34 | */ 35 | void deleteImageVerifyCode(String codeKey); 36 | 37 | /** 38 | * 删除在 redis 中缓存的。图形验证码值 39 | * 40 | * @param codeKey 41 | * @param userCodeText 42 | * @return ImageVerifyCode 43 | * @author Wang Chen Chen<932560435@qq.com> 44 | * @createTime 2020/3/5 0005 11:31 45 | */ 46 | boolean checkVerifyCode(String codeKey, String userCodeText); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/LoginLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.core.metadata.OrderItem; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 8 | import com.xaaef.robin.entity.ChinaArea; 9 | import com.xaaef.robin.entity.LoginLog; 10 | import com.xaaef.robin.param.QueryParams; 11 | import com.xaaef.robin.service.LoginLogService; 12 | import com.xaaef.robin.mapper.LoginLogMapper; 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.springframework.stereotype.Service; 15 | 16 | /** 17 | * @author WangChenChen 18 | * @description 针对表【login_log(登录日志记录)】的数据库操作Service实现 19 | * @createDate 2022-03-24 11:22:11 20 | */ 21 | 22 | 23 | @Service 24 | public class LoginLogServiceImpl extends ServiceImpl 25 | implements LoginLogService { 26 | 27 | @Override 28 | public IPage pageKeywords(QueryParams params) { 29 | var wrapper = new LambdaQueryWrapper(); 30 | Page page = Page.of(params.getPageNum(), params.getPageSize()); 31 | page.addOrder(OrderItem.desc("create_time")); 32 | if (StringUtils.isNotBlank(params.getKeywords())) { 33 | String keywords = params.getKeywords().trim(); 34 | wrapper.like(LoginLog::getNickname, keywords) 35 | .or() 36 | .like(LoginLog::getUsername, keywords) 37 | .or() 38 | .like(LoginLog::getAddress, keywords); 39 | } 40 | return baseMapper.selectPage(page, wrapper); 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/OperLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.core.metadata.OrderItem; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 8 | import com.xaaef.robin.entity.ChinaArea; 9 | import com.xaaef.robin.entity.OperLog; 10 | import com.xaaef.robin.param.QueryParams; 11 | import com.xaaef.robin.service.OperLogService; 12 | import com.xaaef.robin.mapper.OperLogMapper; 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.springframework.stereotype.Service; 15 | 16 | /** 17 | * @author WangChenChen 18 | * @description 针对表【oper_log(用户操作日志)】的数据库操作Service实现 19 | * @createDate 2022-03-24 11:22:11 20 | */ 21 | 22 | 23 | @Service 24 | public class OperLogServiceImpl extends ServiceImpl 25 | implements OperLogService { 26 | 27 | @Override 28 | public IPage pageKeywords(QueryParams params) { 29 | var wrapper = new LambdaQueryWrapper(); 30 | Page page = Page.of(params.getPageNum(), params.getPageSize()); 31 | page.addOrder(OrderItem.desc("create_time")); 32 | if (StringUtils.isNotBlank(params.getKeywords())) { 33 | String keywords = params.getKeywords().trim(); 34 | wrapper.like(OperLog::getTitle, keywords) 35 | .or() 36 | .like(OperLog::getMethod, keywords) 37 | .or() 38 | .like(OperLog::getRequestUrl, keywords); 39 | } 40 | return baseMapper.selectPage(page, wrapper); 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/SysDictDataServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.baomidou.mybatisplus.core.metadata.IPage; 6 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 7 | import com.xaaef.robin.base.service.impl.BaseServiceImpl; 8 | import com.xaaef.robin.entity.SysDictData; 9 | import com.xaaef.robin.param.DictQueryParams; 10 | import com.xaaef.robin.service.SysDictDataService; 11 | import com.xaaef.robin.mapper.SysDictDataMapper; 12 | import lombok.AllArgsConstructor; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * @author WangChenChen 19 | * @description 针对表【sys_dict_data([ 通用 ] 字典数据表)】的数据库操作Service实现 20 | * @createDate 2022-03-22 09:59:32 21 | */ 22 | 23 | 24 | @Service 25 | @AllArgsConstructor 26 | public class SysDictDataServiceImpl extends BaseServiceImpl 27 | implements SysDictDataService { 28 | 29 | 30 | @Override 31 | public IPage pageKeywords(DictQueryParams params) { 32 | Page page = Page.of(params.getPageNum(), params.getPageSize()); 33 | QueryWrapper wrapper = getKeywordsQueryWrapper(params, null); 34 | wrapper.lambda().eq(SysDictData::getTypeKey, params.getDictTypeKey()); 35 | return super.page(page, wrapper); 36 | } 37 | 38 | 39 | @Override 40 | public List listByKey(String dictTypeKey) { 41 | var wrapper = new LambdaQueryWrapper(); 42 | wrapper.eq(SysDictData::getTypeKey, dictTypeKey); 43 | return super.list(wrapper); 44 | } 45 | 46 | 47 | } 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/SysDictTypeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.xaaef.robin.base.service.impl.BaseServiceImpl; 4 | import com.xaaef.robin.entity.SysDictType; 5 | import com.xaaef.robin.service.SysDictTypeService; 6 | import com.xaaef.robin.mapper.SysDictTypeMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author WangChenChen 11 | * @description 针对表【sys_dict_type([ 通用 ] 字典类型表)】的数据库操作Service实现 12 | * @createDate 2022-03-22 09:59:32 13 | */ 14 | 15 | 16 | @Service 17 | public class SysDictTypeServiceImpl extends BaseServiceImpl 18 | implements SysDictTypeService{ 19 | 20 | 21 | 22 | } 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/SysNoticeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.xaaef.robin.base.service.impl.BaseServiceImpl; 4 | import com.xaaef.robin.entity.SysNotice; 5 | import com.xaaef.robin.service.SysNoticeService; 6 | import com.xaaef.robin.mapper.SysNoticeMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author WangChenChen 11 | * @description 针对表【sys_notice([ 通用 ] 通知公告表)】的数据库操作Service实现 12 | * @createDate 2022-03-22 09:59:32 13 | */ 14 | 15 | 16 | @Service 17 | public class SysNoticeServiceImpl extends BaseServiceImpl 18 | implements SysNoticeService { 19 | 20 | 21 | 22 | } 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/SysPermissionServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.xaaef.robin.base.service.impl.BaseServiceImpl; 4 | import com.xaaef.robin.entity.SysPermission; 5 | import com.xaaef.robin.service.SysPermissionService; 6 | import com.xaaef.robin.mapper.SysPermissionMapper; 7 | import lombok.AllArgsConstructor; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | /** 14 | * @author WangChenChen 15 | * @description 针对表【sys_permission([ 权限 ] 菜单权限表)】的数据库操作Service实现 16 | * @createDate 2022-03-22 09:59:32 17 | */ 18 | 19 | 20 | @Service 21 | @AllArgsConstructor 22 | public class SysPermissionServiceImpl extends BaseServiceImpl 23 | implements SysPermissionService { 24 | 25 | @Override 26 | public List listByUserId(Long userId) { 27 | return baseMapper.listByUserId(userId); 28 | } 29 | 30 | @Override 31 | public Set listSimpleByUserId(Long userId) { 32 | return baseMapper.listSimpleByUserId(userId); 33 | } 34 | 35 | 36 | @Override 37 | public boolean roleReference(Long roleId) { 38 | return baseMapper.roleReference(roleId) > 0; 39 | } 40 | 41 | 42 | @Override 43 | public boolean haveChildren(Long pid) { 44 | return count(SysPermission::getParentId, pid) > 0; 45 | } 46 | 47 | 48 | @Override 49 | public List listByDeptId(Long deptId) { 50 | return baseMapper.selectByDeptId(deptId); 51 | } 52 | 53 | 54 | @Override 55 | public List listByRoleId(Long roleId) { 56 | return baseMapper.selectByRoleId(roleId); 57 | } 58 | 59 | 60 | } 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/service/impl/SysUserSocialServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.service.impl; 2 | 3 | import com.xaaef.robin.base.service.impl.BaseServiceImpl; 4 | import com.xaaef.robin.entity.SysUserSocial; 5 | import com.xaaef.robin.service.SysUserSocialService; 6 | import com.xaaef.robin.mapper.SysUserSocialMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author WangChenChen 11 | * @description 针对表【sys_user_social([ 权限 ] 用户社交平台登录)】的数据库操作Service实现 12 | * @createDate 2022-03-22 09:59:32 13 | */ 14 | 15 | 16 | @Service 17 | public class SysUserSocialServiceImpl extends BaseServiceImpl 18 | implements SysUserSocialService { 19 | 20 | 21 | } 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/FSTUtils.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.nustaq.serialization.FSTConfiguration; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | @Slf4j 11 | public class FSTUtils { 12 | 13 | private final static FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration(); 14 | 15 | private final static ObjectMapper MAPPER = JsonUtils.getMapper(); 16 | 17 | /** 18 | * 将对象转换成 字节数组。 19 | * 20 | * @param data 21 | * @return java.util.List 22 | * @author Wang Chen Chen <932560435@qq.com> 23 | * @date 2019/4/18 15:26 24 | */ 25 | public static byte[] toBytes(Object data) { 26 | return conf.asByteArray(data); 27 | } 28 | 29 | 30 | /** 31 | * 将 字节数组 转化为对象 32 | * 33 | * @param src 34 | * @param beanType 35 | * @return java.util.List 36 | * @author Wang Chen Chen <932560435@qq.com> 37 | * @date 2019/4/18 15:26 38 | */ 39 | public static T toPojo(byte[] src, Class beanType) { 40 | Object obj = conf.asObject(src); 41 | return MAPPER.convertValue(obj, beanType); 42 | } 43 | 44 | 45 | /** 46 | * 将 字节数组 转换成pojo对象list 47 | * 48 | * @param src 49 | * @param beanType 50 | * @return java.util.List 51 | * @author Wang Chen Chen <932560435@qq.com> 52 | * @date 2019/4/18 15:26 53 | */ 54 | public static List toListPojo(byte[] src, Class beanType) { 55 | Object obj = conf.asObject(src); 56 | return MAPPER.convertValue(obj, MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, beanType)); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/RequestUtils.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util; 2 | 3 | import com.xaaef.robin.util.useragent.UserAgent; 4 | import com.xaaef.robin.util.useragent.UserAgentParser; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import java.io.IOException; 10 | 11 | /** 12 | *

13 | * 请求工具类 14 | *

15 | * 16 | * @author Wang Chen Chen 17 | * @version 1.0 18 | * @date 2021/7/5 10:50 19 | */ 20 | 21 | @Slf4j 22 | public class RequestUtils { 23 | 24 | private static UserAgentParser parser; 25 | 26 | static { 27 | try { 28 | parser = new UserAgentParser(); 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | log.error("UserAgentParser : {}", e.getMessage()); 32 | } 33 | } 34 | 35 | 36 | /** 37 | * 获取客户端信息 38 | * 39 | * @return 40 | */ 41 | public static UserAgent getUserAgent(HttpServletRequest request) { 42 | String ua = request.getHeader("User-Agent"); 43 | return parser.parse(ua); 44 | } 45 | 46 | 47 | /** 48 | * 获取客户端信息 49 | */ 50 | public static UserAgent getUserAgent(String ua) { 51 | return parser.parse(ua); 52 | } 53 | 54 | 55 | /** 56 | * 获取 请求全路径 57 | */ 58 | public static String getFullPath(HttpServletRequest request) { 59 | StringBuffer url = request.getRequestURL(); 60 | if (!StringUtils.isEmpty(request.getQueryString())) { 61 | url.append("?").append(request.getQueryString()); 62 | } 63 | return url.toString(); 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/Constants.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent; 2 | 3 | /** 4 | * author : denisdou 5 | * email : 402550833@qq.com 6 | * date : 2021/01/26 7 | */ 8 | public class Constants { 9 | 10 | public final static String REGEX = "regex"; 11 | 12 | public final static String VENDOR = "vendor"; 13 | 14 | public final static String FAMILY="family"; 15 | 16 | public final static String OS = "osName"; 17 | 18 | public final static String MAJOR = "majorVersion"; 19 | 20 | public final static String MINOR = "minorVersion"; 21 | 22 | public final static String IS_MOBILE="isMobile"; 23 | 24 | public final static String IS_TV = "isTv"; 25 | 26 | public final static String DEFAULT_VALUE = "-"; 27 | 28 | public final static String TV = "tv"; 29 | } 30 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/UserAgent.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent; 2 | 3 | import com.xaaef.robin.util.useragent.browser.Browser; 4 | import com.xaaef.robin.util.useragent.os.Os; 5 | 6 | /** 7 | * @author doujiajun 402550833@qq.com 8 | */ 9 | 10 | 11 | public class UserAgent { 12 | private final Os os; 13 | private final Browser browser; 14 | 15 | UserAgent(Os os, Browser browser) { 16 | this.os = os; 17 | this.browser = browser; 18 | } 19 | 20 | public Os getOs() { 21 | return os; 22 | } 23 | 24 | public Browser getBrowser() { 25 | return browser; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/browser/Browser.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.browser; 2 | 3 | 4 | import com.xaaef.robin.util.useragent.Constants; 5 | 6 | /** 7 | * @author doujiajun 402550833@qq.com 8 | */ 9 | 10 | public class Browser { 11 | public static final Browser DEFAULT_BROWSER = new Browser(Constants.DEFAULT_VALUE, Constants.DEFAULT_VALUE, null, null, Engine.DEFAULT_ENGINE); 12 | private final String vendor; 13 | private final String family; 14 | private final String major; 15 | private final String minor; 16 | private final Engine engine; 17 | 18 | Browser(String vendor, String family, String major, String minor, Engine engine) { 19 | this.vendor = vendor; 20 | this.family = family; 21 | this.major = major; 22 | this.minor = minor; 23 | this.engine = engine; 24 | } 25 | 26 | public String getVendor() { 27 | return vendor; 28 | } 29 | 30 | public String getFamily() { 31 | return family; 32 | } 33 | 34 | public String getMajor() { 35 | return major; 36 | } 37 | 38 | public String getMinor() { 39 | return minor; 40 | } 41 | 42 | public Engine getEngine() { 43 | return engine; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/browser/BrowserParser.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.browser; 2 | import org.apache.commons.lang3.StringUtils; 3 | 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * @author doujiajun 402550833@qq.com 10 | */ 11 | public class BrowserParser { 12 | private final List patterns; 13 | 14 | BrowserParser(List patterns) { 15 | this.patterns = patterns; 16 | } 17 | 18 | public static BrowserParser addList(List> list) { 19 | return new BrowserParser( 20 | list.stream().map(config -> { 21 | return BrowserPattern.addFromMap(config); 22 | }).collect(Collectors.toList()) 23 | ); 24 | } 25 | 26 | public Browser parse(String agentString){ 27 | if(StringUtils.isBlank(agentString)){ 28 | return Browser.DEFAULT_BROWSER; 29 | } 30 | 31 | Browser browser; 32 | for (BrowserPattern p : patterns) { 33 | if ((browser = p.match(agentString))!=null) { 34 | return browser; 35 | } 36 | } 37 | return Browser.DEFAULT_BROWSER; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/browser/Engine.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.browser; 2 | 3 | 4 | import com.xaaef.robin.util.useragent.Constants; 5 | 6 | /** 7 | * @author doujiajun 402550833@qq.com 8 | */ 9 | public class Engine { 10 | public static final Engine DEFAULT_ENGINE = new Engine(Constants.DEFAULT_VALUE, Constants.DEFAULT_VALUE); 11 | private final String family; 12 | private final String version; 13 | 14 | Engine(String family, String version) { 15 | this.family = family; 16 | this.version = version; 17 | } 18 | 19 | public String getName() { 20 | return family; 21 | } 22 | 23 | public String getVersion() { 24 | return version; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/os/Os.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.os; 2 | 3 | 4 | import com.xaaef.robin.util.useragent.Constants; 5 | 6 | /** 7 | * @author doujiajun 402550833@qq.com 8 | */ 9 | public class Os { 10 | public static final Os DEFAULT_OS = new Os(Constants.DEFAULT_VALUE, Constants.DEFAULT_VALUE, "0", "0", false, false, Constants.DEFAULT_VALUE); 11 | 12 | private final String vendor; 13 | private final String family; 14 | private final String major; 15 | private final String minor; 16 | private final boolean isMobile; 17 | private final boolean isTv; 18 | private final String platform; 19 | 20 | Os(String vendor, String family, String major, String minor, boolean isMobile, boolean isTv, String platform) { 21 | this.vendor = vendor; 22 | this.family = family; 23 | this.major = major; 24 | this.minor = minor; 25 | this.isMobile = isMobile; 26 | this.isTv = isTv; 27 | this.platform = platform; 28 | } 29 | 30 | public String getVendor() { 31 | return vendor; 32 | } 33 | 34 | public String getFamily() { 35 | return family; 36 | } 37 | 38 | public String getMajor() { 39 | return major; 40 | } 41 | 42 | public String getMinor() { 43 | return minor; 44 | } 45 | 46 | public boolean isMobile() { 47 | return isMobile; 48 | } 49 | 50 | public boolean isTv() { 51 | return isTv; 52 | } 53 | 54 | public String getPlatform() { 55 | return platform; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/os/OsParser.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.os; 2 | import org.apache.commons.lang3.StringUtils; 3 | 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * @author doujiajun 402550833@qq.com 10 | */ 11 | public class OsParser { 12 | private List patterns; 13 | 14 | public OsParser(List patterns) { 15 | this.patterns = patterns; 16 | } 17 | 18 | public static OsParser addList(List> list) { 19 | return new OsParser( 20 | list.stream().map(config -> { 21 | return OsPattern.addFromMap(config); 22 | }).collect(Collectors.toList()) 23 | ); 24 | } 25 | 26 | public Os parse(String userAgentString) { 27 | if (StringUtils.isBlank(userAgentString)) { 28 | return Os.DEFAULT_OS; 29 | } 30 | 31 | Os os; 32 | for (OsPattern p : patterns) { 33 | if ((os = p.match(userAgentString)) != null) { 34 | return os; 35 | } 36 | } 37 | return Os.DEFAULT_OS; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/util/useragent/os/PlatformEnum.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.util.useragent.os; 2 | 3 | import com.xaaef.robin.util.useragent.Constants; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * @author doujiajun 402550833@qq.com 10 | */ 11 | public enum PlatformEnum { 12 | 13 | ARM("arm", "ARM"), 14 | 15 | X64("[wow|x|win|amd64|x86_]64", "x64"), 16 | 17 | X86("i[0-9]86|i86pc", "x86"); 18 | 19 | private String regex; 20 | 21 | private String family; 22 | 23 | public String getRegex() { 24 | return regex; 25 | } 26 | 27 | public String getFamily() { 28 | return family; 29 | } 30 | 31 | PlatformEnum(final String regex, final String family) { 32 | this.regex = regex; 33 | this.family = family; 34 | } 35 | 36 | public static String match(String agentString) { 37 | for (PlatformEnum info : values()) { 38 | Pattern pattern = Pattern.compile(info.getRegex()); 39 | Matcher matcher = pattern.matcher(agentString.toLowerCase()); 40 | if (!matcher.find()) { 41 | continue; 42 | } 43 | return info.getFamily(); 44 | } 45 | return Constants.DEFAULT_VALUE; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/BindingPermsVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotNull; 9 | import javax.validation.constraints.Size; 10 | import java.util.Set; 11 | 12 | /** 13 | *

14 | * ID 可以是 角色ID,部门ID 15 | *

16 | * 17 | * @author Wang Chen Chen 18 | * @version 1.0.1 19 | * @date 2021/7/23 15:14 20 | */ 21 | 22 | @Data 23 | @Builder 24 | @AllArgsConstructor 25 | @NoArgsConstructor 26 | public class BindingPermsVO implements java.io.Serializable { 27 | 28 | @NotNull(message = "ID不能为空!") 29 | private Long id; 30 | 31 | @NotNull(message = "权限列表不能为空!") 32 | @Size(min = 1, message = "权限列表最少是一个!") 33 | private Set items; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/BindingRolesVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | 5 | import javax.validation.constraints.NotNull; 6 | import javax.validation.constraints.Size; 7 | import java.util.Set; 8 | 9 | /** 10 | *

11 | * 用户绑定角色 12 | *

13 | * 14 | * @author Wang Chen Chen 15 | * @version 1.0 16 | * @date 2021/7/9 17:46 17 | */ 18 | 19 | @Getter 20 | @Setter 21 | @Builder 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @ToString 25 | public class BindingRolesVO { 26 | 27 | @NotNull(message = "用户ID不能为空!") 28 | private Long userId; 29 | 30 | @NotNull(message = "角色不能为空!") 31 | @Size(min = 1, message = "角色最少是一个!") 32 | private Set roles; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/ButtonVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | 5 | 6 | /** 7 | *

8 | * 用户登录成功后,返回的按钮权限 9 | *

10 | * 11 | * @author Wang Chen Chen <932560435@qq.com> 12 | * @version 2.0 13 | * @date 2019/4/18 11:45 14 | */ 15 | 16 | 17 | @Getter 18 | @Setter 19 | @ToString 20 | @Builder 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | public class ButtonVO implements java.io.Serializable { 24 | 25 | private String perms; 26 | 27 | private String title; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/LoginUserVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | import org.hibernate.validator.constraints.Length; 5 | 6 | import javax.validation.constraints.NotNull; 7 | 8 | 9 | /** 10 | *

11 | * 用户登录,参数传递 12 | *

13 | * 14 | * @author Wang Chen Chen <932560435@qq.com> 15 | * @version 2.0 16 | * @date 2019/4/18 11:45 17 | */ 18 | 19 | 20 | @Getter 21 | @Setter 22 | @ToString 23 | @AllArgsConstructor 24 | @NoArgsConstructor 25 | public class LoginUserVO implements java.io.Serializable { 26 | 27 | @NotNull(message = "用户名不能为空") 28 | @Length(min = 5, message = "用户名长度不能少于五位") 29 | private String username; 30 | 31 | @NotNull(message = "密码不能为空") 32 | @Length(min = 5, message = "密码长度不能少于五位") 33 | private String password; 34 | 35 | @NotNull(message = "验证码不能为空") 36 | @Length(min = 4, max = 4, message = "验证码长度是四位") 37 | private String codeText; 38 | 39 | @NotNull(message = "验证码 KEY 不能为空") 40 | private String codeKey; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/MenuVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import com.xaaef.robin.domain.TreeNode; 4 | import lombok.*; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | *

10 | * 菜单权限 11 | *

12 | * 13 | * @author Wang Chen Chen <932560435@qq.com> 14 | * @version 2.0 15 | * @date 2019/4/18 11:45 16 | */ 17 | 18 | @Getter 19 | @Setter 20 | @ToString 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @EqualsAndHashCode 24 | public class MenuVO implements java.io.Serializable, TreeNode { 25 | 26 | private Long id; 27 | 28 | private Long parentId; 29 | 30 | private String icon; 31 | 32 | private String perms; 33 | 34 | private Integer sort; 35 | 36 | private String title; 37 | 38 | private List children; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/ResetPasswordVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | import org.hibernate.validator.constraints.Length; 5 | 6 | import javax.validation.constraints.NotNull; 7 | 8 | /** 9 | *

10 | * 重置密码 11 | *

12 | * 13 | * @author Wang Chen Chen 14 | * @version 1.0 15 | * @date 2021/7/5 12:14 16 | */ 17 | 18 | 19 | @Getter 20 | @Setter 21 | @Builder 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @ToString 25 | public class ResetPasswordVO { 26 | 27 | /** 28 | * 用户ID 29 | * 30 | * @date 2021/5/21 15:43 31 | */ 32 | @NotNull(message = "用户ID不能为空!") 33 | private Long userId; 34 | 35 | /** 36 | * 新密码 37 | * 38 | * @date 2021/5/21 15:43 39 | */ 40 | @NotNull(message = "新密码不能为空!") 41 | @Length(min = 5, message = "新密码长度要大于6位!") 42 | private String newPwd; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/SysUserVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import com.xaaef.robin.entity.SysUser; 4 | import lombok.*; 5 | 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | 10 | /** 11 | *

12 | * 登录成功后,用户详细 Vo 模型 13 | *

14 | * 15 | * @author Wang Chen Chen<932560435@qq.com> 16 | * @version 2.0 17 | * @date 2019/12/12 23:29 18 | */ 19 | 20 | 21 | @Getter 22 | @Setter 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | public class SysUserVO extends SysUser implements java.io.Serializable { 26 | 27 | /** 28 | * 按钮 29 | */ 30 | private List buttons; 31 | 32 | /** 33 | * 菜单 34 | */ 35 | private List menus; 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/UpdatePasswordVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | import org.hibernate.validator.constraints.Length; 5 | 6 | import javax.validation.constraints.NotNull; 7 | 8 | /** 9 | *

10 | * 修改密码 11 | *

12 | * 13 | * @author Wang Chen Chen 14 | * @version 1.0 15 | * @date 2021/7/5 12:14 16 | */ 17 | 18 | @Getter 19 | @Setter 20 | @Builder 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @ToString 24 | public class UpdatePasswordVO { 25 | 26 | /** 27 | * 用户ID 28 | */ 29 | @NotNull(message = "用户ID不能为空!") 30 | private Long userId; 31 | 32 | /** 33 | * 旧密码 34 | */ 35 | @NotNull(message = "旧密码不能为空!") 36 | @Length(min = 5, message = "旧密码长度要大于6位!") 37 | private String oldPwd; 38 | 39 | /** 40 | * 新密码 41 | */ 42 | @NotNull(message = "新密码不能为空!") 43 | @Length(min = 5, message = "新密码长度要大于6位!") 44 | private String newPwd; 45 | 46 | /** 47 | * 确认密码 48 | */ 49 | @NotNull(message = "确认密码不能为空!") 50 | @Length(min = 5, message = "确认密码长度要大于6位!") 51 | private String confirmPwd; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/UpdatePermsVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import com.xaaef.robin.entity.SysPermission; 4 | import lombok.*; 5 | 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | /** 10 | *

11 | *

12 | * 13 | * @author Wang Chen Chen<932560435@qq.com> 14 | * @version 1.0.1 15 | * @date 2021/7/24 14:39 16 | */ 17 | 18 | @Getter 19 | @Setter 20 | @ToString 21 | @Builder 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | public class UpdatePermsVO implements java.io.Serializable { 25 | 26 | /** 27 | * 已经拥有的菜单 ID 28 | */ 29 | Set have; 30 | 31 | /** 32 | * 全部 菜单 ID 和 名称 33 | */ 34 | List all; 35 | 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/java/com/xaaef/robin/vo/UserIdAndNicknameVO.java: -------------------------------------------------------------------------------- 1 | package com.xaaef.robin.vo; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | *

7 | * 用户简单信息 Vo 模型 8 | *

9 | * 10 | * @author Wang Chen Chen<932560435@qq.com> 11 | * @version 2.0 12 | * @date 2019/12/12 23:29 13 | */ 14 | 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @EqualsAndHashCode 20 | public class UserIdAndNicknameVO implements java.io.Serializable { 21 | 22 | /** 23 | * 用户唯一id 24 | */ 25 | private Long userId; 26 | 27 | /** 28 | * 用户名 29 | */ 30 | private String username; 31 | 32 | /** 33 | * 头像 34 | */ 35 | private String avatar; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.cj.jdbc.Driver 4 | url: jdbc:mysql://localhost:3306/spring_boot_admin?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai 5 | username: ypj94klys0ge 6 | password: U4ux7kaXgS7jto1e 7 | type: com.zaxxer.hikari.HikariDataSource 8 | 9 | redis: 10 | database: 13 11 | host: 192.168.0.189 12 | password: mht123 13 | port: 6379 14 | timeout: 2000 15 | lettuce: 16 | pool: 17 | max-idle: 8 18 | min-idle: 0 19 | max-active: 8 20 | max-wait: -1ms 21 | cache: 22 | redis: 23 | use-key-prefix: true 24 | time-to-live: 60s 25 | 26 | # 七牛云文件上传配置 27 | qiniu: 28 | accessKey: d0JQ8Oyoz9wvRvbWzHTt 29 | secretKey: d0JQ8Oyoz9wvRvbWzHTt 30 | bucketName: 3b52 31 | fileDomain: https://images.baidu.com 32 | 33 | # mybatis-plus 打印 sql 配置 34 | mybatis-plus: 35 | configuration: 36 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 37 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | driver-class-name: com.mysql.cj.jdbc.Driver 4 | url: jdbc:mysql://localhost:3306/spring_boot_admin?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai 5 | username: ypj94klys0ge 6 | password: U4ux7kaXgS7jto1e 7 | type: com.zaxxer.hikari.HikariDataSource 8 | 9 | redis: 10 | database: 2 11 | host: localhost 12 | port: 6379 13 | timeout: 2000 14 | lettuce: 15 | pool: 16 | max-idle: 8 17 | min-idle: 0 18 | max-active: 8 19 | max-wait: -1ms 20 | cache: 21 | redis: 22 | use-key-prefix: true 23 | time-to-live: 60s 24 | 25 | knife4j: 26 | # 开启增强配置 27 | enable: true 28 | # 开启生产环境屏蔽 29 | production: true 30 | 31 | 32 | # 七牛云文件上传配置 33 | qiniu: 34 | accessKey: d0JQ8Oyoz9wvRvbWzHTt 35 | secretKey: d0JQ8Oyoz9wvRvbWzHTt 36 | bucketName: 3b52 37 | fileDomain: https://images.baidu.com 38 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 18888 3 | 4 | spring: 5 | profiles: 6 | active: dev 7 | application: 8 | name: spring-restful-api 9 | jackson: 10 | date-format: yyyy-MM-dd HH:mm:ss 11 | time-zone: GMT+8 12 | default-property-inclusion: non_null 13 | main: 14 | allow-bean-definition-overriding: true 15 | 16 | 17 | # mybatis-plus 自动配置 18 | mybatis-plus: 19 | mapper-locations: classpath:mapper/*.xml 20 | type-aliases-package: com.xaaef.robin.entity 21 | configuration: 22 | default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler 23 | 24 | 25 | # OAuth2.0 Server 配置 26 | jwt: 27 | token: 28 | token-expired: 7200 # 2小时 29 | exclude-path: 30 | - "/auth/sms/send" # 手机短信验证码 发送验证码 31 | - "/auth/sms" # 手机短信验证码 模式接口 32 | - "/auth/login" # 密码登录 33 | - "/auth/captcha/codes/**" # 验证码接口 34 | 35 | 36 | # knife4j 配置 37 | knife4j: 38 | enable: true 39 | production: false 40 | customize: 41 | swagger: 42 | title: 认证服务 43 | description: 认证服务 HTPP API 接口文档 44 | version: 3.0 45 | name: 王逗逗 46 | email: 932560435@qq.com 47 | url: https://xaaef.com 48 | service-url: http://localhost:18888/doc.html 49 | 50 | 51 | info: 52 | app: 53 | name: ${customize.swagger.title} 54 | description: ${customize.swagger.description} 55 | version: ${customize.swagger.version} 56 | 57 | 58 | management: 59 | endpoints: 60 | web: 61 | exposure: 62 | include: '*' 63 | endpoint: 64 | health: 65 | show-details: ALWAYS 66 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/images/watermark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/spring-restful-api/src/main/resources/images/watermark.png -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/ChinaAreaMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | area_code,`level`,parent_code, 23 | zip_code,city_code,`name`, 24 | short_name,merger_name,pinyin, 25 | lng,lat 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/LoginLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | message_id,grant_type,user_id, 23 | nickname,username,avatar, 24 | request_ip,address,os_name, 25 | browser,create_time 26 | 27 | 28 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/OperLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | message_id,title,oper_type, 27 | user_id,method,method_args, 28 | request_method,request_url,request_ip, 29 | address,response_result,status, 30 | error_log,time_cost,create_time 31 | 32 | 33 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysConfigMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | config_id,config_name,config_key, 21 | config_value,config_type,create_time, 22 | create_user,last_update_time,last_update_user 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysDeptMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | dept_id,parent_id,dept_name, 24 | leader,leader_mobile,sort, 25 | `description`,create_time,create_user, 26 | last_update_time,last_update_user 27 | 28 | 29 | 30 | 31 | insert into sys_dept_permission (dept_id, permission_id) values 32 | 33 | (#{id},#{item}) 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysDictDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | dict_code,dict_sort,dict_label, 24 | dict_value,type_key,css_class, 25 | list_class,is_default,create_user, 26 | create_time,last_update_user,last_update_time 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysDictTypeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | type_id,type_name,type_key, 20 | description,create_time,create_user, 21 | last_update_time,last_update_user 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysNoticeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | id,title, 24 | category,release_time,content, 25 | view_range,`status`,expired, 26 | create_time,create_user,last_update_time, 27 | last_update_user 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /spring-restful-api/src/main/resources/mapper/SysUserSocialMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | social_id,user_id,open_id, 17 | social_type,create_time 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /vue-admin-template/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | insert_final_newline = false 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /vue-admin-template/.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' 3 | 4 | # base api 5 | VUE_APP_BASE_API = 'http://localhost:18888' 6 | 7 | # npm 启动端口号 8 | port = 9528 9 | 10 | VUE_CLI_BABEL_TRANSPILE_MODULES = true 11 | 12 | 13 | -------------------------------------------------------------------------------- /vue-admin-template/.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' 3 | 4 | # base api 5 | VUE_APP_BASE_API = 'https://api.xaaef.com' 6 | -------------------------------------------------------------------------------- /vue-admin-template/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | src/assets 3 | public 4 | dist 5 | -------------------------------------------------------------------------------- /vue-admin-template/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | package-lock.json 8 | tests/**/coverage/ 9 | 10 | # Editor directories and files 11 | .idea 12 | .vscode 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | -------------------------------------------------------------------------------- /vue-admin-template/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 10 3 | script: npm run test 4 | notifications: 5 | email: false 6 | -------------------------------------------------------------------------------- /vue-admin-template/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app 4 | '@vue/cli-plugin-babel/preset' 5 | ], 6 | 'env': { 7 | 'development': { 8 | // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). 9 | // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. 10 | // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html 11 | 'plugins': ['dynamic-import-node'] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vue-admin-template/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 6 | 'jest-transform-stub', 7 | '^.+\\.jsx?$': 'babel-jest' 8 | }, 9 | moduleNameMapper: { 10 | '^@/(.*)$': '/src/$1' 11 | }, 12 | snapshotSerializers: ['jest-serializer-vue'], 13 | testMatch: [ 14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 15 | ], 16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], 17 | coverageDirectory: '/tests/unit/coverage', 18 | // 'collectCoverage': true, 19 | 'coverageReporters': [ 20 | 'lcov', 21 | 'text-summary' 22 | ], 23 | testURL: 'http://localhost/' 24 | } 25 | -------------------------------------------------------------------------------- /vue-admin-template/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "@/*": ["src/*"] 6 | } 7 | }, 8 | "exclude": ["node_modules", "dist"] 9 | } 10 | -------------------------------------------------------------------------------- /vue-admin-template/postcss.config.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | 'plugins': { 5 | // to edit target browsers: use "browserslist" field in package.json 6 | 'autoprefixer': {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /vue-admin-template/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/vue-admin-template/public/favicon.ico -------------------------------------------------------------------------------- /vue-admin-template/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= webpackConfig.name %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /vue-admin-template/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/chinaArea.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取分页信息 4 | export function getChinaAreaTree() { 5 | return request({ url: '/china/area/tree', method: 'get' }) 6 | } 7 | 8 | // 获取列表信息 9 | export function getChinaAreaAll(params) { 10 | return request({ url: '/china/area/all/' + params, method: 'get' }) 11 | } 12 | 13 | // 根据ID 查询单个区域信息 14 | export function getChinaAreaById(id) { 15 | return request({ url: '/china/area/' + id, method: 'get' }) 16 | } 17 | 18 | // 分页查询 19 | export function getChinaAreaPage(params) { 20 | return request({ url: '/china/area/query', method: 'get', params: params }) 21 | } 22 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/fileUpload.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 删除 oss 上的图片 4 | export function deleteImage(params) { 5 | return request({ url: '/upload/delete', method: 'delete', params: { url: params }}) 6 | } 7 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/sysDept.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 部门管理 4 | 5 | // 获取列表信息 6 | export function getDeptTree() { 7 | return request({ url: '/dept/tree', method: 'get' }) 8 | } 9 | 10 | // 获取列表信息 11 | export function getDeptPage(params) { 12 | return request({ url: '/dept/query', method: 'get', params: params }) 13 | } 14 | 15 | // 获取列表信息 16 | export function getDeptAll() { 17 | return request({ url: '/dept/all', method: 'get' }) 18 | } 19 | 20 | // 根据ID 查询单个部门信息 21 | export function getDeptById(params) { 22 | return request({ url: '/dept/' + params, method: 'get' }) 23 | } 24 | 25 | // 新增部门 26 | export function saveDept(params) { 27 | return request({ url: '/dept', method: 'post', data: params }) 28 | } 29 | 30 | // 修改部门 31 | export function updateDept(params) { 32 | return request({ url: '/dept', method: 'put', data: params }) 33 | } 34 | 35 | // 删除部门 36 | export function removeDeptById(params) { 37 | return request({ url: '/dept/' + params, method: 'delete' }) 38 | } 39 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/sysLog.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 系统日志 4 | 5 | // 获取操作日志 6 | export function getOperLogPage(params) { 7 | return request({ url: '/oper/log/query', method: 'get', params: params }) 8 | } 9 | 10 | // 删除操作日志 11 | export function removeOperLogById(params) { 12 | return request({ url: '/oper/log/batch', method: 'delete', data: params }) 13 | } 14 | 15 | // 获取登录日志 16 | export function getLoginLogPage(params) { 17 | return request({ url: '/login/log/query', method: 'get', params: params }) 18 | } 19 | 20 | // 删除登录日志 21 | export function removeLoginLogById(params) { 22 | return request({ url: '/login/log/batch', method: 'delete', data: params }) 23 | } 24 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/sysPermission.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 权限管理api 4 | 5 | // 获取分页信息 6 | export function getPermissionPage(params) { 7 | return request({ url: '/permission/query', method: 'get', params: params }) 8 | } 9 | 10 | // 获取树节点 11 | export function getPermissionTree(params) { 12 | return request({ url: '/permission/tree', method: 'get', params: params }) 13 | } 14 | 15 | // 获取列表信息 16 | export function getPermissionAll() { 17 | return request({ url: '/permission/all', method: 'get' }) 18 | } 19 | 20 | // 根据ID 查询单个权限信息 21 | export function getPermissionById(id) { 22 | return request({ url: '/permission/' + id, method: 'get' }) 23 | } 24 | 25 | // 新增权限 26 | export function savePermission(params) { 27 | return request({ url: '/permission', method: 'post', data: params }) 28 | } 29 | 30 | // 修改权限 31 | export function updatePermission(params) { 32 | return request({ url: '/permission', method: 'put', data: params }) 33 | } 34 | 35 | // 删除权限 36 | export function removePermissionById(id) { 37 | return request({ url: '/permission/' + id, method: 'delete' }) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /vue-admin-template/src/api/sysRole.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 角色管理 4 | 5 | // 获取分页信息 6 | export function getRolePage(params) { 7 | return request({ url: '/role/query', method: 'get', params: params }) 8 | } 9 | 10 | // 获取列表信息 11 | export function getRoleAll() { 12 | return request({ url: '/role/all', method: 'get' }) 13 | } 14 | 15 | // 根据ID 查询单个角色信息 16 | export function getRoleById(params) { 17 | return request({ url: '/role/' + params, method: 'get' }) 18 | } 19 | 20 | // 新增角色 21 | export function saveRole(params) { 22 | return request({ url: '/role', method: 'post', data: params }) 23 | } 24 | 25 | // 修改角色 26 | export function updateRole(params) { 27 | return request({ url: '/role', method: 'put', data: params }) 28 | } 29 | 30 | // 删除角色 31 | export function removeRoleById(params) { 32 | return request({ url: '/role/' + params, method: 'delete' }) 33 | } 34 | 35 | // 获取角色权限 36 | export function getRolePerms(params) { 37 | return request({ url: '/role/perms/' + params, method: 'get' }) 38 | } 39 | 40 | // 修改角色权限 41 | export function updateRolePerms(params) { 42 | console.log('params: ', params) 43 | return request({ url: '/role/perms', method: 'post', data: params }) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /vue-admin-template/src/assets/401_images/401.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/vue-admin-template/src/assets/401_images/401.gif -------------------------------------------------------------------------------- /vue-admin-template/src/assets/404_images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/vue-admin-template/src/assets/404_images/404.png -------------------------------------------------------------------------------- /vue-admin-template/src/assets/404_images/404_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/vue-admin-template/src/assets/404_images/404_cloud.png -------------------------------------------------------------------------------- /vue-admin-template/src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thousmile/spring-admin-vue/74cc1589e84db19c8906517e0f47694b27c6458d/vue-admin-template/src/assets/images/logo.png -------------------------------------------------------------------------------- /vue-admin-template/src/components/Charts/mixins/resize.js: -------------------------------------------------------------------------------- 1 | import { debounce } from '@/utils' 2 | 3 | export default { 4 | data() { 5 | return { 6 | $_sidebarElm: null, 7 | $_resizeHandler: null 8 | } 9 | }, 10 | mounted() { 11 | this.initListener() 12 | }, 13 | activated() { 14 | if (!this.$_resizeHandler) { 15 | // avoid duplication init 16 | this.initListener() 17 | } 18 | 19 | // when keep-alive chart activated, auto resize 20 | this.resize() 21 | }, 22 | beforeDestroy() { 23 | this.destroyListener() 24 | }, 25 | deactivated() { 26 | this.destroyListener() 27 | }, 28 | methods: { 29 | // use $_ for mixins properties 30 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 31 | $_sidebarResizeHandler(e) { 32 | if (e.propertyName === 'width') { 33 | this.$_resizeHandler() 34 | } 35 | }, 36 | initListener() { 37 | this.$_resizeHandler = debounce(() => { 38 | this.resize() 39 | }, 100) 40 | window.addEventListener('resize', this.$_resizeHandler) 41 | 42 | this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] 43 | this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) 44 | }, 45 | destroyListener() { 46 | window.removeEventListener('resize', this.$_resizeHandler) 47 | this.$_resizeHandler = null 48 | 49 | this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) 50 | }, 51 | resize() { 52 | const { chart } = this 53 | chart && chart.resize() 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/Copyright/index.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 47 | 48 | 60 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/DragSelect/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 50 | 51 | 66 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 32 | 33 | 45 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/Screenfull/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 50 | 51 | 61 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/ShowUserAvatar/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 65 | 66 | 69 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/SizeSelect/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 50 | -------------------------------------------------------------------------------- /vue-admin-template/src/components/SvgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 47 | 48 | 63 | -------------------------------------------------------------------------------- /vue-admin-template/src/directive/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '@/store' 3 | 4 | /** 注册全局指令**/ 5 | 6 | /** 7 | * 判断权限的指令 8 | * 用法: 添加 9 | */ 10 | Vue.directive('has', { 11 | inserted: function(el, binding, vnode) { 12 | if (!Vue.prototype.$_has(binding.value)) { 13 | el.parentNode.removeChild(el) 14 | } 15 | } 16 | }) 17 | 18 | // 权限检查方法 19 | Vue.prototype.$_has = function(value) { 20 | // 获取用户按钮权限 21 | let isExist = false 22 | // 当前用户所有的按钮列表 23 | const dynamicButtons = store.getters.buttons 24 | if (dynamicButtons === undefined || dynamicButtons === null || dynamicButtons.length < 1) { 25 | return isExist 26 | } 27 | dynamicButtons.forEach(button => { 28 | if (button.perms === value) { 29 | isExist = true 30 | return isExist 31 | } 32 | }) 33 | return isExist 34 | } 35 | 36 | /** 37 | * 修改标题的指令 38 | * 用法:
文章管理
39 | */ 40 | Vue.directive('title', { 41 | inserted: function(el, binding) { 42 | document.title = el.innerText 43 | el.remove() 44 | } 45 | }) 46 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/SvgIcon'// svg component 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const req = require.context('./svg', false, /\.svg$/) 8 | const requireAll = requireContext => requireContext.keys().map(requireContext) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/exit-fullscreen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/eye-open.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/eye.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/fullscreen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/message.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/money.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/password.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/peoples.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/pre.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/pre_dept.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/pre_role.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/pre_user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/size.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_dictionary.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_login_log.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_logs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_oper_log.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_swagger2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/sys_wechat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svg/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-admin-template/src/icons/svgo.yml: -------------------------------------------------------------------------------- 1 | # replace default config 2 | 3 | # multipass: true 4 | # full: true 5 | 6 | plugins: 7 | 8 | # - name 9 | # 10 | # or: 11 | # - name: false 12 | # - name: true 13 | # 14 | # or: 15 | # - name: 16 | # param1: 1 17 | # param2: 2 18 | 19 | - removeAttrs: 20 | attrs: 21 | - 'fill' 22 | - 'fill-rule' 23 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/AppMain.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 24 | 25 | 48 | 49 | 57 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/Sidebar/FixiOSBug.js: -------------------------------------------------------------------------------- 1 | export default { 2 | computed: { 3 | device() { 4 | return this.$store.state.app.device 5 | } 6 | }, 7 | mounted() { 8 | // In order to fix the click on menu on the ios device will trigger the mouseleave bug 9 | // https://github.com/PanJiaChen/vue-element-admin/issues/1135 10 | this.fixBugIniOS() 11 | }, 12 | methods: { 13 | fixBugIniOS() { 14 | const $subMenu = this.$refs.subMenu 15 | if ($subMenu) { 16 | const handleMouseleave = $subMenu.handleMouseleave 17 | $subMenu.handleMouseleave = (e) => { 18 | if (this.device === 'mobile') { 19 | return 20 | } 21 | handleMouseleave(e) 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/Sidebar/Item.vue: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/Sidebar/Link.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 37 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/Sidebar/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 58 | -------------------------------------------------------------------------------- /vue-admin-template/src/layout/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Navbar } from './Navbar' 2 | export { default as Sidebar } from './Sidebar' 3 | export { default as AppMain } from './AppMain' 4 | export { default as TagsView } from './TagsView/index.vue' -------------------------------------------------------------------------------- /vue-admin-template/src/layout/mixin/ResizeHandler.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | const { body } = document 4 | const WIDTH = 992 // refer to Bootstrap's responsive design 5 | 6 | export default { 7 | watch: { 8 | $route(route) { 9 | if (this.device === 'mobile' && this.sidebar.opened) { 10 | store.dispatch('app/closeSideBar', { withoutAnimation: false }) 11 | } 12 | } 13 | }, 14 | beforeMount() { 15 | window.addEventListener('resize', this.$_resizeHandler) 16 | }, 17 | beforeDestroy() { 18 | window.removeEventListener('resize', this.$_resizeHandler) 19 | }, 20 | mounted() { 21 | const isMobile = this.$_isMobile() 22 | if (isMobile) { 23 | store.dispatch('app/toggleDevice', 'mobile') 24 | store.dispatch('app/closeSideBar', { withoutAnimation: true }) 25 | } 26 | }, 27 | methods: { 28 | // use $_ for mixins properties 29 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 30 | $_isMobile() { 31 | const rect = body.getBoundingClientRect() 32 | return rect.width - 1 < WIDTH 33 | }, 34 | $_resizeHandler() { 35 | if (!document.hidden) { 36 | const isMobile = this.$_isMobile() 37 | store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') 38 | 39 | if (isMobile) { 40 | store.dispatch('app/closeSideBar', { withoutAnimation: true }) 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vue-admin-template/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import store from './store' 4 | import router from './router' 5 | import 'normalize.css/normalize.css' // A modern alternative to CSS resets 6 | import ElementUI from 'element-ui' 7 | import 'element-ui/lib/theme-chalk/index.css' 8 | import '@/styles/index.scss' // global css 9 | import '@/icons' // icon 10 | import '@/permission' // permission control 11 | import '@/directive' 12 | import { elementSize } from './settings' 13 | 14 | Vue.use(ElementUI, { size: store.getters.size || elementSize }) 15 | 16 | import * as filters from './filters' // global filters 17 | 18 | // 全局拦截器 filters 19 | Object.keys(filters).forEach(key => { 20 | Vue.filter(key, filters[key]) 21 | }) 22 | 23 | import ShowUserAvatar from '@/components/ShowUserAvatar' 24 | Vue.component('ShowUserAvatar', ShowUserAvatar) 25 | 26 | Vue.config.productionTip = false 27 | 28 | new Vue({ 29 | el: '#app', 30 | router, 31 | store, 32 | render: h => h(App) 33 | }) 34 | -------------------------------------------------------------------------------- /vue-admin-template/src/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * 项目名称 4 | */ 5 | title: '小鲨鱼后台管理', 6 | 7 | /** 8 | * 是否固定头部 9 | */ 10 | fixedHeader: true, 11 | 12 | /** 13 | * 是否显示logo 14 | */ 15 | sidebarLogo: true, 16 | 17 | /** 18 | * 是否显示 tagsView 19 | */ 20 | tagsView: true, 21 | 22 | /** 23 | * 默认: default 24 | * 中号: medium 25 | * 小号: small 26 | * 迷你: mini 27 | */ 28 | elementSize: 'small' 29 | 30 | } 31 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | sidebar: state => state.app.sidebar, 3 | size: state => state.app.size, 4 | device: state => state.app.device, 5 | settings: state => state.settings, 6 | visitedViews: state => state.tagsView.visitedViews, 7 | cachedViews: state => state.tagsView.cachedViews, 8 | 9 | errorLogs: state => state.errorLog.logs, 10 | 11 | token: state => state.user.token, 12 | nickname: state => state.user.nickname, 13 | username: state => state.user.username, 14 | avatar: state => state.user.avatar, 15 | userinfo: state => state.user.userinfo, 16 | 17 | roles: state => state.user.roles, 18 | // 从后台获取的用户菜单,没有解析过的 19 | menus: state => state.user.menus, 20 | // 从后台获取的用户 按钮权限 21 | buttons: state => state.user.buttons, 22 | 23 | // permission.js 24 | // 菜单路由,显示在页面上的 25 | menuRouters: state => state.permission.routers, 26 | // 当前用户的 动态菜单路由 27 | dynamicRouters: state => state.permission.dynamicRouters, 28 | 29 | // 全部用的用户信息,但是只有 头像和用户ID 以及用户名 30 | simpleUsers: state => state.user.simpleUsers 31 | 32 | } 33 | export default getters 34 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import getters from './getters' 4 | import app from './modules/app' 5 | import settings from './modules/settings' 6 | import user from './modules/user' 7 | import errorLog from './modules/errorLog' 8 | import permission from './modules/permission' 9 | import tagsView from './modules/tagsView' 10 | 11 | Vue.use(Vuex) 12 | 13 | const store = new Vuex.Store({ 14 | modules: { 15 | app, 16 | settings, 17 | user, 18 | errorLog, 19 | permission, 20 | tagsView 21 | }, 22 | getters 23 | }) 24 | 25 | export default store 26 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/modules/app.js: -------------------------------------------------------------------------------- 1 | const sidebarKey = 'sidebarStatus' 2 | const sizeKey = 'size' 3 | 4 | const state = { 5 | sidebar: { 6 | opened: localStorage.getItem(sidebarKey) ? !!+localStorage.getItem(sidebarKey) : true, 7 | withoutAnimation: false 8 | }, 9 | device: 'desktop', 10 | size: localStorage.getItem(sizeKey) || 'default' 11 | } 12 | 13 | const mutations = { 14 | TOGGLE_SIDEBAR: state => { 15 | state.sidebar.opened = !state.sidebar.opened 16 | state.sidebar.withoutAnimation = false 17 | if (state.sidebar.opened) { 18 | localStorage.setItem(sidebarKey, '1') 19 | } else { 20 | localStorage.setItem(sidebarKey, '0') 21 | } 22 | }, 23 | CLOSE_SIDEBAR: (state, withoutAnimation) => { 24 | localStorage.setItem(sidebarKey, '0') 25 | state.sidebar.opened = false 26 | state.sidebar.withoutAnimation = withoutAnimation 27 | }, 28 | TOGGLE_DEVICE: (state, device) => { 29 | state.device = device 30 | }, 31 | SET_SIZE: (state, size) => { 32 | state.size = size 33 | localStorage.setItem(sizeKey, size) 34 | } 35 | } 36 | 37 | const actions = { 38 | toggleSideBar({ commit }) { 39 | commit('TOGGLE_SIDEBAR') 40 | }, 41 | closeSideBar({ commit }, { withoutAnimation }) { 42 | commit('CLOSE_SIDEBAR', withoutAnimation) 43 | }, 44 | toggleDevice({ commit }, device) { 45 | commit('TOGGLE_DEVICE', device) 46 | }, 47 | setSize({ commit }, size) { 48 | commit('SET_SIZE', size) 49 | } 50 | } 51 | 52 | export default { 53 | namespaced: true, 54 | state, 55 | mutations, 56 | actions 57 | } 58 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/modules/errorLog.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | logs: [] 3 | } 4 | 5 | const mutations = { 6 | ADD_ERROR_LOG: (state, log) => { 7 | state.logs.push(log) 8 | }, 9 | CLEAR_ERROR_LOG: (state) => { 10 | state.logs.splice(0) 11 | } 12 | } 13 | 14 | const actions = { 15 | addErrorLog({ commit }, log) { 16 | commit('ADD_ERROR_LOG', log) 17 | }, 18 | clearErrorLog({ commit }) { 19 | commit('CLEAR_ERROR_LOG') 20 | } 21 | } 22 | 23 | export default { 24 | namespaced: true, 25 | state, 26 | mutations, 27 | actions 28 | } 29 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/modules/permission.js: -------------------------------------------------------------------------------- 1 | // store/permission.js 2 | import { asyncRouterMap, constantRoutes } from '@/router' 3 | 4 | /** 5 | * 6 | * @param {Array} userRouter 后台返回的用户权限json 7 | * @param {Array} allRouter 前端配置好的所有动态路由的集合 8 | * @return {Array} realRoutes 过滤后的路由 9 | */ 10 | 11 | export function recursionRouter(userRouter = [], allRouter = []) { 12 | var realRoutes = [] 13 | allRouter.forEach((v, i) => { 14 | userRouter.forEach((item, index) => { 15 | if (item.perms === v.meta.perms) { 16 | if (item.children && item.children.length > 0) { 17 | v.children = recursionRouter(item.children, v.children) 18 | } 19 | v.meta.title = item.title 20 | v.meta.icon = item.icon 21 | realRoutes.push(v) 22 | } 23 | }) 24 | }) 25 | return realRoutes 26 | } 27 | 28 | /** 29 | * 30 | * @param {Array} routes 用户过滤后的路由 31 | * 32 | * 递归为所有有子路由的路由设置第一个children.path为默认路由 33 | */ 34 | export function setDefaultRoute(routes) { 35 | routes.forEach((v, i) => { 36 | if (v.children && v.children.length > 0) { 37 | v.redirect = { name: v.children[0].name } 38 | setDefaultRoute(v.children) 39 | } 40 | }) 41 | } 42 | 43 | const permission = { 44 | state: { 45 | routers: constantRoutes, // 这是默认权限列表 比如404 500等路由 46 | dynamicRouters: [] // 这是通过后台获取的权利列表 47 | }, 48 | mutations: { 49 | SET_ROUTERS: (state, routers) => { 50 | state.dynamicRouters = routers 51 | state.routers = constantRoutes.concat(routers) 52 | } 53 | }, 54 | actions: { 55 | toVueRoutes({ commit }, data) { 56 | return new Promise(resolve => { 57 | const allRouter = recursionRouter(data, asyncRouterMap) 58 | commit('SET_ROUTERS', allRouter) 59 | resolve(allRouter) 60 | }) 61 | } 62 | } 63 | } 64 | 65 | export default permission 66 | -------------------------------------------------------------------------------- /vue-admin-template/src/store/modules/settings.js: -------------------------------------------------------------------------------- 1 | import { fixedHeader, sidebarLogo, tagsView, title } from '@/settings' 2 | 3 | const state = { 4 | fixedHeader: fixedHeader, 5 | sidebarTitle: title, 6 | sidebarLogo: sidebarLogo, 7 | tagsView: tagsView 8 | } 9 | 10 | const mutations = { 11 | CHANGE_SETTING: (state, { key, value }) => { 12 | if (state.hasOwnProperty(key)) { 13 | state[key] = value 14 | } 15 | } 16 | } 17 | 18 | const actions = { 19 | changeSetting({ commit }, data) { 20 | commit('CHANGE_SETTING', data) 21 | } 22 | } 23 | 24 | export default { 25 | namespaced: true, 26 | state, 27 | mutations, 28 | actions 29 | } 30 | 31 | -------------------------------------------------------------------------------- /vue-admin-template/src/styles/element-ui.scss: -------------------------------------------------------------------------------- 1 | // cover some element-ui styles 2 | 3 | .el-breadcrumb__inner, 4 | .el-breadcrumb__inner a { 5 | font-weight: 400 !important; 6 | } 7 | 8 | .el-upload { 9 | input[type="file"] { 10 | display: none !important; 11 | } 12 | } 13 | 14 | .el-upload__input { 15 | display: none; 16 | } 17 | 18 | 19 | // to fixed https://github.com/ElemeFE/element/issues/2461 20 | .el-dialog { 21 | transform: none; 22 | left: 0; 23 | position: relative; 24 | margin: 0 auto; 25 | } 26 | 27 | // refine element ui upload 28 | .upload-container { 29 | .el-upload { 30 | width: 100%; 31 | 32 | .el-upload-dragger { 33 | width: 100%; 34 | height: 200px; 35 | } 36 | } 37 | } 38 | 39 | // dropdown 40 | .el-dropdown-menu { 41 | a { 42 | display: block 43 | } 44 | } 45 | 46 | // to fix el-date-picker css style 47 | .el-range-separator { 48 | box-sizing: content-box; 49 | } 50 | -------------------------------------------------------------------------------- /vue-admin-template/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import './variables.scss'; 2 | @import './mixin.scss'; 3 | @import './transition.scss'; 4 | @import './element-ui.scss'; 5 | @import './sidebar.scss'; 6 | 7 | body { 8 | height: 100%; 9 | -moz-osx-font-smoothing: grayscale; 10 | -webkit-font-smoothing: antialiased; 11 | text-rendering: optimizeLegibility; 12 | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; 13 | } 14 | 15 | label { 16 | font-weight: 700; 17 | } 18 | 19 | html { 20 | height: 100%; 21 | box-sizing: border-box; 22 | } 23 | 24 | #app { 25 | height: 100%; 26 | } 27 | 28 | *, 29 | *:before, 30 | *:after { 31 | box-sizing: inherit; 32 | } 33 | 34 | a:focus, 35 | a:active { 36 | outline: none; 37 | } 38 | 39 | a, 40 | a:focus, 41 | a:hover { 42 | cursor: pointer; 43 | color: inherit; 44 | text-decoration: none; 45 | } 46 | 47 | div:focus { 48 | outline: none; 49 | } 50 | 51 | .clearfix { 52 | &:after { 53 | visibility: hidden; 54 | display: block; 55 | font-size: 0; 56 | content: " "; 57 | clear: both; 58 | height: 0; 59 | } 60 | } 61 | 62 | // main-container global css 63 | .app-container { 64 | padding: 10px; 65 | margin-top: 10px; 66 | } 67 | 68 | // main-container global css 69 | .wrapper { 70 | margin-top: 20px; 71 | } 72 | 73 | .avatar-wrapper { 74 | cursor: pointer; 75 | position: relative; 76 | 77 | .user-avatar { 78 | width: 50px; 79 | height: 50px; 80 | border-radius: 10px; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /vue-admin-template/src/styles/mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix { 2 | &:after { 3 | content: ""; 4 | display: table; 5 | clear: both; 6 | } 7 | } 8 | 9 | @mixin scrollBar { 10 | &::-webkit-scrollbar-track-piece { 11 | background: #d3dce6; 12 | } 13 | 14 | &::-webkit-scrollbar { 15 | width: 6px; 16 | } 17 | 18 | &::-webkit-scrollbar-thumb { 19 | background: #99a9bf; 20 | border-radius: 20px; 21 | } 22 | } 23 | 24 | @mixin relative { 25 | position: relative; 26 | width: 100%; 27 | height: 100%; 28 | } 29 | -------------------------------------------------------------------------------- /vue-admin-template/src/styles/transition.scss: -------------------------------------------------------------------------------- 1 | // global transition css 2 | 3 | /* fade */ 4 | .fade-enter-active, 5 | .fade-leave-active { 6 | transition: opacity 0.28s; 7 | } 8 | 9 | .fade-enter, 10 | .fade-leave-active { 11 | opacity: 0; 12 | } 13 | 14 | /* fade-transform */ 15 | .fade-transform-leave-active, 16 | .fade-transform-enter-active { 17 | transition: all .5s; 18 | } 19 | 20 | .fade-transform-enter { 21 | opacity: 0; 22 | transform: translateX(-30px); 23 | } 24 | 25 | .fade-transform-leave-to { 26 | opacity: 0; 27 | transform: translateX(30px); 28 | } 29 | 30 | /* breadcrumb transition */ 31 | .breadcrumb-enter-active, 32 | .breadcrumb-leave-active { 33 | transition: all .5s; 34 | } 35 | 36 | .breadcrumb-enter, 37 | .breadcrumb-leave-active { 38 | opacity: 0; 39 | transform: translateX(20px); 40 | } 41 | 42 | .breadcrumb-move { 43 | transition: all .5s; 44 | } 45 | 46 | .breadcrumb-leave-active { 47 | position: absolute; 48 | } 49 | -------------------------------------------------------------------------------- /vue-admin-template/src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | // sidebar 2 | $menuText:#bfcbd9; 3 | $menuActiveText:#409EFF; 4 | $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951 5 | 6 | $menuBg:#304156; 7 | $menuHover:#263445; 8 | 9 | $subMenuBg:#1f2d3d; 10 | $subMenuHover:#001528; 11 | 12 | $sideBarWidth: 210px; 13 | 14 | // the :export directive is the magic sauce for webpack 15 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 16 | :export { 17 | menuText: $menuText; 18 | menuActiveText: $menuActiveText; 19 | subMenuActiveText: $subMenuActiveText; 20 | menuBg: $menuBg; 21 | menuHover: $menuHover; 22 | subMenuBg: $subMenuBg; 23 | subMenuHover: $subMenuHover; 24 | sideBarWidth: $sideBarWidth; 25 | } 26 | -------------------------------------------------------------------------------- /vue-admin-template/src/utils/auth.js: -------------------------------------------------------------------------------- 1 | // token 值 在 Cookie 中key名称 2 | const TokenKey = 'TokenValue' 3 | 4 | export function getToken() { 5 | return localStorage.getItem(TokenKey) 6 | } 7 | 8 | export function setToken(token) { 9 | return localStorage.setItem(TokenKey, token) 10 | } 11 | 12 | export function removeToken() { 13 | return localStorage.removeItem(TokenKey) 14 | } 15 | -------------------------------------------------------------------------------- /vue-admin-template/src/utils/get-page-title.js: -------------------------------------------------------------------------------- 1 | import defaultSettings from '@/settings' 2 | 3 | export default function getPageTitle(pageTitle) { 4 | if (pageTitle) { 5 | return `${pageTitle} - ${defaultSettings.title}` 6 | } 7 | return `${defaultSettings.title}` 8 | } 9 | -------------------------------------------------------------------------------- /vue-admin-template/src/utils/open-window.js: -------------------------------------------------------------------------------- 1 | /** 2 | *Created by PanJiaChen on 16/11/29. 3 | * @param {Sting} url 4 | * @param {Sting} title 5 | * @param {Number} w 6 | * @param {Number} h 7 | */ 8 | export default function openWindow(url, title, w, h) { 9 | // Fixes dual-screen position Most browsers Firefox 10 | const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left 11 | const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top 12 | 13 | const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width 14 | const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height 15 | 16 | const left = ((width / 2) - (w / 2)) + dualScreenLeft 17 | const top = ((height / 2) - (h / 2)) + dualScreenTop 18 | const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left) 19 | 20 | // Puts focus on the newWindow 21 | if (window.focus) { 22 | newWindow.focus() 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/dashboard/components/mixins/resize.js: -------------------------------------------------------------------------------- 1 | import { debounce } from '@/utils' 2 | 3 | export default { 4 | data() { 5 | return { 6 | $_sidebarElm: null, 7 | $_resizeHandler: null 8 | } 9 | }, 10 | mounted() { 11 | this.$_resizeHandler = debounce(() => { 12 | if (this.chart) { 13 | this.chart.resize() 14 | } 15 | }, 100) 16 | this.$_initResizeEvent() 17 | this.$_initSidebarResizeEvent() 18 | }, 19 | beforeDestroy() { 20 | this.$_destroyResizeEvent() 21 | this.$_destroySidebarResizeEvent() 22 | }, 23 | // to fixed bug when cached by keep-alive 24 | // https://github.com/PanJiaChen/vue-element-admin/issues/2116 25 | activated() { 26 | this.$_initResizeEvent() 27 | this.$_initSidebarResizeEvent() 28 | }, 29 | deactivated() { 30 | this.$_destroyResizeEvent() 31 | this.$_destroySidebarResizeEvent() 32 | }, 33 | methods: { 34 | // use $_ for mixins properties 35 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 36 | $_initResizeEvent() { 37 | window.addEventListener('resize', this.$_resizeHandler) 38 | }, 39 | $_destroyResizeEvent() { 40 | window.removeEventListener('resize', this.$_resizeHandler) 41 | }, 42 | $_sidebarResizeHandler(e) { 43 | if (e.propertyName === 'width') { 44 | this.$_resizeHandler() 45 | } 46 | }, 47 | $_initSidebarResizeEvent() { 48 | this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] 49 | this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) 50 | }, 51 | $_destroySidebarResizeEvent() { 52 | this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/sys/dictionary/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/sys/notice/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/sys/swagger/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /vue-admin-template/src/views/sys/wechat/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/components/Hamburger.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import Hamburger from '@/components/Hamburger/index.vue' 3 | describe('Hamburger.vue', () => { 4 | it('toggle click', () => { 5 | const wrapper = shallowMount(Hamburger) 6 | const mockFn = jest.fn() 7 | wrapper.vm.$on('toggleClick', mockFn) 8 | wrapper.find('.hamburger').trigger('click') 9 | expect(mockFn).toBeCalled() 10 | }) 11 | it('prop isActive', () => { 12 | const wrapper = shallowMount(Hamburger) 13 | wrapper.setProps({ isActive: true }) 14 | expect(wrapper.contains('.is-active')).toBe(true) 15 | wrapper.setProps({ isActive: false }) 16 | expect(wrapper.contains('.is-active')).toBe(false) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/components/SvgIcon.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import SvgIcon from '@/components/SvgIcon/index.vue' 3 | describe('SvgIcon.vue', () => { 4 | it('iconClass', () => { 5 | const wrapper = shallowMount(SvgIcon, { 6 | propsData: { 7 | iconClass: 'test' 8 | } 9 | }) 10 | expect(wrapper.find('use').attributes().href).toBe('#icon-test') 11 | }) 12 | it('className', () => { 13 | const wrapper = shallowMount(SvgIcon, { 14 | propsData: { 15 | iconClass: 'test' 16 | } 17 | }) 18 | expect(wrapper.classes().length).toBe(1) 19 | wrapper.setProps({ className: 'test' }) 20 | expect(wrapper.classes().includes('test')).toBe(true) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/utils/formatTime.spec.js: -------------------------------------------------------------------------------- 1 | import { formatTime } from '@/utils/index.js' 2 | 3 | describe('Utils:formatTime', () => { 4 | const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" 5 | const retrofit = 5 * 1000 6 | 7 | it('ten digits timestamp', () => { 8 | expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分') 9 | }) 10 | it('test now', () => { 11 | expect(formatTime(+new Date() - 1)).toBe('刚刚') 12 | }) 13 | it('less two minute', () => { 14 | expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前') 15 | }) 16 | it('less two hour', () => { 17 | expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前') 18 | }) 19 | it('less one day', () => { 20 | expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前') 21 | }) 22 | it('more than one day', () => { 23 | expect(formatTime(d)).toBe('7月13日17时54分') 24 | }) 25 | it('format', () => { 26 | expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') 27 | expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') 28 | expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/utils/param2Obj.spec.js: -------------------------------------------------------------------------------- 1 | import { param2Obj } from '@/utils/index.js' 2 | describe('Utils:param2Obj', () => { 3 | const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95' 4 | 5 | it('param2Obj test', () => { 6 | expect(param2Obj(url)).toEqual({ 7 | name: 'bill', 8 | age: '29', 9 | sex: '1', 10 | field: window.btoa('test'), 11 | key: '测试' 12 | }) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/utils/parseTime.spec.js: -------------------------------------------------------------------------------- 1 | import { parseTime } from '@/utils/index.js' 2 | 3 | describe('Utils:parseTime', () => { 4 | const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" 5 | it('timestamp', () => { 6 | expect(parseTime(d)).toBe('2018-07-13 17:54:01') 7 | }) 8 | it('timestamp string', () => { 9 | expect(parseTime((d + ''))).toBe('2018-07-13 17:54:01') 10 | }) 11 | it('ten digits timestamp', () => { 12 | expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01') 13 | }) 14 | it('new Date', () => { 15 | expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01') 16 | }) 17 | it('format', () => { 18 | expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') 19 | expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') 20 | expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') 21 | }) 22 | it('get the day of the week', () => { 23 | expect(parseTime(d, '{a}')).toBe('五') // 星期五 24 | }) 25 | it('get the day of the week', () => { 26 | expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日 27 | }) 28 | it('empty argument', () => { 29 | expect(parseTime()).toBeNull() 30 | }) 31 | 32 | it('null', () => { 33 | expect(parseTime(null)).toBeNull() 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /vue-admin-template/tests/unit/utils/validate.spec.js: -------------------------------------------------------------------------------- 1 | import { validUsername, isExternal } from '@/utils/validate.js' 2 | 3 | describe('Utils:validate', () => { 4 | it('validUsername', () => { 5 | expect(validUsername('admin')).toBe(true) 6 | expect(validUsername('editor')).toBe(true) 7 | expect(validUsername('xxxx')).toBe(false) 8 | }) 9 | it('isExternal', () => { 10 | expect(isExternal('https://github.com/PanJiaChen/vue-element-admin')).toBe(true) 11 | expect(isExternal('http://github.com/PanJiaChen/vue-element-admin')).toBe(true) 12 | expect(isExternal('github.com/PanJiaChen/vue-element-admin')).toBe(false) 13 | expect(isExternal('/dashboard')).toBe(false) 14 | expect(isExternal('./dashboard')).toBe(false) 15 | expect(isExternal('dashboard')).toBe(false) 16 | }) 17 | }) 18 | --------------------------------------------------------------------------------