├── .gitignore ├── 0.http ├── 0.登录.http └── http-client.env.json ├── 1.data └── soccer.mv.db ├── LICENSE ├── README.md ├── document └── img │ └── 1543051392883.jpg ├── pom.xml ├── soccer-angular-webapp ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.js ├── .stylelintrc ├── LICENSE ├── README-zh_CN.md ├── README.md ├── _mock │ ├── README.md │ ├── _user.ts │ └── index.ts ├── angular.json ├── karma.conf.js ├── ng-alain.json ├── package.json ├── pom.xml ├── proxy.conf.js ├── src │ ├── app │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── common │ │ │ └── auth-value.ts │ │ ├── core │ │ │ ├── README.md │ │ │ ├── core.module.ts │ │ │ ├── index.ts │ │ │ ├── module-import-guard.ts │ │ │ ├── net │ │ │ │ └── default.interceptor.ts │ │ │ └── startup │ │ │ │ └── startup.service.ts │ │ ├── global-config.module.ts │ │ ├── layout │ │ │ ├── basic │ │ │ │ ├── README.md │ │ │ │ ├── basic.component.html │ │ │ │ ├── basic.component.ts │ │ │ │ └── widgets │ │ │ │ │ ├── clear-storage.component.ts │ │ │ │ │ ├── fullscreen.component.ts │ │ │ │ │ ├── search.component.ts │ │ │ │ │ └── user.component.ts │ │ │ ├── blank │ │ │ │ ├── README.md │ │ │ │ └── blank.component.ts │ │ │ ├── layout.module.ts │ │ │ └── passport │ │ │ │ ├── passport.component.html │ │ │ │ ├── passport.component.less │ │ │ │ └── passport.component.ts │ │ ├── routes │ │ │ ├── dashboard │ │ │ │ ├── dashboard.component.html │ │ │ │ └── dashboard.component.ts │ │ │ ├── exception │ │ │ │ ├── exception-routing.module.ts │ │ │ │ ├── exception.component.ts │ │ │ │ ├── exception.module.ts │ │ │ │ └── trigger.component.ts │ │ │ ├── passport │ │ │ │ ├── callback.component.ts │ │ │ │ ├── lock │ │ │ │ │ ├── lock.component.html │ │ │ │ │ ├── lock.component.less │ │ │ │ │ └── lock.component.ts │ │ │ │ ├── login │ │ │ │ │ ├── login.component.html │ │ │ │ │ ├── login.component.less │ │ │ │ │ └── login.component.ts │ │ │ │ ├── register-result │ │ │ │ │ ├── register-result.component.html │ │ │ │ │ └── register-result.component.ts │ │ │ │ └── register │ │ │ │ │ ├── register.component.html │ │ │ │ │ ├── register.component.less │ │ │ │ │ └── register.component.ts │ │ │ ├── routes-routing.module.ts │ │ │ ├── routes.module.ts │ │ │ └── sys │ │ │ │ ├── auth │ │ │ │ ├── auth.component.html │ │ │ │ ├── auth.component.ts │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ └── sys-auth.service.ts │ │ │ │ ├── config │ │ │ │ ├── config.component.html │ │ │ │ └── config.component.ts │ │ │ │ ├── dept │ │ │ │ ├── dept.component.html │ │ │ │ ├── dept.component.ts │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ └── sys-dept.service.ts │ │ │ │ ├── log │ │ │ │ ├── log.component.html │ │ │ │ └── log.component.ts │ │ │ │ ├── menu │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ ├── menu.component.html │ │ │ │ ├── menu.component.ts │ │ │ │ └── sys-menu.service.ts │ │ │ │ ├── profile │ │ │ │ ├── profile-basic │ │ │ │ │ ├── profile-basic.component.html │ │ │ │ │ └── profile-basic.component.ts │ │ │ │ ├── profile-safety │ │ │ │ │ ├── profile-safety.component.html │ │ │ │ │ └── profile-safety.component.ts │ │ │ │ ├── profile.component.html │ │ │ │ └── profile.component.ts │ │ │ │ ├── role │ │ │ │ ├── auth │ │ │ │ │ ├── auth.component.html │ │ │ │ │ └── auth.component.ts │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ ├── menu │ │ │ │ │ ├── menu.component.html │ │ │ │ │ └── menu.component.ts │ │ │ │ ├── role.component.html │ │ │ │ └── role.component.ts │ │ │ │ ├── sys-routing.module.ts │ │ │ │ ├── sys.module.ts │ │ │ │ └── user │ │ │ │ ├── edit │ │ │ │ ├── edit.component.html │ │ │ │ └── edit.component.ts │ │ │ │ ├── user.component.html │ │ │ │ └── user.component.ts │ │ └── shared │ │ │ ├── index.ts │ │ │ ├── json-schema │ │ │ ├── README.md │ │ │ ├── json-schema.module.ts │ │ │ └── test │ │ │ │ └── test.widget.ts │ │ │ ├── shared-delon.module.ts │ │ │ ├── shared-zorro.module.ts │ │ │ ├── shared.module.ts │ │ │ ├── st-widget │ │ │ ├── README.md │ │ │ └── st-widget.module.ts │ │ │ └── utils │ │ │ ├── format-username.ts │ │ │ ├── treeUtils.ts │ │ │ └── yuan.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── color.less │ │ ├── logo-color.svg │ │ ├── logo-full.svg │ │ ├── logo.svg │ │ ├── style.compact.css │ │ ├── style.dark.css │ │ ├── tmp │ │ │ ├── app-data.json │ │ │ └── img │ │ │ │ └── avatar.jpg │ │ └── zorro.svg │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── style-icons-auto.ts │ ├── style-icons.ts │ ├── styles.less │ ├── styles │ │ ├── index.less │ │ └── theme.less │ ├── test.ts │ └── typings.d.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── yarn.lock └── soccer-server ├── pom.xml └── src └── main ├── java └── com │ └── dqv5 │ └── soccer │ ├── Application.java │ ├── common │ ├── AuthValue.java │ ├── ConfigValue.java │ ├── Pageable.java │ ├── RestReturn.java │ ├── RestReturnEntity.java │ ├── TreeNode.java │ └── TreeNodeType.java │ ├── config │ ├── AutoFillMetaObjectHandler.java │ ├── ControllerAspect.java │ ├── GlobalExceptionHandler.java │ ├── InitDataRunner.java │ ├── ResourceHandlerConfig.java │ ├── SoccerProperties.java │ ├── SwaggerConfig.java │ └── SystemConfig.java │ ├── exception │ └── CommonRuntimeException.java │ ├── file │ ├── AmazonS3Configuration.java │ ├── AmazonS3FileHandler.java │ ├── AmazonS3Properties.java │ ├── DiskFileHandler.java │ ├── DiskProperties.java │ ├── FileStoreType.java │ └── IntegrationFileHandler.java │ ├── mapper │ ├── SysAuthFolderMapper.java │ ├── SysAuthMapper.java │ ├── SysConfigMapper.java │ ├── SysDeptMapper.java │ ├── SysFileMapper.java │ ├── SysLogMapper.java │ ├── SysMenuMapper.java │ ├── SysRoleAuthMapper.java │ ├── SysRoleMapper.java │ ├── SysRoleMenuMapper.java │ ├── SysUserDeptMapper.java │ ├── SysUserMapper.java │ └── SysUserRoleMapper.java │ ├── pojo │ ├── AbstractBaseVO.java │ ├── ChangePasswordParam.java │ ├── FileUploadDto.java │ ├── PageParam.java │ ├── SysAuth.java │ ├── SysAuthFolder.java │ ├── SysDept.java │ ├── SysFile.java │ ├── SysInfo.java │ ├── SysMenu.java │ ├── SysRole.java │ ├── SysUser.java │ ├── UpdateProfileParam.java │ └── UserQueryParam.java │ ├── security │ ├── AuthUser.java │ ├── CustomPasswordEncoder.java │ ├── JWTAuthenticationEntryPoint.java │ ├── JWTAuthenticationFilter.java │ ├── JWTAuthorizationTokenFilter.java │ ├── SecurityConfig.java │ └── UserDetailsServiceImpl.java │ ├── service │ ├── InitDataService.java │ ├── SysAuthService.java │ ├── SysConfigService.java │ ├── SysDeptService.java │ ├── SysFileService.java │ ├── SysLogService.java │ ├── SysMenuService.java │ ├── SysProfileService.java │ ├── SysRoleService.java │ ├── SysUserService.java │ └── impl │ │ ├── InitDataServiceImpl.java │ │ ├── SysAuthServiceImpl.java │ │ ├── SysConfigServiceImpl.java │ │ ├── SysDeptServiceImpl.java │ │ ├── SysFileServiceImpl.java │ │ ├── SysLogServiceImpl.java │ │ ├── SysMenuServiceImpl.java │ │ ├── SysProfileServiceImpl.java │ │ ├── SysRoleServiceImpl.java │ │ └── SysUserServiceImpl.java │ ├── table │ ├── AbstractBaseTable.java │ ├── SysAuthFolderTable.java │ ├── SysAuthTable.java │ ├── SysConfigTable.java │ ├── SysDeptTable.java │ ├── SysFileTable.java │ ├── SysLogTable.java │ ├── SysMenuTable.java │ ├── SysRoleAuthTable.java │ ├── SysRoleMenuTable.java │ ├── SysRoleTable.java │ ├── SysUserDeptTable.java │ ├── SysUserRoleTable.java │ └── SysUserTable.java │ ├── utils │ ├── AspectUtil.java │ ├── DqFileUtils.java │ ├── IPUtils.java │ ├── IpIpFreeUtils.java │ ├── JsonUtil.java │ ├── JwtTokenUtil.java │ ├── MediaFileUtils.java │ ├── SecurityUtils.java │ ├── SpringUtils.java │ └── TreeUtils.java │ └── web │ ├── PageController.java │ ├── SysAuthController.java │ ├── SysConfigController.java │ ├── SysController.java │ ├── SysDeptController.java │ ├── SysFileController.java │ ├── SysLogController.java │ ├── SysMenuController.java │ ├── SysProfileController.java │ ├── SysRoleController.java │ └── SysUserController.java └── resources ├── application-h2.yml ├── application-pg.yml ├── application-prod.yml ├── application.yml ├── files └── ipipfree.ipdb ├── liquibase └── common │ ├── changes │ └── 10000.xml │ └── db.changelog-master.xml ├── mapper ├── mybatis-config.xml └── sqlMap │ ├── SysAuthMapper.xml │ ├── SysDeptMapper.xml │ ├── SysMenuMapper.xml │ ├── SysRoleMapper.xml │ └── SysUserMapper.xml └── static └── web ├── 272.a66059b130dca387.js ├── 3rdpartylicenses.txt ├── 559.c5385e94f2a6a3a4.js ├── assets ├── color.less ├── logo-color.svg ├── logo-full.svg ├── logo.svg ├── style.compact.css ├── style.dark.css ├── tmp │ ├── app-data.json │ └── img │ │ └── avatar.jpg └── zorro.svg ├── favicon.ico ├── index.html ├── main.1678d8c113e3e971.js ├── polyfills.8f101dea817be423.js ├── runtime.a7630984665b46f1.js └── styles.5009e02597ba8a66.css /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | relbel.xml 4 | node_modules/ 5 | /soccer-server/target/ 6 | -------------------------------------------------------------------------------- /0.http/0.登录.http: -------------------------------------------------------------------------------- 1 | ### 登录 2 | POST {{server}}/api/login 3 | Content-Type: application/x-www-form-urlencoded 4 | 5 | username=admin&password=123456 6 | 7 | ### 获取用户信息 8 | GET {{server}}/api/user 9 | Authorization: bearer {{token}} 10 | -------------------------------------------------------------------------------- /0.http/http-client.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "local": { 3 | "server": "http://localhost:8080", 4 | "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInVzZXJuYW1lIjoiYWRtaW4iLCJpYXQiOjE3MDIxMzMzNjMsImV4cCI6MTcwMjczODE2M30.2XTu74_wLlYfCTuJkvZKEepYFQwzVY8QaeRjhTOvJis" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /1.data/soccer.mv.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/1.data/soccer.mv.db -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2024 杜谦 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-angular 2 | 3 | 基于 Spring Boot + Angular 的前后端分离框架。 4 | 5 | ## 项目简介 6 | 7 | * 这是一套基于 Spring Boot + MyBatis-Plus + Angular 的前后端分离框架。 8 | * 后端使用 Maven 对项目进行管理,提高项目的易开发性、扩展性。 9 | * 前端使用 Angular 构建单页面应用,UI 采用 [NG-ZORRO](https://ng.ant.design/)。 10 | 11 | ## 主要功能(开发中...) 12 | 13 | ### 电脑端 14 | 15 | - [x] 登录、退出登录 16 | - [x] 部门管理 17 | - [x] 用户管理 18 | - [x] 菜单管理 19 | - [x] 角色管理 20 | - [x] 权限管理 21 | - [x] 日志管理 22 | - [x] 系统配置管理 23 | - [x] 个人信息、修改密码 24 | 25 | ## 依赖 26 | 27 | ### java后端依赖环境 28 | 29 | * Maven 3 30 | * Java 8 31 | * Spring Boot 2.7.18 32 | * PostgreSQL 33 | 34 | ### 前端依赖环境 35 | 36 | * Node.js 37 | * npm & yarn 38 | * Angular 17 39 | * ng-zorro-antd 17 40 | * ng-alain 17 41 | 42 | ## 工程说明 43 | 44 | 完善中... 45 | 46 | ## 本地运行 47 | 48 | 1. 启动后台项目: 使用idea启动,或打包后 `java -jar xxx.jar` 49 | 2. 启动前台项目: `npm start` 50 | 3. 电脑打开页面:`http://localhost:4200` 51 | 52 | ## 效果图 53 | 54 | ![](document/img/1543051392883.jpg) 55 | 56 | ## 相关链接 57 | 58 | * [Spring Boot](https://spring.io/projects/spring-boot): spring的全新框架,简化新Spring应用的初始搭建以及开发过程。 59 | * [Liquibase](https://liquibase.org/): 一个开源数据库架构更改管理解决方案,使您能够轻松管理数据库更改的修订 60 | * [Angular](https://angular.cn/): 一套前端单页面应用开发框架。 61 | * [Ant design](https://ant.design/): 一个服务于企业级产品的设计体系。 62 | * [ng-zorro](https://ng.ant.design/): Ant Design 的 Angular 实现 63 | * [ng-alain](https://ng-alain.com/): 一个基于 Antd 中后台前端解决方案 64 | 65 | ## TODO 66 | 67 | - [ ] 前端遇到接口异常时,按钮的 loading 状态要取消 68 | 69 | ## License 70 | 71 | [MIT License](./LICENSE) 72 | 73 | -------------------------------------------------------------------------------- /document/img/1543051392883.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/document/img/1543051392883.jpg -------------------------------------------------------------------------------- /soccer-angular-webapp/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /soccer-angular-webapp/.eslintignore: -------------------------------------------------------------------------------- 1 | _cli-tpl/ 2 | dist/ 3 | coverage/ 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Dependency directories 13 | node_modules/ 14 | 15 | # TypeScript cache 16 | *.tsbuildinfo 17 | 18 | # Optional npm cache directory 19 | .npm 20 | 21 | # Optional eslint cache 22 | .eslintcache 23 | 24 | # Yarn Integrity file 25 | .yarn-integrity 26 | 27 | # dotenv environment variables file 28 | .env 29 | .env.test 30 | 31 | .cache/ 32 | 33 | # yarn v2 34 | .yarn 35 | 36 | **/src/index.html -------------------------------------------------------------------------------- /soccer-angular-webapp/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | /target/ 44 | -------------------------------------------------------------------------------- /soccer-angular-webapp/.nvmrc: -------------------------------------------------------------------------------- 1 | 12.14.1 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/.prettierignore: -------------------------------------------------------------------------------- 1 | # add files you wish to ignore here 2 | **/*.md 3 | **/*.svg 4 | **/test.ts 5 | 6 | .stylelintrc 7 | .prettierrc 8 | 9 | src/assets/* 10 | src/index.html 11 | node_modules/ 12 | .vscode/ 13 | coverage/ 14 | dist/ 15 | package.json 16 | tslint.json 17 | 18 | _cli-tpl/**/* 19 | -------------------------------------------------------------------------------- /soccer-angular-webapp/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | useTabs: false, 4 | printWidth: 140, 5 | tabWidth: 2, 6 | semi: true, 7 | htmlWhitespaceSensitivity: 'strict', 8 | arrowParens: 'avoid', 9 | bracketSpacing: true, 10 | proseWrap: 'preserve', 11 | trailingComma: 'none', 12 | endOfLine: 'lf' 13 | }; 14 | -------------------------------------------------------------------------------- /soccer-angular-webapp/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard", 4 | "stylelint-config-rational-order" 5 | ], 6 | "customSyntax": "postcss-less", 7 | "plugins": [ 8 | "stylelint-order", 9 | "stylelint-declaration-block-no-ignored-properties" 10 | ], 11 | "rules": { 12 | "function-no-unknown": null, 13 | "no-descending-specificity": null, 14 | "plugin/declaration-block-no-ignored-properties": true, 15 | "selector-type-no-unknown": [ 16 | true, 17 | { 18 | "ignoreTypes": [ 19 | "/^g2-/", 20 | "/^nz-/", 21 | "/^app-/" 22 | ] 23 | } 24 | ], 25 | "selector-pseudo-element-no-unknown": [ 26 | true, 27 | { 28 | "ignorePseudoElements": [ 29 | "ng-deep" 30 | ] 31 | } 32 | ], 33 | "import-notation": "string" 34 | }, 35 | "ignoreFiles": [ 36 | "src/assets/**/*" 37 | ] 38 | } -------------------------------------------------------------------------------- /soccer-angular-webapp/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-present 卡色 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /soccer-angular-webapp/_mock/README.md: -------------------------------------------------------------------------------- 1 | [Document](https://ng-alain.com/mock) 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/_mock/index.ts: -------------------------------------------------------------------------------- 1 | export * from './_user'; 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/portal'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /soccer-angular-webapp/ng-alain.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/ng-alain/schema.json", 3 | "theme": { 4 | "list": [ 5 | { 6 | "theme": "dark" 7 | }, 8 | { 9 | "theme": "compact" 10 | } 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /soccer-angular-webapp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.dqv5 7 | soccer 8 | 0.2.0 9 | 10 | 11 | soccer-angular-webapp 12 | 0.2.0 13 | jar 14 | soccer-angular-webapp 15 | 16 | 17 | -------------------------------------------------------------------------------- /soccer-angular-webapp/proxy.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * For more configuration, please refer to https://angular.io/guide/build#proxying-to-a-backend-server 3 | * 4 | * 更多配置描述请参考 https://angular.cn/guide/build#proxying-to-a-backend-server 5 | * 6 | * Note: The proxy is only valid for real requests, Mock does not actually generate requests, so the priority of Mock will be higher than the proxy 7 | */ 8 | module.exports = { 9 | /** 10 | * The following means that all requests are directed to the backend `https://localhost:9000/` 11 | */ 12 | '/api/': { 13 | target: 'http://localhost:8080/', 14 | secure: false, // Ignore invalid SSL certificates 15 | changeOrigin: true 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, OnInit, Renderer2 } from '@angular/core'; 2 | import { NavigationEnd, NavigationError, RouteConfigLoadStart, Router } from '@angular/router'; 3 | import { TitleService, VERSION as VERSION_ALAIN, stepPreloader } from '@delon/theme'; 4 | import { environment } from '@env/environment'; 5 | import { NzModalService } from 'ng-zorro-antd/modal'; 6 | import { VERSION as VERSION_ZORRO } from 'ng-zorro-antd/version'; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | template: ` ` 11 | }) 12 | export class AppComponent implements OnInit { 13 | private donePreloader = stepPreloader(); 14 | constructor( 15 | el: ElementRef, 16 | renderer: Renderer2, 17 | private router: Router, 18 | private titleSrv: TitleService, 19 | private modalSrv: NzModalService 20 | ) { 21 | renderer.setAttribute(el.nativeElement, 'ng-alain-version', VERSION_ALAIN.full); 22 | renderer.setAttribute(el.nativeElement, 'ng-zorro-version', VERSION_ZORRO.full); 23 | } 24 | 25 | ngOnInit(): void { 26 | let configLoad = false; 27 | this.router.events.subscribe(ev => { 28 | if (ev instanceof RouteConfigLoadStart) { 29 | configLoad = true; 30 | } 31 | if (configLoad && ev instanceof NavigationError) { 32 | this.modalSrv.confirm({ 33 | nzTitle: `提醒`, 34 | nzContent: environment.production ? `应用可能已发布新版本,请点击刷新才能生效。` : `无法加载路由:${ev.url}`, 35 | nzCancelDisabled: false, 36 | nzOkText: '刷新', 37 | nzCancelText: '忽略', 38 | nzOnOk: () => location.reload() 39 | }); 40 | } 41 | if (ev instanceof NavigationEnd) { 42 | this.donePreloader(); 43 | this.titleSrv.setTitle(); 44 | this.modalSrv.closeAll(); 45 | } 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/common/auth-value.ts: -------------------------------------------------------------------------------- 1 | export class AuthValue { 2 | static SYS_USER_QUERY = "sys_user_query"; 3 | static SYS_USER_INSERT = "sys_user_insert"; 4 | static SYS_USER_UPDATE = "sys_user_update"; 5 | static SYS_USER_DELETE = "sys_user_delete"; 6 | 7 | static SYS_ROLE_QUERY = "sys_role_query"; 8 | static SYS_ROLE_INSERT = "sys_role_insert"; 9 | static SYS_ROLE_UPDATE = "sys_role_update"; 10 | static SYS_ROLE_DELETE = "sys_role_delete"; 11 | 12 | static SYS_MENU_QUERY = "sys_menu_query"; 13 | static SYS_MENU_INSERT = "sys_menu_insert"; 14 | static SYS_MENU_UPDATE = "sys_menu_update"; 15 | static SYS_MENU_DELETE = "sys_menu_delete"; 16 | 17 | static SYS_AUTH_QUERY = "sys_auth_query"; 18 | static SYS_AUTH_INSERT = "sys_auth_insert"; 19 | static SYS_AUTH_UPDATE = "sys_auth_update"; 20 | static SYS_AUTH_DELETE = "sys_auth_delete"; 21 | 22 | static SYS_DEPT_QUERY = "sys_dept_query"; 23 | static SYS_DEPT_INSERT = "sys_dept_insert"; 24 | static SYS_DEPT_UPDATE = "sys_dept_update"; 25 | static SYS_DEPT_DELETE = "sys_dept_delete"; 26 | 27 | static SYS_CONFIG_QUERY = "sys_config_query"; 28 | static SYS_CONFIG_SET = "sys_config_set"; 29 | 30 | static SYS_LOG_QUERY = "sys_log_query"; 31 | 32 | static SYS_RE_INIT_DATA = "sys_re_init_data"; 33 | } 34 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/core/README.md: -------------------------------------------------------------------------------- 1 | ### CoreModule 2 | 3 | **应** 仅只留 `providers` 属性。 4 | 5 | **作用:** 一些通用服务,例如:用户消息、HTTP数据访问。 6 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule, Optional, SkipSelf} from '@angular/core'; 2 | 3 | import {throwIfAlreadyLoaded} from './module-import-guard'; 4 | 5 | @NgModule({ 6 | providers: [] 7 | }) 8 | export class CoreModule { 9 | constructor(@Optional() @SkipSelf() parentModule: CoreModule) { 10 | throwIfAlreadyLoaded(parentModule, 'CoreModule'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/core/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export * from './module-import-guard'; 3 | export * from './net/default.interceptor'; 4 | export * from './startup/startup.service'; 5 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/core/module-import-guard.ts: -------------------------------------------------------------------------------- 1 | // https://angular.io/guide/styleguide#style-04-12 2 | export function throwIfAlreadyLoaded(parentModule: any, moduleName: string): void { 3 | if (parentModule) { 4 | throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/basic/README.md: -------------------------------------------------------------------------------- 1 | [Document](https://ng-alain.com/theme/layout-default) 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/basic/basic.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {SettingsService, User} from '@delon/theme'; 3 | import {LayoutDefaultOptions} from '@delon/theme/layout-default'; 4 | import {environment} from '@env/environment'; 5 | 6 | @Component({ 7 | selector: 'layout-basic', 8 | templateUrl: './basic.component.html', 9 | }) 10 | export class LayoutBasicComponent { 11 | options: LayoutDefaultOptions = { 12 | logoExpanded: `./assets/logo-full.svg`, 13 | logoCollapsed: `./assets/logo.svg`, 14 | }; 15 | searchToggleStatus = false; 16 | showSettingDrawer = !environment.production; 17 | 18 | get user(): User { 19 | return this.settings.user; 20 | } 21 | 22 | constructor(private settings: SettingsService) { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/basic/widgets/clear-storage.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core'; 2 | import { NzMessageService } from 'ng-zorro-antd/message'; 3 | import { NzModalService } from 'ng-zorro-antd/modal'; 4 | 5 | @Component({ 6 | selector: 'header-clear-storage', 7 | template: ` 8 | 9 | 清理本地缓存 10 | `, 11 | host: { 12 | '[class.flex-1]': 'true' 13 | }, 14 | changeDetection: ChangeDetectionStrategy.OnPush 15 | }) 16 | export class HeaderClearStorageComponent { 17 | constructor(private modalSrv: NzModalService, private messageSrv: NzMessageService) {} 18 | 19 | @HostListener('click') 20 | _click(): void { 21 | this.modalSrv.confirm({ 22 | nzTitle: 'Make sure clear all local storage?', 23 | nzOnOk: () => { 24 | localStorage.clear(); 25 | this.messageSrv.success('Clear Finished!'); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/basic/widgets/fullscreen.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core'; 2 | import screenfull from 'screenfull'; 3 | 4 | @Component({ 5 | selector: 'header-fullscreen', 6 | template: ` 7 | 8 | {{ status ? '退出全屏' : '全屏' }} 9 | `, 10 | host: { 11 | '[class.flex-1]': 'true' 12 | }, 13 | changeDetection: ChangeDetectionStrategy.OnPush 14 | }) 15 | export class HeaderFullScreenComponent { 16 | status = false; 17 | 18 | @HostListener('window:resize') 19 | _resize(): void { 20 | this.status = screenfull.isFullscreen; 21 | } 22 | 23 | @HostListener('click') 24 | _click(): void { 25 | if (screenfull.isEnabled) { 26 | screenfull.toggle(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/basic/widgets/user.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth'; 4 | import { SettingsService, User } from '@delon/theme'; 5 | 6 | @Component({ 7 | selector: 'header-user', 8 | template: ` 9 |
10 | 11 | {{ user.name }} 12 |
13 | 14 |
15 |
16 | 17 | 个人中心 18 |
19 |
20 | 21 | 触发错误 22 |
23 |
  • 24 |
    25 | 26 | 退出登录 27 |
    28 |
    29 |
    30 | `, 31 | changeDetection: ChangeDetectionStrategy.OnPush 32 | }) 33 | export class HeaderUserComponent { 34 | get user(): User { 35 | return this.settings.user; 36 | } 37 | 38 | constructor(private settings: SettingsService, private router: Router, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {} 39 | 40 | logout(): void { 41 | this.tokenService.clear(); 42 | this.router.navigateByUrl(this.tokenService.login_url!); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/blank/README.md: -------------------------------------------------------------------------------- 1 | [Document](https://ng-alain.com/theme/blank) 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/blank/blank.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'layout-blank', 5 | template: ` `, 6 | host: { 7 | '[class.alain-blank]': 'true' 8 | } 9 | }) 10 | export class LayoutBlankComponent {} 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/passport/passport.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | 6 | {{ app.name }} 7 |
    8 |
    {{ app.description }}
    9 |
    10 | 11 | 12 | Copyright 13 | 2022 14 | duqian 15 | 16 |
    17 |
    18 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/layout/passport/passport.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Inject, OnInit} from '@angular/core'; 2 | import {DA_SERVICE_TOKEN, ITokenService} from '@delon/auth'; 3 | import {SettingsService} from "@delon/theme"; 4 | 5 | @Component({ 6 | selector: 'layout-passport', 7 | templateUrl: './passport.component.html', 8 | styleUrls: ['./passport.component.less'] 9 | }) 10 | export class LayoutPassportComponent implements OnInit { 11 | app: any = {}; 12 | links = [ 13 | { 14 | title: '帮助', 15 | href: '' 16 | }, 17 | { 18 | title: '隐私', 19 | href: '' 20 | }, 21 | { 22 | title: '条款', 23 | href: '' 24 | } 25 | ]; 26 | 27 | constructor(@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService, 28 | private settingsService: SettingsService) { 29 | } 30 | 31 | ngOnInit(): void { 32 | this.app = this.settingsService.getApp(); 33 | this.tokenService.clear(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/dashboard/dashboard.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/dashboard/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-dashboard', 5 | templateUrl: './dashboard.component.html', 6 | changeDetection: ChangeDetectionStrategy.OnPush 7 | }) 8 | export class DashboardComponent {} 9 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/exception/exception-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | import { ExceptionComponent } from './exception.component'; 5 | import { ExceptionTriggerComponent } from './trigger.component'; 6 | 7 | const routes: Routes = [ 8 | { path: '403', component: ExceptionComponent, data: { type: 403 } }, 9 | { path: '404', component: ExceptionComponent, data: { type: 404 } }, 10 | { path: '500', component: ExceptionComponent, data: { type: 500 } }, 11 | { path: 'trigger', component: ExceptionTriggerComponent } 12 | ]; 13 | 14 | @NgModule({ 15 | imports: [RouterModule.forChild(routes)], 16 | exports: [RouterModule] 17 | }) 18 | export class ExceptionRoutingModule {} 19 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/exception/exception.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { ExceptionType } from '@delon/abc/exception'; 4 | 5 | @Component({ 6 | selector: 'app-exception', 7 | template: ` `, 8 | changeDetection: ChangeDetectionStrategy.OnPush 9 | }) 10 | export class ExceptionComponent { 11 | get type(): ExceptionType { 12 | return this.route.snapshot.data['type']; 13 | } 14 | 15 | constructor(private route: ActivatedRoute) {} 16 | } 17 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/exception/exception.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { ExceptionModule as DelonExceptionModule } from '@delon/abc/exception'; 4 | import { NzButtonModule } from 'ng-zorro-antd/button'; 5 | import { NzCardModule } from 'ng-zorro-antd/card'; 6 | 7 | import { ExceptionRoutingModule } from './exception-routing.module'; 8 | import { ExceptionComponent } from './exception.component'; 9 | import { ExceptionTriggerComponent } from './trigger.component'; 10 | 11 | @NgModule({ 12 | imports: [CommonModule, DelonExceptionModule, NzButtonModule, NzCardModule, ExceptionRoutingModule], 13 | declarations: [ExceptionComponent, ExceptionTriggerComponent] 14 | }) 15 | export class ExceptionModule {} 16 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/exception/trigger.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject } from '@angular/core'; 2 | import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth'; 3 | import { _HttpClient } from '@delon/theme'; 4 | 5 | @Component({ 6 | selector: 'exception-trigger', 7 | template: ` 8 |
    9 | 10 | 11 | 12 | 13 |
    14 | ` 15 | }) 16 | export class ExceptionTriggerComponent { 17 | types = [401, 403, 404, 500]; 18 | 19 | constructor(private http: _HttpClient, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {} 20 | 21 | go(type: number): void { 22 | this.http.get(`/api/${type}`).subscribe(); 23 | } 24 | 25 | refresh(): void { 26 | this.tokenService.set({ token: 'invalid-token' }); 27 | // 必须提供一个后端地址,无法通过 Mock 来模拟 28 | this.http.post(`https://localhost:5001/auth`).subscribe( 29 | res => console.warn('成功', res), 30 | err => { 31 | console.log('最后结果失败', err); 32 | } 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/callback.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { SocialService } from '@delon/auth'; 4 | import { SettingsService } from '@delon/theme'; 5 | 6 | @Component({ 7 | selector: 'app-callback', 8 | template: ``, 9 | providers: [SocialService] 10 | }) 11 | export class CallbackComponent implements OnInit { 12 | type = ''; 13 | 14 | constructor(private socialService: SocialService, private settingsSrv: SettingsService, private route: ActivatedRoute) {} 15 | 16 | ngOnInit(): void { 17 | this.type = this.route.snapshot.params['type']; 18 | this.mockModel(); 19 | } 20 | 21 | private mockModel(): void { 22 | const info = { 23 | token: '123456789', 24 | name: 'cipchk', 25 | email: `${this.type}@${this.type}.com`, 26 | id: 10000, 27 | time: +new Date() 28 | }; 29 | this.settingsSrv.setUser({ 30 | ...this.settingsSrv.user, 31 | ...info 32 | }); 33 | this.socialService.callback(info); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/lock/lock.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 | 5 |
    6 |
    7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
    20 |
    21 |
    22 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/lock/lock.component.less: -------------------------------------------------------------------------------- 1 | :host ::ng-deep { 2 | .ant-card-body { 3 | position: relative; 4 | margin-top: 80px; 5 | } 6 | 7 | .avatar { 8 | position: absolute; 9 | top: -20px; 10 | left: 50%; 11 | margin-left: -20px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/lock/lock.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject } from '@angular/core'; 2 | import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; 3 | import { Router } from '@angular/router'; 4 | import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth'; 5 | import { SettingsService, User } from '@delon/theme'; 6 | 7 | @Component({ 8 | selector: 'passport-lock', 9 | templateUrl: './lock.component.html', 10 | styleUrls: ['./lock.component.less'] 11 | }) 12 | export class UserLockComponent { 13 | f: UntypedFormGroup; 14 | 15 | get user(): User { 16 | return this.settings.user; 17 | } 18 | 19 | constructor( 20 | fb: UntypedFormBuilder, 21 | @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService, 22 | private settings: SettingsService, 23 | private router: Router 24 | ) { 25 | this.f = fb.group({ 26 | password: [null, Validators.required] 27 | }); 28 | } 29 | 30 | submit(): void { 31 | for (const i in this.f.controls) { 32 | this.f.controls[i].markAsDirty(); 33 | this.f.controls[i].updateValueAndValidity(); 34 | } 35 | if (this.f.valid) { 36 | console.log('Valid!'); 37 | console.log(this.f.value); 38 | this.tokenService.set({ 39 | token: '123' 40 | }); 41 | this.router.navigate(['dashboard']); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/login/login.component.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 忘记密码 27 | 28 | 29 | 30 | 33 | 34 |
    35 |
    36 | 其他登录方式 37 | 39 | 41 | 42 | 注册账户 43 |
    44 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/login/login.component.less: -------------------------------------------------------------------------------- 1 | @import '@delon/theme/index'; 2 | 3 | :host { 4 | display: block; 5 | width: 368px; 6 | margin: 0 auto; 7 | 8 | ::ng-deep { 9 | .ant-tabs .ant-tabs-bar { 10 | margin-bottom: 24px; 11 | text-align: center; 12 | border-bottom: 0; 13 | } 14 | 15 | .ant-tabs-tab { 16 | font-size: 16px; 17 | line-height: 24px; 18 | } 19 | 20 | .ant-input-affix-wrapper .ant-input:not(:first-child) { 21 | padding-left: 4px; 22 | } 23 | 24 | .icon { 25 | margin-left: 16px; 26 | color: rgb(0 0 0 / 20%); 27 | font-size: 24px; 28 | vertical-align: middle; 29 | cursor: pointer; 30 | transition: color 0.3s; 31 | 32 | &:hover { 33 | color: @primary-color; 34 | } 35 | } 36 | 37 | .other { 38 | margin-top: 24px; 39 | line-height: 22px; 40 | text-align: left; 41 | 42 | nz-tooltip { 43 | vertical-align: middle; 44 | } 45 | 46 | .register { 47 | float: right; 48 | } 49 | } 50 | } 51 | } 52 | 53 | [data-theme='dark'] { 54 | :host ::ng-deep { 55 | .icon { 56 | color: rgb(255 255 255 / 20%); 57 | 58 | &:hover { 59 | color: #fff; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/register-result/register-result.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 | 你的账户:{{email}} 注册成功 5 |
    6 |
    7 | 10 | 13 |
    14 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/register-result/register-result.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { NzMessageService } from 'ng-zorro-antd/message'; 4 | 5 | @Component({ 6 | selector: 'passport-register-result', 7 | templateUrl: './register-result.component.html' 8 | }) 9 | export class UserRegisterResultComponent { 10 | params = { email: '' }; 11 | email = ''; 12 | constructor(route: ActivatedRoute, public msg: NzMessageService) { 13 | this.params.email = this.email = route.snapshot.queryParams['email'] || 'ng-alain@example.com'; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/passport/register/register.component.less: -------------------------------------------------------------------------------- 1 | @import '@delon/theme/index'; 2 | 3 | :host { 4 | display: block; 5 | width: 368px; 6 | margin: 0 auto; 7 | 8 | ::ng-deep { 9 | h3 { 10 | margin-bottom: 20px; 11 | font-size: 16px; 12 | } 13 | 14 | .submit { 15 | width: 50%; 16 | } 17 | 18 | .login { 19 | float: right; 20 | line-height: @btn-height-lg; 21 | } 22 | } 23 | } 24 | 25 | ::ng-deep { 26 | .register-password-cdk { 27 | .success, 28 | .warning, 29 | .error { 30 | transition: color 0.3s; 31 | } 32 | 33 | .success { 34 | color: @success-color; 35 | } 36 | 37 | .warning { 38 | color: @warning-color; 39 | } 40 | 41 | .error { 42 | color: @error-color; 43 | } 44 | 45 | .progress-pass > .progress { 46 | .ant-progress-bg { 47 | background-color: @warning-color; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/routes.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, Type } from '@angular/core'; 2 | import { SharedModule } from '@shared'; 3 | 4 | // dashboard pages 5 | import { DashboardComponent } from './dashboard/dashboard.component'; 6 | // single pages 7 | import { CallbackComponent } from './passport/callback.component'; 8 | import { UserLockComponent } from './passport/lock/lock.component'; 9 | // passport pages 10 | import { UserLoginComponent } from './passport/login/login.component'; 11 | import { UserRegisterResultComponent } from './passport/register-result/register-result.component'; 12 | import { UserRegisterComponent } from './passport/register/register.component'; 13 | import { RouteRoutingModule } from './routes-routing.module'; 14 | 15 | const COMPONENTS: Array> = [ 16 | DashboardComponent, 17 | // passport pages 18 | UserLoginComponent, 19 | UserRegisterComponent, 20 | UserRegisterResultComponent, 21 | // single pages 22 | CallbackComponent, 23 | UserLockComponent 24 | ]; 25 | 26 | @NgModule({ 27 | imports: [SharedModule, RouteRoutingModule], 28 | declarations: COMPONENTS 29 | }) 30 | export class RoutesModule {} 31 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/auth/auth.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/auth/edit/edit.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/auth/edit/edit.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {SFSchema, SFSelectWidgetSchema, SFUISchema} from '@delon/form'; 3 | import {_HttpClient} from '@delon/theme'; 4 | import {NzMessageService} from 'ng-zorro-antd/message'; 5 | import {NzModalRef} from 'ng-zorro-antd/modal'; 6 | import {SysAuthService} from "../sys-auth.service"; 7 | import {map, Observable} from "rxjs"; 8 | 9 | @Component({ 10 | selector: 'app-sys-auth-edit', 11 | templateUrl: './edit.component.html', 12 | }) 13 | export class SysAuthEditComponent implements OnInit { 14 | record: any = {}; 15 | i: any; 16 | schema: SFSchema = { 17 | properties: { 18 | authName: {type: 'string', title: '权限名称', maxLength: 15}, 19 | authValue: {type: 'string', title: '权限标识'}, 20 | authFolderId: { 21 | type: 'string', title: '所属目录', ui: { 22 | widget: 'select', 23 | asyncData: () => this.loadAuthFolders() 24 | } as SFSelectWidgetSchema 25 | }, 26 | }, 27 | required: ['authName', 'authValue'], 28 | }; 29 | ui: SFUISchema = { 30 | '*': { 31 | spanLabelFixed: 100, 32 | grid: {span: 24}, 33 | }, 34 | $authName: { 35 | widget: 'string' 36 | }, 37 | }; 38 | 39 | constructor( 40 | private modal: NzModalRef, 41 | private msgSrv: NzMessageService, 42 | private sysAuthService: SysAuthService, 43 | public http: _HttpClient, 44 | ) { 45 | } 46 | 47 | ngOnInit(): void { 48 | console.log('init edit', this.record); 49 | if (this.record) { 50 | this.i = { 51 | ...this.record 52 | } 53 | } 54 | } 55 | 56 | private loadAuthFolders(): Observable { 57 | return this.sysAuthService.loadAuthFolders() 58 | .pipe( 59 | map(data => data.map((item: any) => ({ 60 | value: item.authFolderId, 61 | label: item.authFolderName 62 | })) 63 | ) 64 | ) 65 | } 66 | 67 | save(value: any): void { 68 | const api = this.record.authId != null ? '/api/auth/update' : '/api/auth/insert'; 69 | this.http.post(api, value).subscribe(res => { 70 | this.msgSrv.success(res.msg); 71 | this.modal.close(true); 72 | }); 73 | } 74 | 75 | close(): void { 76 | this.modal.destroy(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/auth/sys-auth.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {_HttpClient} from '@delon/theme'; 3 | import {map, Observable} from "rxjs"; 4 | 5 | @Injectable() 6 | export class SysAuthService { 7 | 8 | constructor(private http: _HttpClient) { 9 | } 10 | 11 | loadAuthFolders(): Observable { 12 | return this.http.get('/api/auth/folders').pipe( 13 | map(res => res.data) 14 | ) 15 | } 16 | 17 | loadAuthTree(): Observable { 18 | return this.http.get('/api/auth/tree').pipe( 19 | map(res => res.data) 20 | ) 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/config/config.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/dept/dept.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 部门名称 12 | 部门编码 13 | 排序 14 | 操作 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | {{ item.deptName }} 28 | 29 | {{ item.deptCode }} 30 | {{ item.displayIndex }} 31 | 32 | 编辑 33 | 删除 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/dept/edit/edit.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/dept/edit/edit.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {SFSchema, SFUISchema} from '@delon/form'; 3 | import {_HttpClient} from '@delon/theme'; 4 | import {NzMessageService} from 'ng-zorro-antd/message'; 5 | import {NzModalRef} from 'ng-zorro-antd/modal'; 6 | import {SysDeptService} from "../sys-dept.service"; 7 | import {SFTreeSelectWidgetSchema} from '@delon/form/widgets/tree-select'; 8 | 9 | @Component({ 10 | selector: 'app-sys-dept-edit', 11 | templateUrl: './edit.component.html', 12 | }) 13 | export class SysDeptEditComponent implements OnInit { 14 | record: any = {}; 15 | i: any; 16 | schema: SFSchema = { 17 | properties: { 18 | deptName: {type: 'string', title: '部门名称', maxLength: 50}, 19 | deptCode: {type: 'string', title: '部门编码', maxLength: 50}, 20 | parentId: { 21 | type: 'string', title: '上级部门', 22 | ui: { 23 | widget: 'tree-select', 24 | asyncData: () => this.sysDeptService.loadDeptTree() 25 | } as SFTreeSelectWidgetSchema, 26 | }, 27 | displayIndex: {type: 'number', title: '排序'}, 28 | }, 29 | required: ['deptName', 'deptCode'], 30 | }; 31 | ui: SFUISchema = { 32 | '*': { 33 | spanLabelFixed: 100, 34 | grid: {span: 24}, 35 | }, 36 | $deptName: { 37 | widget: 'string' 38 | }, 39 | }; 40 | 41 | constructor( 42 | private modal: NzModalRef, 43 | private msgSrv: NzMessageService, 44 | public http: _HttpClient, 45 | private sysDeptService: SysDeptService 46 | ) { 47 | } 48 | 49 | ngOnInit(): void { 50 | console.log(this.record); 51 | if (this.record.deptId) { 52 | this.http.get(`/api/dept/info/${this.record.deptId}`).subscribe(res => this.i = res.data); 53 | } 54 | } 55 | 56 | save(value: any): void { 57 | const api = this.record.deptId ? '/api/dept/update' : '/api/dept/insert'; 58 | this.http.post(api, value).subscribe(res => { 59 | this.msgSrv.success(res.msg); 60 | this.modal.close(true); 61 | }); 62 | } 63 | 64 | close(): void { 65 | this.modal.destroy(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/dept/sys-dept.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {_HttpClient} from '@delon/theme'; 3 | import {map, Observable} from "rxjs"; 4 | 5 | @Injectable() 6 | export class SysDeptService { 7 | 8 | constructor(private http: _HttpClient) { 9 | } 10 | 11 | loadDeptTree(): Observable { 12 | return this.http.get('/api/dept/tree').pipe( 13 | map(res => res.data) 14 | ) 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/log/log.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/log/log.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, ViewChild} from '@angular/core'; 2 | import {STColumn, STComponent} from '@delon/abc/st'; 3 | import {SFSchema} from '@delon/form'; 4 | import {ModalHelper, _HttpClient} from '@delon/theme'; 5 | 6 | @Component({ 7 | selector: 'app-sys-log', 8 | templateUrl: './log.component.html', 9 | }) 10 | export class SysLogComponent implements OnInit { 11 | url = `/api/log/list`; 12 | searchSchema: SFSchema = { 13 | properties: { 14 | username: { 15 | type: 'string', 16 | title: '账号' 17 | }, 18 | nickName: { 19 | type: 'string', 20 | title: '昵称' 21 | } 22 | } 23 | }; 24 | @ViewChild('st') private readonly st!: STComponent; 25 | columns: STColumn[] = [ 26 | {title: '编号', type: 'no'}, 27 | {title: '账号', index: 'username'}, 28 | {title: '昵称', index: 'nickName'}, 29 | {title: '请求地址', index: 'requestUrl'}, 30 | {title: '耗时', type: 'number', index: 'runTime'}, 31 | {title: '时间', type: 'date', index: 'createdDate'}, 32 | ]; 33 | 34 | constructor(private http: _HttpClient, private modal: ModalHelper) { 35 | } 36 | 37 | ngOnInit(): void { 38 | } 39 | 40 | add(): void { 41 | // this.modal 42 | // .createStatic(FormEditComponent, { i: { id: 0 } }) 43 | // .subscribe(() => this.st.reload()); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/menu/edit/edit.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/menu/edit/edit.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {SFSchema, SFUISchema} from '@delon/form'; 3 | import {_HttpClient} from '@delon/theme'; 4 | import {NzMessageService} from 'ng-zorro-antd/message'; 5 | import {NzModalRef} from 'ng-zorro-antd/modal'; 6 | 7 | @Component({ 8 | selector: 'app-sys-menu-edit', 9 | templateUrl: './edit.component.html', 10 | }) 11 | export class SysMenuEditComponent implements OnInit { 12 | record: any = {}; 13 | i: any; 14 | schema: SFSchema = { 15 | properties: { 16 | menuName: {type: 'string', title: '菜单名称', maxLength: 15}, 17 | menuCode: {type: 'string', title: '菜单编码'}, 18 | link: {type: 'string', title: '链接'}, 19 | externalLink: {type: 'string', title: '外部链接'}, 20 | icon: {type: 'string', title: '图标'}, 21 | displayIndex: {type: 'number', title: '排序'}, 22 | }, 23 | required: ['menuName', 'menuCode'], 24 | }; 25 | ui: SFUISchema = { 26 | '*': { 27 | spanLabelFixed: 100, 28 | grid: {span: 24}, 29 | }, 30 | $menuName: { 31 | widget: 'string' 32 | }, 33 | }; 34 | 35 | constructor( 36 | private modal: NzModalRef, 37 | private msgSrv: NzMessageService, 38 | public http: _HttpClient, 39 | ) { 40 | } 41 | 42 | ngOnInit(): void { 43 | console.log(this.record); 44 | if (this.record.menuId) { 45 | this.http.get(`/api/menu/info/${this.record.menuId}`).subscribe(res => this.i = res.data); 46 | } 47 | } 48 | 49 | save(value: any): void { 50 | const api = this.record.menuId ? '/api/menu/update' : '/api/menu/insert'; 51 | this.http.post(api, value).subscribe(res => { 52 | this.msgSrv.success(res.msg); 53 | this.modal.close(true); 54 | }); 55 | } 56 | 57 | close(): void { 58 | this.modal.destroy(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/menu/menu.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 菜单名称 12 | 菜单编码 13 | 链接 14 | 外部链接 15 | 图标 16 | 排序 17 | 操作 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | {{ item.menuName }} 31 | 32 | {{ item.menuCode }} 33 | {{ item.link }} 34 | {{ item.externalLink }} 35 | {{ item.icon }} 36 | {{ item.displayIndex }} 37 | 38 | 编辑 39 | 删除 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/menu/sys-menu.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {_HttpClient} from '@delon/theme'; 3 | import {map, Observable} from "rxjs"; 4 | 5 | @Injectable() 6 | export class SysMenuService { 7 | 8 | constructor(private http: _HttpClient) { 9 | } 10 | 11 | loadMenuTree(): Observable { 12 | return this.http.get('/api/menu/tree').pipe( 13 | map(res => res.data) 14 | ) 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/profile/profile-basic/profile-basic.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/profile/profile-safety/profile-safety.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/profile/profile-safety/profile-safety.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, Inject, OnInit} from '@angular/core'; 2 | import {SFRadioWidgetSchema, SFSchema, SFStringWidgetSchema, SFUISchema} from "@delon/form"; 3 | import {_HttpClient} from "@delon/theme"; 4 | import {NzMessageService} from "ng-zorro-antd/message"; 5 | import {DA_SERVICE_TOKEN, TokenService} from "@delon/auth"; 6 | import {Router} from "@angular/router"; 7 | 8 | @Component({ 9 | selector: 'app-profile-safety', 10 | templateUrl: './profile-safety.component.html', 11 | styles: [] 12 | }) 13 | export class ProfileSafetyComponent implements OnInit { 14 | loading = false; 15 | safetySchema: SFSchema = { 16 | properties: { 17 | oldPassword: { 18 | type: 'string', 19 | title: '原密码', 20 | maxLength: 50, 21 | ui: {type: 'password'} as SFStringWidgetSchema 22 | }, 23 | newPassword: { 24 | type: 'string', 25 | title: '新密码', 26 | maxLength: 50, 27 | ui: {type: 'password'} as SFStringWidgetSchema 28 | }, 29 | repeatPassword: { 30 | type: 'string', 31 | title: '确认密码', 32 | maxLength: 50, 33 | ui: {type: 'password'} as SFStringWidgetSchema 34 | }, 35 | }, 36 | required: ['oldPassword', 'newPassword', 'repeatPassword'], 37 | }; 38 | safetyUi: SFUISchema = { 39 | '*': { 40 | spanLabelFixed: 100, 41 | grid: {span: 24}, 42 | }, 43 | }; 44 | safetyData = {}; 45 | 46 | constructor(public http: _HttpClient, private messageService: NzMessageService, 47 | @Inject(DA_SERVICE_TOKEN) private tokenService: TokenService, private router: Router) { 48 | } 49 | 50 | ngOnInit(): void { 51 | } 52 | 53 | 54 | saveSafety(value: any) { 55 | const data = { 56 | ...value 57 | } 58 | this.http.post('/api/profile/changePassword', data).subscribe(res => { 59 | this.messageService.success(res.msg); 60 | }) 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/profile/profile.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/profile/profile.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-sys-profile', 5 | templateUrl: './profile.component.html', 6 | styles: [] 7 | }) 8 | export class SysProfileComponent implements OnInit { 9 | 10 | constructor() { 11 | } 12 | 13 | ngOnInit(): void { 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/auth/auth.component.html: -------------------------------------------------------------------------------- 1 |
    2 | 4 |
    5 | 9 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/auth/auth.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, ViewChild} from '@angular/core'; 2 | import {_HttpClient} from '@delon/theme'; 3 | import {NzDrawerRef} from "ng-zorro-antd/drawer"; 4 | import {NzTreeComponent} from "ng-zorro-antd/tree"; 5 | import {NzMessageService} from "ng-zorro-antd/message"; 6 | import {SysAuthService} from "../../auth/sys-auth.service"; 7 | import {NzTreeNode} from "ng-zorro-antd/core/tree/nz-tree-base-node"; 8 | import {getCheckedNodes} from "../../../../shared/utils/treeUtils"; 9 | 10 | @Component({ 11 | selector: 'app-sys-role-auth', 12 | templateUrl: './auth.component.html', 13 | }) 14 | export class SysRoleAuthComponent implements OnInit { 15 | record: any = {}; 16 | treeNodes = []; 17 | defaultCheckedKeys: string[] = []; 18 | loading = false; 19 | saveLoading = false; 20 | @ViewChild('treeComponent') private treeComponent!: NzTreeComponent 21 | 22 | constructor(public http: _HttpClient, private nzDrawerRef: NzDrawerRef, 23 | private nzMessageService: NzMessageService, private sysAuthService: SysAuthService) { 24 | } 25 | 26 | ngOnInit(): void { 27 | console.log(this.record) 28 | this.loadAuthTree(); 29 | this.loadRoleInfo(); 30 | } 31 | 32 | loadRoleInfo() { 33 | this.loading = true; 34 | this.http.get('/api/role/info/' + this.record.roleId).subscribe(res => { 35 | this.loading = false; 36 | this.defaultCheckedKeys = res.data.auths.map((x: any) => x.authId); 37 | }) 38 | } 39 | 40 | loadAuthTree() { 41 | this.sysAuthService.loadAuthTree().subscribe(data => { 42 | this.treeNodes = data; 43 | }) 44 | } 45 | 46 | cancel(): void { 47 | this.nzDrawerRef.close(); 48 | } 49 | 50 | ok(): void { 51 | const nodeList: NzTreeNode[] = getCheckedNodes(this.treeComponent); 52 | const authIds: string[] = []; 53 | nodeList.filter(node => node.origin['type'] === 'auth').forEach(node => { 54 | authIds.push(node.key); 55 | }); 56 | const param = { 57 | roleId: this.record.roleId, 58 | auths: authIds.map(authId => ({authId})), 59 | } 60 | this.saveLoading = true; 61 | this.http.post('/api/role/saveRoleAuth', param).subscribe(res => { 62 | this.saveLoading = false; 63 | this.nzMessageService.success(res.msg); 64 | this.nzDrawerRef.close(); 65 | }) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/edit/edit.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/edit/edit.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {SFSchema, SFUISchema} from '@delon/form'; 3 | import {_HttpClient} from '@delon/theme'; 4 | import {NzMessageService} from 'ng-zorro-antd/message'; 5 | import {NzModalRef} from 'ng-zorro-antd/modal'; 6 | 7 | @Component({ 8 | selector: 'app-sys-role-edit', 9 | templateUrl: './edit.component.html', 10 | }) 11 | export class SysRoleEditComponent implements OnInit { 12 | record: any = {}; 13 | i: any; 14 | schema: SFSchema = { 15 | properties: { 16 | roleValue: {type: 'string', title: '角色标识'}, 17 | roleName: {type: 'string', title: '角色名称'}, 18 | }, 19 | required: ['roleName', 'roleValue'], 20 | }; 21 | ui: SFUISchema = { 22 | '*': { 23 | spanLabelFixed: 100, 24 | grid: {span: 24}, 25 | }, 26 | $roleValue: { 27 | widget: 'string', 28 | }, 29 | $roleName: { 30 | widget: 'string' 31 | }, 32 | }; 33 | 34 | constructor( 35 | private modal: NzModalRef, 36 | private msgSrv: NzMessageService, 37 | public http: _HttpClient, 38 | ) { 39 | } 40 | 41 | ngOnInit(): void { 42 | console.log('init edit', this.record); 43 | if (this.record.roleId != null) { 44 | this.http.get(`/api/role/info/${this.record.roleId}`).subscribe(res => (this.i = res.data)); 45 | } 46 | } 47 | 48 | save(value: any): void { 49 | const api = this.record.roleId != null ? '/api/role/update' : '/api/role/insert'; 50 | this.http.post(api, value).subscribe(res => { 51 | this.msgSrv.success(res.msg); 52 | this.modal.close(true); 53 | }); 54 | } 55 | 56 | close(): void { 57 | this.modal.destroy(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/menu/menu.component.html: -------------------------------------------------------------------------------- 1 |
    2 | 4 |
    5 | 9 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/role/role.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/sys-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | import {SysLogComponent} from './log/log.component'; 4 | import {SysUserComponent} from './user/user.component'; 5 | import {SysRoleComponent} from './role/role.component'; 6 | import {SysMenuComponent} from './menu/menu.component'; 7 | import {SysAuthComponent} from "./auth/auth.component"; 8 | import {SysConfigComponent} from "./config/config.component"; 9 | import {SysDeptComponent} from "./dept/dept.component"; 10 | import {SysProfileComponent} from "./profile/profile.component"; 11 | 12 | const routes: Routes = [ 13 | {path: 'user', component: SysUserComponent}, 14 | {path: 'role', component: SysRoleComponent}, 15 | {path: 'menu', component: SysMenuComponent}, 16 | {path: 'auth', component: SysAuthComponent}, 17 | {path: 'dept', component: SysDeptComponent}, 18 | {path: 'config', component: SysConfigComponent}, 19 | {path: 'log', component: SysLogComponent}, 20 | {path: 'profile', component: SysProfileComponent}, 21 | ]; 22 | 23 | @NgModule({ 24 | imports: [RouterModule.forChild(routes)], 25 | exports: [RouterModule] 26 | }) 27 | export class SysRoutingModule { 28 | } 29 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/sys.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule, Type} from '@angular/core'; 2 | import {SharedModule} from '@shared'; 3 | import {SysRoutingModule} from './sys-routing.module'; 4 | import {SysLogComponent} from './log/log.component'; 5 | import {SysUserComponent} from './user/user.component'; 6 | import {SysRoleComponent} from './role/role.component'; 7 | import {SysMenuComponent} from './menu/menu.component'; 8 | import {SysRoleEditComponent} from './role/edit/edit.component'; 9 | import {SysMenuEditComponent} from './menu/edit/edit.component'; 10 | import {SysUserEditComponent} from './user/edit/edit.component'; 11 | import {SysRoleMenuComponent} from "./role/menu/menu.component"; 12 | import {SysMenuService} from "./menu/sys-menu.service"; 13 | import {SysAuthComponent} from "./auth/auth.component"; 14 | import {SysAuthEditComponent} from "./auth/edit/edit.component"; 15 | import {SysRoleAuthComponent} from "./role/auth/auth.component"; 16 | import {SysAuthService} from "./auth/sys-auth.service"; 17 | import {SysConfigComponent} from "./config/config.component"; 18 | import {SysDeptComponent} from "./dept/dept.component"; 19 | import {SysProfileComponent} from "./profile/profile.component"; 20 | import {ProfileBasicComponent} from "./profile/profile-basic/profile-basic.component"; 21 | import {ProfileSafetyComponent} from "./profile/profile-safety/profile-safety.component"; 22 | import {SysDeptEditComponent} from "./dept/edit/edit.component"; 23 | import {SysDeptService} from "./dept/sys-dept.service"; 24 | 25 | const COMPONENTS: Type[] = [ 26 | SysUserComponent, SysUserEditComponent, 27 | SysRoleComponent, SysRoleEditComponent, SysRoleMenuComponent, SysRoleAuthComponent, 28 | SysMenuComponent, SysMenuEditComponent, 29 | SysAuthComponent, SysAuthEditComponent, 30 | SysDeptComponent, SysDeptEditComponent, 31 | SysConfigComponent, SysLogComponent, 32 | SysProfileComponent, ProfileBasicComponent, ProfileSafetyComponent 33 | ]; 34 | 35 | @NgModule({ 36 | imports: [ 37 | SharedModule, 38 | SysRoutingModule, 39 | ], 40 | declarations: COMPONENTS, 41 | providers: [ 42 | SysMenuService, 43 | SysAuthService, 44 | SysDeptService 45 | ], 46 | }) 47 | export class SysModule { 48 | } 49 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/user/edit/edit.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/routes/sys/user/user.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 |
    12 |
    13 | 14 |
    15 | 16 | 17 |
    18 |
    19 |
    20 | 21 |
    22 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/index.ts: -------------------------------------------------------------------------------- 1 | // Components 2 | 3 | // Utils 4 | export * from './utils/yuan'; 5 | 6 | // Module 7 | export * from './shared.module'; 8 | export * from './json-schema/json-schema.module'; 9 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/json-schema/README.md: -------------------------------------------------------------------------------- 1 | # 建议统一在 `widgets` 目录下自定义小部件 2 | 3 | > 注:`@delon/form` 本身提供 NG-ZORRO 数据录入组件的全部实现,以及若干第三方组件的代码,可从[widgets-third](https://github.com/ng-alain/delon/tree/master/packages/form/widgets-third)中获取并放置 `widgets` 目录下注册即可。 4 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/json-schema/json-schema.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { DelonFormModule, WidgetRegistry } from '@delon/form'; 3 | 4 | import { SharedModule } from '../shared.module'; 5 | import { TestWidget } from './test/test.widget'; 6 | import { AutoCompleteWidgetModule } from '@delon/form/widgets/autocomplete'; 7 | import { CascaderWidgetModule } from '@delon/form/widgets/cascader'; 8 | import { MentionWidgetModule } from '@delon/form/widgets/mention'; 9 | import { RateWidgetModule } from '@delon/form/widgets/rate'; 10 | import { SliderWidgetModule } from '@delon/form/widgets/slider'; 11 | import { TagWidgetModule } from '@delon/form/widgets/tag'; 12 | import { TimeWidgetModule } from '@delon/form/widgets/time'; 13 | import { TransferWidgetModule } from '@delon/form/widgets/transfer'; 14 | import { TreeSelectWidgetModule } from '@delon/form/widgets/tree-select'; 15 | import { UploadWidgetModule } from '@delon/form/widgets/upload'; 16 | 17 | export const SCHEMA_THIRDS_COMPONENTS = [TestWidget]; 18 | 19 | @NgModule({ 20 | declarations: SCHEMA_THIRDS_COMPONENTS, 21 | imports: [SharedModule, DelonFormModule.forRoot(), AutoCompleteWidgetModule, CascaderWidgetModule, MentionWidgetModule, RateWidgetModule, SliderWidgetModule, TagWidgetModule, TimeWidgetModule, TransferWidgetModule, TreeSelectWidgetModule, UploadWidgetModule], 22 | exports: SCHEMA_THIRDS_COMPONENTS 23 | }) 24 | export class JsonSchemaModule { 25 | constructor(widgetRegistry: WidgetRegistry) { 26 | widgetRegistry.register(TestWidget.KEY, TestWidget); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/json-schema/test/test.widget.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; 2 | import { ControlWidget } from '@delon/form'; 3 | 4 | @Component({ 5 | selector: 'test', 6 | template: ` 7 | 8 | test widget 9 | 10 | `, 11 | preserveWhitespaces: false, 12 | changeDetection: ChangeDetectionStrategy.OnPush 13 | }) 14 | export class TestWidget extends ControlWidget implements OnInit { 15 | static readonly KEY = 'test'; 16 | 17 | ngOnInit(): void { 18 | console.warn('init test widget'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/shared-delon.module.ts: -------------------------------------------------------------------------------- 1 | import { PageHeaderModule } from '@delon/abc/page-header'; 2 | import { ResultModule } from '@delon/abc/result'; 3 | import { SEModule } from '@delon/abc/se'; 4 | import { STModule } from '@delon/abc/st'; 5 | import { SVModule } from '@delon/abc/sv'; 6 | 7 | export const SHARED_DELON_MODULES = [PageHeaderModule, STModule, SEModule, SVModule, ResultModule]; 8 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/shared-zorro.module.ts: -------------------------------------------------------------------------------- 1 | import {NzAlertModule} from 'ng-zorro-antd/alert'; 2 | import {NzAvatarModule} from 'ng-zorro-antd/avatar'; 3 | import {NzButtonModule} from 'ng-zorro-antd/button'; 4 | import {NzCardModule} from 'ng-zorro-antd/card'; 5 | import {NzCheckboxModule} from 'ng-zorro-antd/checkbox'; 6 | import {NzDrawerModule} from 'ng-zorro-antd/drawer'; 7 | import {NzDropDownModule} from 'ng-zorro-antd/dropdown'; 8 | import {NzFormModule} from 'ng-zorro-antd/form'; 9 | import {NzGridModule} from 'ng-zorro-antd/grid'; 10 | import {NzIconModule} from 'ng-zorro-antd/icon'; 11 | import {NzInputModule} from 'ng-zorro-antd/input'; 12 | import {NzInputNumberModule} from 'ng-zorro-antd/input-number'; 13 | import {NzModalModule} from 'ng-zorro-antd/modal'; 14 | import {NzPopconfirmModule} from 'ng-zorro-antd/popconfirm'; 15 | import {NzPopoverModule} from 'ng-zorro-antd/popover'; 16 | import {NzProgressModule} from 'ng-zorro-antd/progress'; 17 | import {NzSelectModule} from 'ng-zorro-antd/select'; 18 | import {NzSpinModule} from 'ng-zorro-antd/spin'; 19 | import {NzTableModule} from 'ng-zorro-antd/table'; 20 | import {NzTabsModule} from 'ng-zorro-antd/tabs'; 21 | import {NzToolTipModule} from 'ng-zorro-antd/tooltip'; 22 | import {NzDividerModule} from 'ng-zorro-antd/divider'; 23 | import {NzTreeModule} from "ng-zorro-antd/tree"; 24 | 25 | export const SHARED_ZORRO_MODULES = [ 26 | NzFormModule, 27 | NzGridModule, 28 | NzButtonModule, 29 | NzInputModule, 30 | NzInputNumberModule, 31 | NzAlertModule, 32 | NzProgressModule, 33 | NzSelectModule, 34 | NzAvatarModule, 35 | NzCardModule, 36 | NzDropDownModule, 37 | NzPopconfirmModule, 38 | NzTableModule, 39 | NzPopoverModule, 40 | NzDrawerModule, 41 | NzModalModule, 42 | NzTabsModule, 43 | NzToolTipModule, 44 | NzIconModule, 45 | NzCheckboxModule, 46 | NzSpinModule, 47 | NzDividerModule, 48 | NzTreeModule 49 | ]; 50 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, Type } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { ReactiveFormsModule, FormsModule } from '@angular/forms'; 4 | import { RouterModule } from '@angular/router'; 5 | import { AlainThemeModule } from '@delon/theme'; 6 | import { DelonACLModule } from '@delon/acl'; 7 | import { DelonFormModule } from '@delon/form'; 8 | 9 | import { SHARED_DELON_MODULES } from './shared-delon.module'; 10 | import { SHARED_ZORRO_MODULES } from './shared-zorro.module'; 11 | import { AngularSplitModule } from 'angular-split'; 12 | 13 | // #region third libs 14 | 15 | const THIRDMODULES: Array> = [ 16 | AngularSplitModule 17 | ]; 18 | 19 | // #endregion 20 | 21 | // #region your componets & directives 22 | 23 | const COMPONENTS: Array> = []; 24 | const DIRECTIVES: Array> = []; 25 | 26 | // #endregion 27 | 28 | @NgModule({ 29 | imports: [ 30 | CommonModule, 31 | FormsModule, 32 | RouterModule, 33 | ReactiveFormsModule, 34 | AlainThemeModule.forChild(), 35 | DelonACLModule, 36 | DelonFormModule, 37 | ...SHARED_DELON_MODULES, 38 | ...SHARED_ZORRO_MODULES, 39 | // third libs 40 | ...THIRDMODULES 41 | ], 42 | declarations: [ 43 | // your components 44 | ...COMPONENTS, 45 | ...DIRECTIVES 46 | ], 47 | exports: [ 48 | CommonModule, 49 | FormsModule, 50 | ReactiveFormsModule, 51 | RouterModule, 52 | AlainThemeModule, 53 | DelonACLModule, 54 | DelonFormModule, 55 | ...SHARED_DELON_MODULES, 56 | ...SHARED_ZORRO_MODULES, 57 | // third libs 58 | ...THIRDMODULES, 59 | // your components 60 | ...COMPONENTS, 61 | ...DIRECTIVES 62 | ] 63 | }) 64 | export class SharedModule { } 65 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/st-widget/README.md: -------------------------------------------------------------------------------- 1 | [Demo](https://ng-alain.com/components/st/en?#components-st-widget) 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/st-widget/st-widget.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | // import { STWidgetRegistry } from '@delon/abc/st'; 4 | import { SharedModule } from '../shared.module'; 5 | 6 | export const STWIDGET_COMPONENTS = []; 7 | 8 | @NgModule({ 9 | declarations: STWIDGET_COMPONENTS, 10 | imports: [SharedModule], 11 | exports: [...STWIDGET_COMPONENTS] 12 | }) 13 | export class STWidgetModule { 14 | // constructor(widgetRegistry: STWidgetRegistry) { 15 | // widgetRegistry.register(STImgWidget.KEY, STImgWidget); 16 | // } 17 | } 18 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/utils/format-username.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 格式化更新人姓名 3 | */ 4 | export function formatUsername(value: string): string { 5 | if (value == null) { 6 | return value; 7 | } 8 | if (!value.includes('~~~')) { 9 | return value; 10 | } 11 | return value.split('~~~')[1]; 12 | } 13 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/utils/treeUtils.ts: -------------------------------------------------------------------------------- 1 | import {NzTreeComponent} from "ng-zorro-antd/tree"; 2 | import {NzTreeNode} from "ng-zorro-antd/core/tree/nz-tree-base-node"; 3 | 4 | /** 5 | * 获取选中的树节点,包括完全选中节点(及其下级节点)、半选中节点, 6 | * 7 | */ 8 | export function getCheckedNodes(treeComponent: NzTreeComponent): NzTreeNode[] { 9 | const halfCheckedNodeList = treeComponent.getHalfCheckedNodeList(); 10 | const checkedNodeList = treeComponent.getCheckedNodeList(); 11 | const checkedNodeListWithChildren = getAllWithChildren(checkedNodeList); 12 | return [...halfCheckedNodeList, ...checkedNodeListWithChildren]; 13 | } 14 | 15 | 16 | function getAllWithChildren(nodeList: NzTreeNode[]): NzTreeNode[] { 17 | let list: NzTreeNode[] = []; 18 | nodeList.forEach(node => { 19 | list.push(node); 20 | if (node.children && node.children.length > 0) { 21 | const childrenList = getAllWithChildren(node.children); 22 | childrenList.forEach(child => list.push(child)); 23 | } 24 | }); 25 | return list; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/app/shared/utils/yuan.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 转化成RMB元字符串 3 | * 4 | * @param digits 当数字类型时,允许指定小数点后数字的个数,默认2位小数 5 | */ 6 | export function yuan(value: number | string, digits: number = 2): string { 7 | if (typeof value === 'number') { 8 | value = value.toFixed(digits); 9 | } 10 | return `¥ ${value}`; 11 | } 12 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-angular-webapp/src/assets/.gitkeep -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/logo-color.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ]> 6 | 10 | 11 | 12 | 15 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ]> 6 | 10 | 11 | 12 | 15 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/tmp/app-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Soccer", 4 | "description": "Springboot + Angular 开发框架" 5 | }, 6 | "user": { 7 | "name": "Admin", 8 | "avatar": "./assets/tmp/img/avatar.jpg", 9 | "email": "duqian42707@163.com" 10 | }, 11 | "menu": [ 12 | { 13 | "text": "主导航", 14 | "group": true, 15 | "hideInBreadcrumb": true, 16 | "children": [ 17 | { 18 | "text": "仪表盘", 19 | "icon": "anticon-dashboard", 20 | "children": [ 21 | { 22 | "text": "仪表盘", 23 | "link": "/dashboard" 24 | } 25 | ] 26 | }, 27 | { 28 | "text": "系统管理", 29 | "icon": "anticon-setting", 30 | "shortcutRoot": true, 31 | "children": [ 32 | { 33 | "text": "用户管理", 34 | "link": "/sys/user" 35 | }, 36 | { 37 | "text": "角色管理", 38 | "link": "/sys/role" 39 | }, 40 | { 41 | "text": "菜单管理", 42 | "link": "/sys/menu" 43 | }, 44 | { 45 | "text": "权限管理", 46 | "link": "/sys/auth" 47 | }, 48 | { 49 | "text": "系统日志", 50 | "link": "/sys/log" 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/tmp/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-angular-webapp/src/assets/tmp/img/avatar.jpg -------------------------------------------------------------------------------- /soccer-angular-webapp/src/assets/zorro.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | import { Environment } from '@delon/theme'; 2 | 3 | export const environment = { 4 | production: true, 5 | useHash: true, 6 | api: { 7 | baseUrl: '', 8 | refreshTokenEnabled: true, 9 | refreshTokenType: 'auth-refresh' 10 | } 11 | } as Environment; 12 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | import { provideMockConfig, mockInterceptor } from '@delon/mock'; 6 | import { Environment } from '@delon/theme'; 7 | 8 | import * as MOCKDATA from '../../_mock'; 9 | 10 | export const environment = { 11 | production: false, 12 | useHash: true, 13 | api: { 14 | baseUrl: '', 15 | refreshTokenEnabled: true, 16 | refreshTokenType: 'auth-refresh' 17 | }, 18 | providers: [provideMockConfig({ data: MOCKDATA })], 19 | interceptorFns: [mockInterceptor], 20 | modules: [] 21 | } as Environment; 22 | 23 | /* 24 | * In development mode, to ignore zone related error stack frames such as 25 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can 26 | * import the following file, but please comment it out in production mode 27 | * because it will have performance impact when throw error 28 | */ 29 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 30 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-angular-webapp/src/favicon.ico -------------------------------------------------------------------------------- /soccer-angular-webapp/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode, ViewEncapsulation } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { NzSafeAny } from 'ng-zorro-antd/core/types'; 5 | 6 | import { AppModule } from './app/app.module'; 7 | import { environment } from './environments/environment'; 8 | 9 | 10 | 11 | if (environment.production) { 12 | enableProdMode(); 13 | } 14 | 15 | platformBrowserDynamic() 16 | .bootstrapModule(AppModule, { 17 | defaultEncapsulation: ViewEncapsulation.Emulated, 18 | preserveWhitespaces: false 19 | }) 20 | .then(res => { 21 | const win = window as NzSafeAny; 22 | if (win && win.appBootstrap) { 23 | win.appBootstrap(); 24 | } 25 | return res; 26 | }) 27 | .catch(err => console.error(err)); 28 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/style-icons.ts: -------------------------------------------------------------------------------- 1 | // Custom icon static resources 2 | 3 | import { BulbOutline, ExceptionOutline, InfoOutline, LinkOutline, ProfileOutline } from '@ant-design/icons-angular/icons'; 4 | 5 | export const ICONS = [InfoOutline, BulbOutline, ProfileOutline, ExceptionOutline, LinkOutline]; 6 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/styles.less: -------------------------------------------------------------------------------- 1 | @import '@delon/theme/system/index'; 2 | @import '@delon/abc/index'; 3 | @import '@delon/chart/index'; 4 | @import '@delon/theme/layout-default/style/index'; 5 | @import '@delon/theme/layout-blank/style/index'; 6 | 7 | @import './styles/index'; 8 | @import './styles/theme'; 9 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/styles/index.less: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/styles/theme.less: -------------------------------------------------------------------------------- 1 | // You can directly set the default theme 2 | // - `default` Default theme 3 | // - `dark` Import the official dark less style file 4 | // - `compact` Import the official compact less style file 5 | @import '@delon/theme/theme-default.less'; 6 | 7 | // ==========The following is the custom theme variable area========== 8 | // The theme paraments can be generated at https://ng-alain.github.io/ng-alain/ 9 | // @primary-color: #f50; 10 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unassigned-import */ 2 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 3 | 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | // First, initialize the Angular testing environment. 12 | getTestBed().initTestEnvironment( 13 | BrowserDynamicTestingModule, 14 | platformBrowserDynamicTesting(), { 15 | teardown: { destroyAfterEach: false } 16 | } 17 | ); 18 | -------------------------------------------------------------------------------- /soccer-angular-webapp/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | // # 3rd Party Library 2 | // If the library doesn't have typings available at `@types/`, 3 | // you can still use it by manually adding typings for it 4 | -------------------------------------------------------------------------------- /soccer-angular-webapp/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /soccer-angular-webapp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "declaration": false, 14 | "downlevelIteration": true, 15 | "experimentalDecorators": true, 16 | "moduleResolution": "node", 17 | "importHelpers": true, 18 | "target": "ES2022", 19 | "module": "es2020", 20 | "lib": [ 21 | "es2020", 22 | "dom" 23 | ], 24 | "paths": { 25 | "@shared": [ 26 | "src/app/shared/index" 27 | ], 28 | "@core": [ 29 | "src/app/core/index" 30 | ], 31 | "@env/*": [ 32 | "src/environments/*" 33 | ] 34 | }, 35 | "allowSyntheticDefaultImports": true, 36 | "useDefineForClassFields": false 37 | }, 38 | "angularCompilerOptions": { 39 | "enableI18nLegacyMessageIdFormat": false, 40 | "strictInjectionParameters": true, 41 | "strictInputAccessModifiers": true, 42 | "strictTemplates": true 43 | } 44 | } -------------------------------------------------------------------------------- /soccer-angular-webapp/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/Application.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer; 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.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 7 | 8 | @SpringBootApplication 9 | @MapperScan({"com.dqv5.soccer.mapper"}) 10 | @EnableGlobalMethodSecurity(prePostEnabled = true) 11 | public class Application { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(Application.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/AuthValue.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | /** 4 | * @author duq 5 | * @date 2024/1/3 6 | */ 7 | public class AuthValue { 8 | 9 | public static final String SYS_USER_QUERY = "sys_user_query"; 10 | public static final String SYS_USER_INSERT = "sys_user_insert"; 11 | public static final String SYS_USER_UPDATE = "sys_user_update"; 12 | public static final String SYS_USER_DELETE = "sys_user_delete"; 13 | 14 | public static final String SYS_ROLE_QUERY = "sys_role_query"; 15 | public static final String SYS_ROLE_INSERT = "sys_role_insert"; 16 | public static final String SYS_ROLE_UPDATE = "sys_role_update"; 17 | public static final String SYS_ROLE_DELETE = "sys_role_delete"; 18 | 19 | public static final String SYS_MENU_QUERY = "sys_menu_query"; 20 | public static final String SYS_MENU_INSERT = "sys_menu_insert"; 21 | public static final String SYS_MENU_UPDATE = "sys_menu_update"; 22 | public static final String SYS_MENU_DELETE = "sys_menu_delete"; 23 | 24 | public static final String SYS_AUTH_QUERY = "sys_auth_query"; 25 | public static final String SYS_AUTH_INSERT = "sys_auth_insert"; 26 | public static final String SYS_AUTH_UPDATE = "sys_auth_update"; 27 | public static final String SYS_AUTH_DELETE = "sys_auth_delete"; 28 | 29 | public static final String SYS_DEPT_QUERY = "sys_dept_query"; 30 | public static final String SYS_DEPT_INSERT = "sys_dept_insert"; 31 | public static final String SYS_DEPT_UPDATE = "sys_dept_update"; 32 | public static final String SYS_DEPT_DELETE = "sys_dept_delete"; 33 | 34 | public static final String SYS_CONFIG_QUERY = "sys_config_query"; 35 | public static final String SYS_CONFIG_SET = "sys_config_set"; 36 | 37 | public static final String SYS_LOG_QUERY = "sys_log_query"; 38 | 39 | public static final String SYS_RE_INIT_DATA = "sys_re_init_data"; 40 | } 41 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/ConfigValue.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @author duq 8 | * @date 2024/1/3 9 | */ 10 | @AllArgsConstructor 11 | @Getter 12 | public enum ConfigValue { 13 | SYS_NAME("sys_name", "系统名称", "Soccer"), 14 | SYS_DESC("sys_desc", "系统描述", "Springboot + Angular 开发框架"), 15 | SYS_LOGO_BIG("sys_logo_big", "系统Logo(大)", "https://image.dqv5.com/public/soccer.png"), 16 | SYS_LOGO_SMALL("sys_logo_small", "系统Logo(小)", "https://image.dqv5.com/public/soccer.png"), 17 | ; 18 | 19 | private final String configKey; 20 | private final String configName; 21 | private final String defaultValue; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/Pageable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author duqian 7 | * @date 2023/12/6 8 | */ 9 | @Data 10 | public class Pageable { 11 | private int pageNumber; 12 | private int pageSize; 13 | 14 | public static Pageable of(int pageNumber, int pageSize) { 15 | Pageable pageable = new Pageable(); 16 | pageable.setPageNumber(pageNumber); 17 | pageable.setPageSize(pageSize); 18 | return pageable; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/RestReturn.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | 6 | /** 7 | * @author duq 8 | * @date 2022/7/17 9 | */ 10 | public class RestReturn { 11 | 12 | private static final String SUCCESS = "操作成功"; 13 | 14 | public static ResponseEntity> ok() { 15 | return ResponseEntity.ok(RestReturnEntity.builder().msg(SUCCESS).build()); 16 | } 17 | 18 | public static ResponseEntity> ok(String message) { 19 | return ResponseEntity.ok(RestReturnEntity.builder().msg(message).build()); 20 | } 21 | 22 | public static ResponseEntity> ok(T data) { 23 | return ResponseEntity.ok(RestReturnEntity.builder().msg(SUCCESS).data(data).build()); 24 | } 25 | 26 | public static ResponseEntity> ok(String message, T data) { 27 | return ResponseEntity.ok(RestReturnEntity.builder().msg(message).data(data).build()); 28 | } 29 | 30 | public static ResponseEntity> fail(String message) { 31 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(RestReturnEntity.builder().msg(message).build()); 32 | } 33 | 34 | public static ResponseEntity> fail(String message, T data) { 35 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(RestReturnEntity.builder().msg(message).data(data).build()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/RestReturnEntity.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | /** 7 | * 通用返回值实体类 8 | * 9 | * @author duq 10 | * @date 2022/7/17 11 | */ 12 | @Data 13 | @Builder 14 | public class RestReturnEntity { 15 | /** 16 | * 提示信息 17 | */ 18 | private String msg; 19 | /** 20 | * 异常信息 21 | */ 22 | private String errMsg; 23 | /** 24 | * 数据 25 | */ 26 | private T data; 27 | 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/TreeNode.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * @author duq 10 | * @date 2022/7/17 11 | */ 12 | @Data 13 | public class TreeNode { 14 | private String key; 15 | private String title; 16 | private Boolean isLeaf; 17 | private List children = new ArrayList<>(); 18 | private TreeNodeType type; 19 | private Object origin; 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/common/TreeNodeType.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.common; 2 | 3 | public enum TreeNodeType { 4 | menu, auth_folder, auth, dept; 5 | } 6 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/AutoFillMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import com.dqv5.soccer.exception.CommonRuntimeException; 5 | import com.dqv5.soccer.utils.SecurityUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.ibatis.reflection.MetaObject; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * 自动填充:创建人、创建时间、更新人、更新时间 14 | * https://baomidou.com/pages/4c6bcf/ 15 | */ 16 | @Slf4j 17 | @Component 18 | public class AutoFillMetaObjectHandler implements MetaObjectHandler { 19 | 20 | @Override 21 | public void insertFill(MetaObject metaObject) { 22 | try { 23 | //根据属性的名字加入判断即可 24 | if (metaObject.hasGetter("createdDate")) { 25 | this.setFieldValByName("createdDate", new Date(), metaObject); 26 | } 27 | if (metaObject.hasGetter("createdBy")) { 28 | this.setFieldValByName("createdBy", getCurrentUserId(), metaObject); 29 | } 30 | } catch (Exception e) { 31 | throw new CommonRuntimeException("自动注入异常 => " + e.getMessage()); 32 | } 33 | updateFill(metaObject); 34 | } 35 | 36 | @Override 37 | public void updateFill(MetaObject metaObject) { 38 | try { 39 | if (metaObject.hasGetter("lastModifiedDate")) { 40 | this.setFieldValByName("lastModifiedDate", new Date(), metaObject); 41 | } 42 | if (metaObject.hasGetter("lastModifiedBy")) { 43 | this.setFieldValByName("lastModifiedBy", getCurrentUserId(), metaObject); 44 | } 45 | } catch (Exception e) { 46 | throw new CommonRuntimeException("自动注入异常 => " + e.getMessage()); 47 | } 48 | } 49 | 50 | /** 51 | * 获取登录用户名 52 | */ 53 | private String getCurrentUserId() { 54 | try { 55 | return SecurityUtils.getCurrentUserId(); 56 | } catch (Exception e) { 57 | return null; 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import com.dqv5.soccer.common.RestReturn; 4 | import com.dqv5.soccer.common.RestReturnEntity; 5 | import com.dqv5.soccer.exception.CommonRuntimeException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | 13 | 14 | /** 15 | * 统一异常处理 16 | */ 17 | @Slf4j 18 | @RestControllerAdvice 19 | public class GlobalExceptionHandler { 20 | @ExceptionHandler(value = Exception.class) 21 | public ResponseEntity> exceptionHandler(Exception e) { 22 | log.error(e.getMessage(), e); 23 | return RestReturn.fail(e.getMessage()); 24 | } 25 | 26 | @ExceptionHandler(value = {CommonRuntimeException.class}) 27 | public ResponseEntity> exceptionHandler(CommonRuntimeException e) { 28 | log.error("通用异常: {}", e.getMessage()); 29 | return RestReturn.fail(e.getMessage()); 30 | } 31 | 32 | @ExceptionHandler(value = {AccessDeniedException.class}) 33 | public ResponseEntity> exceptionHandler(AccessDeniedException e) { 34 | log.error("{}", e.getMessage()); 35 | RestReturnEntity body = RestReturnEntity.builder().msg("该操作禁止访问").build(); 36 | return ResponseEntity.status(HttpStatus.FORBIDDEN).body(body); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/InitDataRunner.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import com.dqv5.soccer.service.InitDataService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.annotation.Resource; 9 | 10 | @Component 11 | @Slf4j 12 | public class InitDataRunner implements CommandLineRunner { 13 | 14 | @Resource 15 | private InitDataService initDataService; 16 | 17 | @Override 18 | public void run(String... args) { 19 | initDataService.initData(false); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/ResourceHandlerConfig.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.http.CacheControl; 5 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | import java.time.Duration; 9 | 10 | @Configuration 11 | public class ResourceHandlerConfig implements WebMvcConfigurer { 12 | 13 | @Override 14 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 15 | CacheControl cacheControl = CacheControl.maxAge(Duration.ofDays(365)).cachePublic(); 16 | registry.addResourceHandler("/web/**").addResourceLocations("classpath:/static/web/").setCacheControl(cacheControl); 17 | registry.addResourceHandler("/swagger-ui/").addResourceLocations("classpath:/META-INF/resources/"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/SoccerProperties.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author duq 10 | * @date 2022/7/17 11 | */ 12 | @Getter 13 | @Setter 14 | @Configuration 15 | @ConfigurationProperties(prefix = "soccer") 16 | public class SoccerProperties { 17 | } 18 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.RequestHandlerSelectors; 7 | import springfox.documentation.service.*; 8 | import springfox.documentation.spi.DocumentationType; 9 | import springfox.documentation.spi.service.contexts.SecurityContext; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; 12 | 13 | import java.util.Collections; 14 | 15 | 16 | /** 17 | * @author admin 18 | */ 19 | @Configuration 20 | @EnableSwagger2WebMvc 21 | public class SwaggerConfig { 22 | 23 | private static final String AUTH_TOKEN_NAME = "token"; 24 | 25 | @Bean 26 | public Docket createApi() { 27 | return new Docket(DocumentationType.SWAGGER_2) 28 | .apiInfo(apiInfo()) 29 | .pathMapping("/") 30 | .select() 31 | .apis(RequestHandlerSelectors.basePackage("com.dqv5.soccer.web")) 32 | .build() 33 | .securityContexts(Collections.singletonList(securityContext())) 34 | .securitySchemes(Collections.singletonList((securityScheme()))); 35 | } 36 | 37 | private SecurityContext securityContext() { 38 | return SecurityContext.builder() 39 | .securityReferences(Collections.singletonList(defaultAuth())) 40 | //.forPaths(PathSelectors.regex("/*.*")) 41 | .build(); 42 | } 43 | 44 | private SecurityReference defaultAuth() { 45 | AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{ 46 | new AuthorizationScope("global", "accessEverything") 47 | }; 48 | return SecurityReference.builder().reference(AUTH_TOKEN_NAME).scopes(authorizationScopes).build(); 49 | } 50 | 51 | private SecurityScheme securityScheme() { 52 | return new ApiKey(AUTH_TOKEN_NAME, "Authorization", "header"); 53 | } 54 | 55 | private ApiInfo apiInfo() { 56 | return new ApiInfoBuilder() 57 | .title("spring-boot-angular") 58 | .description("基于Spring boot + angular 的前后端分离框架。") 59 | .version("1") 60 | .build(); 61 | } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/config/SystemConfig.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.client.RestTemplate; 6 | 7 | /** 8 | * @author duq 9 | * @date 2022/7/17 10 | */ 11 | @Configuration 12 | public class SystemConfig { 13 | @Bean 14 | public RestTemplate getRestTemplate() { 15 | return new RestTemplate(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/exception/CommonRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.exception; 2 | 3 | /** 4 | * @author duq 5 | * @date 2022/7/17 6 | */ 7 | public class CommonRuntimeException extends RuntimeException { 8 | public CommonRuntimeException() { 9 | super(); 10 | } 11 | 12 | public CommonRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public CommonRuntimeException(Throwable cause) { 17 | super(cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/file/AmazonS3Configuration.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.file; 2 | 3 | import com.amazonaws.ClientConfiguration; 4 | import com.amazonaws.auth.AWSCredentials; 5 | import com.amazonaws.auth.AWSStaticCredentialsProvider; 6 | import com.amazonaws.auth.BasicAWSCredentials; 7 | import com.amazonaws.client.builder.AwsClientBuilder; 8 | import com.amazonaws.services.s3.AmazonS3; 9 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | 14 | import javax.annotation.Resource; 15 | 16 | /** 17 | * 使用@ConditionalOnProperty注解,满足一定条件时才加载配置类或bean, 18 | * 用法:https://blog.csdn.net/qq_33790670/article/details/108800037 19 | * 20 | * @author duqian 21 | * @date 2021/05/28 22 | */ 23 | @Configuration 24 | @ConditionalOnProperty(name = "soccer.file-store.s3.enable", havingValue = "true") 25 | public class AmazonS3Configuration { 26 | @Resource 27 | private AmazonS3Properties properties; 28 | 29 | @Bean 30 | public AmazonS3 amazonS3() { 31 | AWSCredentials credentials = new BasicAWSCredentials(properties.getAccessKey(), properties.getSecretKey()); 32 | ClientConfiguration clientConfiguration = new ClientConfiguration(); 33 | clientConfiguration.setMaxConnections(500); 34 | AmazonS3 s3 = AmazonS3ClientBuilder.standard() 35 | .withCredentials(new AWSStaticCredentialsProvider(credentials)) 36 | .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(properties.getEndpoint(), "")) 37 | .withClientConfiguration(clientConfiguration) 38 | // 通过域名访问时,bucketName不作为子域名而是作为下一级路径 39 | .withPathStyleAccessEnabled(true) 40 | .build(); 41 | if (!s3.doesBucketExistV2(properties.getBucketName())) { 42 | s3.createBucket(properties.getBucketName()); 43 | } 44 | return s3; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/file/AmazonS3Properties.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.file; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author duq 10 | * @date 2024/1/23 11 | */ 12 | @Getter 13 | @Setter 14 | @Configuration 15 | @ConfigurationProperties(prefix = "soccer.file-store.s3") 16 | public class AmazonS3Properties { 17 | private boolean enable; 18 | private String endpoint; 19 | private String bucketName; 20 | private String accessKey; 21 | private String secretKey; 22 | } 23 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/file/DiskProperties.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.file; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author duq 10 | * @date 2024/1/23 11 | */ 12 | @Getter 13 | @Setter 14 | @Configuration 15 | @ConfigurationProperties(prefix = "soccer.file-store.disk") 16 | public class DiskProperties { 17 | private boolean enable; 18 | private String root; 19 | } 20 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/file/FileStoreType.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.file; 2 | 3 | import com.dqv5.soccer.exception.CommonRuntimeException; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | /** 8 | * @author duq 9 | * @date 2024/2/17 10 | */ 11 | @Getter 12 | @AllArgsConstructor 13 | public enum FileStoreType { 14 | Disk(1, "disk"), 15 | AmazonS3(2, "s3"), 16 | ; 17 | 18 | private final int value; 19 | private final String name; 20 | 21 | public static FileStoreType fromName(String name) { 22 | for (FileStoreType value : FileStoreType.values()) { 23 | if (value.getName().equalsIgnoreCase(name)) { 24 | return value; 25 | } 26 | } 27 | throw new CommonRuntimeException("参数异常:" + name); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/file/IntegrationFileHandler.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.file; 2 | 3 | import org.apache.commons.codec.digest.DigestUtils; 4 | 5 | import java.io.InputStream; 6 | import java.util.Objects; 7 | 8 | /** 9 | * @author duq 10 | * @date 2024/2/17 11 | */ 12 | public interface IntegrationFileHandler { 13 | /** 14 | * 上传文件,返回storeInfo 15 | * 16 | * @param inputStream 17 | * @param fileName 18 | * @return 19 | */ 20 | String upload(InputStream inputStream, String fileName); 21 | 22 | /** 23 | * 下载文件,获取输入流 24 | * 25 | * @param storeInfo 26 | * @return 27 | */ 28 | InputStream getInputStream(String storeInfo); 29 | 30 | /** 31 | * 删除文件 32 | * 33 | * @param storeInfo 34 | */ 35 | void delete(String storeInfo); 36 | 37 | /** 38 | * 检查文件一致性 39 | * 40 | * @param storeInfo 41 | * @param sha256 42 | * @return 43 | */ 44 | default boolean checkFile(String storeInfo, String sha256) { 45 | try (InputStream inputStream = this.getInputStream(storeInfo)) { 46 | String sha256Hex = DigestUtils.sha256Hex(inputStream); 47 | return Objects.equals(sha256, sha256Hex); 48 | } catch (Exception e) { 49 | return false; 50 | } 51 | } 52 | 53 | /** 54 | * 是否匹配存储类型 55 | * 56 | * @param storeType 57 | * @return 58 | */ 59 | boolean support(int storeType); 60 | } 61 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysAuthFolderMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysAuthFolderTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2023/12/31 9 | */ 10 | public interface SysAuthFolderMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysAuthMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.dqv5.soccer.pojo.SysAuth; 6 | import com.dqv5.soccer.table.SysAuthTable; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author duq 13 | * @date 2022/7/18 14 | */ 15 | public interface SysAuthMapper extends BaseMapper { 16 | 17 | List queryByRoleId(String roleId); 18 | 19 | List queryByUserId(String userId); 20 | 21 | List queryList(@Param("param") JSONObject param); 22 | } 23 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysConfigTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2024/1/16 9 | */ 10 | public interface SysConfigMapper extends BaseMapper { 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.pojo.SysDept; 5 | import com.dqv5.soccer.table.SysDeptTable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author duq 11 | * @date 2024/1/10 12 | */ 13 | public interface SysDeptMapper extends BaseMapper { 14 | List queryByUserId(String userId); 15 | } 16 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysFileMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysFileTable; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author duq 10 | * @date 2022/7/5 11 | */ 12 | public interface SysFileMapper extends BaseMapper { 13 | List queryList(); 14 | } 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysLogTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2022/7/18 9 | */ 10 | public interface SysLogMapper extends BaseMapper { 11 | } 12 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysMenuTable; 5 | import com.dqv5.soccer.table.SysRoleTable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author duq 11 | * @date 2022/7/18 12 | */ 13 | public interface SysMenuMapper extends BaseMapper { 14 | 15 | List queryByRoleId(String roleId); 16 | 17 | List queryByUserId(String userId); 18 | } 19 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysRoleAuthMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysRoleAuthTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2022/7/5 9 | */ 10 | public interface SysRoleAuthMapper extends BaseMapper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.pojo.SysRole; 5 | import com.dqv5.soccer.table.SysRoleTable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author duq 11 | * @date 2022/7/5 12 | */ 13 | public interface SysRoleMapper extends BaseMapper { 14 | 15 | List queryList(); 16 | 17 | List queryByUserId(String userId); 18 | } 19 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysRoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysRoleMenuTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2022/7/5 9 | */ 10 | public interface SysRoleMenuMapper extends BaseMapper { 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysUserDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysUserDeptTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2024/1/16 9 | */ 10 | public interface SysUserDeptMapper extends BaseMapper { 11 | } 12 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.pojo.SysUser; 5 | import com.dqv5.soccer.pojo.UserQueryParam; 6 | import com.dqv5.soccer.table.SysUserTable; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author duq 13 | * @date 2022/7/5 14 | */ 15 | public interface SysUserMapper extends BaseMapper { 16 | List queryList(@Param("param") UserQueryParam param); 17 | } 18 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/mapper/SysUserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.dqv5.soccer.table.SysUserRoleTable; 5 | 6 | /** 7 | * @author duq 8 | * @date 2023/12/6 9 | */ 10 | public interface SysUserRoleMapper extends BaseMapper { 11 | } 12 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/AbstractBaseVO.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * @author duq 9 | * @date 2024/1/1 10 | */ 11 | @Data 12 | public abstract class AbstractBaseVO { 13 | 14 | private String createdBy; 15 | 16 | private String createdNickName; 17 | 18 | private Date createdDate; 19 | 20 | private String lastModifiedBy; 21 | 22 | private String lastModifiedNickName; 23 | 24 | private Date lastModifiedDate; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/ChangePasswordParam.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author duq 7 | * @date 2022/7/5 8 | */ 9 | @Data 10 | public class ChangePasswordParam { 11 | private String oldPassword; 12 | private String newPassword; 13 | } 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/FileUploadDto.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | @Data 8 | @ApiModel("上传文件信息") 9 | public class FileUploadDto { 10 | @ApiModelProperty("文件访问URL") 11 | private String url; 12 | @ApiModelProperty("文件名称") 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/PageParam.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author duq 7 | * @date 2024/3/3 8 | */ 9 | @Data 10 | public class PageParam { 11 | private int pageNum = 1; 12 | private int pageSize = 10; 13 | } 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysAuth.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.common.TreeNode; 4 | import com.dqv5.soccer.common.TreeNodeType; 5 | import com.dqv5.soccer.table.AbstractBaseTable; 6 | import com.dqv5.soccer.table.SysAuthTable; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.*; 10 | import org.springframework.beans.BeanUtils; 11 | 12 | import java.io.Serializable; 13 | 14 | @EqualsAndHashCode(callSuper = true) 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Builder 19 | @ApiModel("系统权限") 20 | public class SysAuth extends AbstractBaseVO implements Serializable { 21 | private static final long serialVersionUID = 1L; 22 | 23 | @ApiModelProperty("权限id") 24 | private String authId; 25 | 26 | @ApiModelProperty("权限标识") 27 | private String authValue; 28 | 29 | @ApiModelProperty("权限名称") 30 | private String authName; 31 | 32 | @ApiModelProperty("权限目录id") 33 | private String authFolderId; 34 | 35 | @ApiModelProperty("排序") 36 | private Integer displayIndex; 37 | 38 | @ApiModelProperty("权限分组名称") 39 | private String authFolderName; 40 | 41 | 42 | public static SysAuth of(SysAuthTable table) { 43 | SysAuth sysAuth = new SysAuth(); 44 | BeanUtils.copyProperties(table, sysAuth); 45 | return sysAuth; 46 | } 47 | 48 | public SysAuthTable toTable() { 49 | SysAuthTable table = new SysAuthTable(); 50 | BeanUtils.copyProperties(this, table); 51 | return table; 52 | } 53 | 54 | public TreeNode toTreeNode() { 55 | TreeNode treeNode = new TreeNode(); 56 | treeNode.setType(TreeNodeType.auth); 57 | treeNode.setOrigin(this); 58 | treeNode.setKey(authId); 59 | treeNode.setTitle(authName); 60 | treeNode.setIsLeaf(true); 61 | return treeNode; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysAuthFolder.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.common.TreeNode; 4 | import com.dqv5.soccer.common.TreeNodeType; 5 | import com.dqv5.soccer.table.AbstractBaseTable; 6 | import com.dqv5.soccer.table.SysAuthFolderTable; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.*; 10 | import org.springframework.beans.BeanUtils; 11 | 12 | import java.io.Serializable; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Optional; 16 | import java.util.stream.Collectors; 17 | 18 | @EqualsAndHashCode(callSuper = true) 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Builder 23 | @ApiModel("系统权限目录") 24 | public class SysAuthFolder extends AbstractBaseVO implements Serializable { 25 | private static final long serialVersionUID = 1L; 26 | 27 | @ApiModelProperty("权限目录id") 28 | private String authFolderId; 29 | 30 | @ApiModelProperty("权限目录名称") 31 | private String authFolderName; 32 | 33 | @ApiModelProperty("排序") 34 | private Integer displayIndex; 35 | 36 | @ApiModelProperty("分组下的权限") 37 | private List auths; 38 | 39 | 40 | public static SysAuthFolder of(SysAuthFolderTable table) { 41 | SysAuthFolder sysAuth = new SysAuthFolder(); 42 | BeanUtils.copyProperties(table, sysAuth); 43 | return sysAuth; 44 | } 45 | 46 | public SysAuthFolderTable toTable() { 47 | SysAuthFolderTable table = new SysAuthFolderTable(); 48 | BeanUtils.copyProperties(this, table); 49 | return table; 50 | } 51 | 52 | public TreeNode toTreeNode() { 53 | TreeNode treeNode = new TreeNode(); 54 | treeNode.setType(TreeNodeType.auth_folder); 55 | treeNode.setOrigin(this); 56 | treeNode.setKey(authFolderId); 57 | treeNode.setTitle(authFolderName); 58 | List children = Optional.ofNullable(auths).orElse(new ArrayList<>()) 59 | .stream().map(SysAuth::toTreeNode).collect(Collectors.toList()); 60 | treeNode.setChildren(children); 61 | treeNode.setIsLeaf(children.isEmpty()); 62 | return treeNode; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysDept.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.common.TreeNode; 4 | import com.dqv5.soccer.common.TreeNodeType; 5 | import com.dqv5.soccer.table.SysDeptTable; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.*; 9 | import org.springframework.beans.BeanUtils; 10 | 11 | import java.io.Serializable; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Optional; 15 | import java.util.stream.Collectors; 16 | 17 | @EqualsAndHashCode(callSuper = true) 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Builder 22 | @ApiModel("部门") 23 | public class SysDept extends AbstractBaseVO implements Serializable { 24 | private static final long serialVersionUID = 1L; 25 | 26 | @ApiModelProperty("部门id") 27 | private String deptId; 28 | 29 | @ApiModelProperty("部门名称") 30 | private String deptName; 31 | 32 | @ApiModelProperty("部门编码") 33 | private String deptCode; 34 | 35 | @ApiModelProperty("上级部门id") 36 | private String parentId; 37 | 38 | @ApiModelProperty("下级部门") 39 | private List children = new ArrayList<>(); 40 | 41 | public static SysDept of(SysDeptTable table) { 42 | SysDept sysDept = new SysDept(); 43 | BeanUtils.copyProperties(table, sysDept); 44 | return sysDept; 45 | } 46 | 47 | public SysDeptTable toTable() { 48 | SysDeptTable table = new SysDeptTable(); 49 | BeanUtils.copyProperties(this, table); 50 | return table; 51 | } 52 | 53 | public TreeNode toTreeNode() { 54 | TreeNode treeNode = new TreeNode(); 55 | treeNode.setType(TreeNodeType.dept); 56 | treeNode.setOrigin(this); 57 | treeNode.setKey(deptId); 58 | treeNode.setTitle(deptName); 59 | List children = Optional.ofNullable(this.children).orElse(new ArrayList<>()) 60 | .stream().map(SysDept::toTreeNode).collect(Collectors.toList()); 61 | treeNode.setChildren(children); 62 | treeNode.setIsLeaf(children.isEmpty()); 63 | return treeNode; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysFile.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.table.SysFileTable; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import org.springframework.beans.BeanUtils; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author duq 12 | * @date 2024/2/15 13 | */ 14 | @Data 15 | @EqualsAndHashCode(callSuper = true) 16 | public class SysFile extends AbstractBaseVO implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String fileId; 20 | private String fileName; 21 | private String fileType; 22 | private Long fileSize; 23 | private Integer duration; 24 | private String sha256; 25 | private Integer storeType; 26 | private String storeInfo; 27 | private String remark; 28 | private String url; 29 | 30 | public static SysFile of(SysFileTable table) { 31 | SysFile sysFile = new SysFile(); 32 | BeanUtils.copyProperties(table, sysFile); 33 | sysFile.setUrl("/api/file/file/" + table.getFileId()); 34 | return sysFile; 35 | } 36 | 37 | public SysFileTable toTable() { 38 | SysFileTable table = new SysFileTable(); 39 | BeanUtils.copyProperties(this, table); 40 | return table; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysInfo.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author duq 7 | * @date 2024/1/27 8 | */ 9 | @Data 10 | public class SysInfo { 11 | private String sysName; 12 | private String sysDesc; 13 | private String sysLogoBig; 14 | private String sysLogoSmall; 15 | } 16 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysRole.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.table.AbstractBaseTable; 4 | import com.dqv5.soccer.table.SysRoleTable; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.*; 8 | import org.springframework.beans.BeanUtils; 9 | 10 | import java.io.Serializable; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author duqian 16 | * @date 2023/12/12 17 | */ 18 | @EqualsAndHashCode(callSuper = true) 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Builder 23 | @ApiModel("系统角色") 24 | public class SysRole extends AbstractBaseVO implements Serializable { 25 | @ApiModelProperty("角色id") 26 | private String roleId; 27 | @ApiModelProperty("角色标识") 28 | private String roleValue; 29 | @ApiModelProperty("角色名称") 30 | private String roleName; 31 | @ApiModelProperty("关联的菜单") 32 | private List menus = new ArrayList<>(); 33 | @ApiModelProperty("关联的权限") 34 | private List auths = new ArrayList<>(); 35 | 36 | public static SysRole of(SysRoleTable table) { 37 | SysRole sysAuth = new SysRole(); 38 | BeanUtils.copyProperties(table, sysAuth); 39 | return sysAuth; 40 | } 41 | 42 | public SysRoleTable toTable() { 43 | SysRoleTable table = new SysRoleTable(); 44 | BeanUtils.copyProperties(this, table); 45 | return table; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/SysUser.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import com.dqv5.soccer.table.SysUserTable; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import io.swagger.annotations.ApiModel; 6 | import lombok.*; 7 | import org.springframework.beans.BeanUtils; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * @author duqian 16 | * @date 2023/12/12 17 | */ 18 | @EqualsAndHashCode(callSuper = true) 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Builder 23 | @ApiModel("系统用户") 24 | public class SysUser extends AbstractBaseVO implements Serializable { 25 | private static final long serialVersionUID = 1L; 26 | private String userId; 27 | private String account; 28 | @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) 29 | private String password; 30 | private String nickName; 31 | private String avatarUrl; 32 | private Integer gender; 33 | private String phone; 34 | private String email; 35 | private Integer status; 36 | private String openid; 37 | private Date lastLoginTime; 38 | private Date lastPasswordResetTime; 39 | 40 | private List depts = new ArrayList<>(); 41 | 42 | public static SysUser of(SysUserTable table) { 43 | SysUser sysUser = new SysUser(); 44 | BeanUtils.copyProperties(table, sysUser); 45 | return sysUser; 46 | } 47 | 48 | public SysUserTable toTable() { 49 | SysUserTable table = new SysUserTable(); 50 | BeanUtils.copyProperties(this, table); 51 | return table; 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/UpdateProfileParam.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author duq 7 | * @date 2022/7/5 8 | */ 9 | @Data 10 | public class UpdateProfileParam { 11 | private String nickName; 12 | private String avatarUrl; 13 | private Integer gender; 14 | } 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/pojo/UserQueryParam.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.pojo; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * @author duq 8 | * @date 2024/3/3 9 | */ 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class UserQueryParam extends PageParam{ 13 | private String deptId; 14 | } 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/security/CustomPasswordEncoder.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.security; 2 | 3 | import org.springframework.security.crypto.password.PasswordEncoder; 4 | 5 | /** 6 | * @author duq 7 | * @date 2022/7/12 8 | */ 9 | public class CustomPasswordEncoder implements PasswordEncoder { 10 | @Override 11 | public String encode(CharSequence rawPassword) { 12 | return "" + rawPassword + ""; 13 | } 14 | 15 | @Override 16 | public boolean matches(CharSequence rawPassword, String encodedPassword) { 17 | return encode(rawPassword).equals(encodedPassword); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/security/JWTAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.security; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.AuthenticationEntryPoint; 5 | 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | 11 | public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint { 12 | @Override 13 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) 14 | throws IOException, ServletException { 15 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/security/JWTAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.security; 2 | 3 | import com.dqv5.soccer.utils.JsonUtil; 4 | import com.dqv5.soccer.utils.JwtTokenUtil; 5 | import org.springframework.security.authentication.AuthenticationServiceException; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.core.AuthenticationException; 9 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 10 | 11 | import javax.servlet.FilterChain; 12 | import javax.servlet.ServletException; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { 20 | 21 | 22 | @Override 23 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { 24 | if (!request.getMethod().equals("POST")) { 25 | throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); 26 | } 27 | String username = request.getParameter("username"); 28 | String password = request.getParameter("password"); 29 | UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); 30 | return this.getAuthenticationManager().authenticate(authRequest); 31 | } 32 | 33 | @Override 34 | protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { 35 | AuthUser user = (AuthUser) authResult.getPrincipal(); 36 | // 创建Token 37 | String token = JwtTokenUtil.createToken(user.getUsername()); 38 | 39 | // 设置编码 防止乱码问题 40 | response.setCharacterEncoding("UTF-8"); 41 | response.setContentType("application/json; charset=utf-8"); 42 | // 在请求头里返回创建成功的token 43 | Map data = new HashMap<>(); 44 | data.put("msg", "登录成功"); 45 | data.put("token", token); 46 | response.getWriter().write(JsonUtil.toString(data)); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/InitDataService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | /** 4 | * @author duq 5 | * @date 2024/1/26 6 | */ 7 | public interface InitDataService { 8 | void initData(boolean reCreate); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysAuthService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.dqv5.soccer.common.Pageable; 5 | import com.dqv5.soccer.pojo.SysAuth; 6 | import com.dqv5.soccer.common.TreeNode; 7 | import com.dqv5.soccer.pojo.SysAuthFolder; 8 | import com.dqv5.soccer.table.SysAuthTable; 9 | import com.github.pagehelper.PageInfo; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author duqian 15 | * @date 2022/7/17 16 | */ 17 | 18 | public interface SysAuthService { 19 | List findAuthTree(); 20 | 21 | PageInfo queryListForPage(JSONObject param, Pageable pageable); 22 | 23 | List findFolders(); 24 | 25 | SysAuthTable findOne(String id); 26 | 27 | void insert(SysAuthTable sysUser); 28 | 29 | void update(SysAuthTable sysUser); 30 | 31 | void deleteById(String id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysConfigService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.dqv5.soccer.pojo.SysInfo; 5 | import com.dqv5.soccer.table.SysConfigTable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author duq 11 | * @date 2024/1/16 12 | */ 13 | public interface SysConfigService { 14 | List queryAll(); 15 | 16 | void setConfig(JSONObject param); 17 | 18 | SysInfo getSysInfo(); 19 | } 20 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysDeptService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.common.TreeNode; 4 | import com.dqv5.soccer.pojo.SysDept; 5 | import com.dqv5.soccer.table.SysDeptTable; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author admin 11 | * @date 2022/7/17 12 | */ 13 | public interface SysDeptService { 14 | List queryAll(); 15 | 16 | List queryAllTree(); 17 | 18 | SysDept findOne(String id); 19 | 20 | void insert(SysDeptTable param); 21 | 22 | void update(SysDeptTable param); 23 | 24 | void deleteById(String id); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysFileService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.pojo.SysFile; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | /** 9 | * @author duqian 10 | * @date 2024/1/23 11 | */ 12 | 13 | public interface SysFileService { 14 | 15 | SysFile uploadFile(MultipartFile file); 16 | 17 | SysFile getFileInfo(String id); 18 | 19 | void downloadFile(String id, String dl, HttpServletResponse response); 20 | 21 | void deleteFile(String id); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysLogService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.common.Pageable; 4 | import com.dqv5.soccer.table.SysLogTable; 5 | import com.github.pagehelper.PageInfo; 6 | 7 | /** 8 | * @author admin 9 | * @date 2022/7/17 10 | */ 11 | public interface SysLogService { 12 | PageInfo queryListForPage(Pageable pageable); 13 | 14 | void insert(SysLogTable param); 15 | } 16 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysMenuService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.common.TreeNode; 4 | import com.dqv5.soccer.pojo.SysMenu; 5 | import com.dqv5.soccer.table.SysMenuTable; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * @author admin 12 | * @date 2022/7/17 13 | */ 14 | public interface SysMenuService { 15 | List findAll(); 16 | 17 | List findAllTree(); 18 | 19 | SysMenuTable findOne(String id); 20 | 21 | void insert(SysMenu param); 22 | 23 | void update(SysMenu param); 24 | 25 | void deleteById(String id); 26 | 27 | List queryByUserId(String userId); 28 | } 29 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysProfileService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.pojo.ChangePasswordParam; 4 | import com.dqv5.soccer.pojo.UpdateProfileParam; 5 | 6 | /** 7 | * @author duq 8 | * @date 2022/7/10 9 | */ 10 | public interface SysProfileService { 11 | 12 | void updateProfile(UpdateProfileParam param); 13 | 14 | void changePassword(ChangePasswordParam param); 15 | } 16 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysRoleService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.common.Pageable; 4 | import com.dqv5.soccer.pojo.SysRole; 5 | import com.dqv5.soccer.table.SysRoleTable; 6 | import com.github.pagehelper.PageInfo; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author duq 12 | * @date 2022/7/10 13 | */ 14 | public interface SysRoleService { 15 | 16 | PageInfo queryListForPage(Pageable pageable); 17 | 18 | SysRole findOne(String id); 19 | 20 | void insert(SysRoleTable param); 21 | 22 | void update(SysRoleTable param); 23 | 24 | void deleteById(String id); 25 | 26 | void saveRoleMenu(SysRole param); 27 | 28 | void saveRoleAuth(SysRole param); 29 | 30 | List queryByUserId(String userId); 31 | } 32 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/SysUserService.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service; 2 | 3 | import com.dqv5.soccer.pojo.SysUser; 4 | import com.dqv5.soccer.pojo.UserQueryParam; 5 | import com.github.pagehelper.PageInfo; 6 | 7 | /** 8 | * @author duq 9 | * @date 2022/7/10 10 | */ 11 | public interface SysUserService { 12 | PageInfo queryListForPage(UserQueryParam pageable); 13 | 14 | SysUser findOne(String id); 15 | 16 | void insert(SysUser sysUser); 17 | 18 | void update(SysUser sysUser); 19 | 20 | void deleteById(String id); 21 | } 22 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/impl/SysLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.dqv5.soccer.table.SysLogTable; 5 | import com.dqv5.soccer.mapper.SysLogMapper; 6 | import com.dqv5.soccer.service.SysLogService; 7 | import com.dqv5.soccer.security.AuthUser; 8 | import com.dqv5.soccer.utils.SecurityUtils; 9 | import com.github.pagehelper.PageHelper; 10 | import com.github.pagehelper.PageInfo; 11 | import com.dqv5.soccer.common.Pageable; 12 | import org.springframework.stereotype.Service; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.List; 16 | 17 | @Service 18 | public class SysLogServiceImpl implements SysLogService { 19 | @Resource 20 | private SysLogMapper sysLogMapper; 21 | 22 | 23 | @Override 24 | public PageInfo queryListForPage(Pageable pageable) { 25 | QueryWrapper queryWrapper = new QueryWrapper<>(); 26 | PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize()); 27 | List list = sysLogMapper.selectList(queryWrapper); 28 | return new PageInfo<>(list); 29 | } 30 | 31 | 32 | @Override 33 | public void insert(SysLogTable param) { 34 | param.setLogId(null); 35 | AuthUser user = SecurityUtils.getCurrentUserDetail(); 36 | if (user != null) { 37 | param.setUserId(user.getUserId()); 38 | param.setUsername(user.getUsername()); 39 | param.setNickName(user.getNickName()); 40 | } 41 | sysLogMapper.insert(param); 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/service/impl/SysProfileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.service.impl; 2 | 3 | import com.dqv5.soccer.exception.CommonRuntimeException; 4 | import com.dqv5.soccer.mapper.SysUserMapper; 5 | import com.dqv5.soccer.pojo.ChangePasswordParam; 6 | import com.dqv5.soccer.pojo.UpdateProfileParam; 7 | import com.dqv5.soccer.security.AuthUser; 8 | import com.dqv5.soccer.service.SysProfileService; 9 | import com.dqv5.soccer.table.SysUserTable; 10 | import com.dqv5.soccer.utils.SecurityUtils; 11 | import org.springframework.security.crypto.password.PasswordEncoder; 12 | import org.springframework.stereotype.Service; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.Date; 16 | 17 | /** 18 | * @author duqian 19 | * @date 2024/1/22 20 | */ 21 | @Service 22 | public class SysProfileServiceImpl implements SysProfileService { 23 | 24 | @Resource 25 | private SysUserMapper sysUserMapper; 26 | @Resource 27 | private PasswordEncoder passwordEncoder; 28 | 29 | 30 | @Override 31 | public void updateProfile(UpdateProfileParam param) { 32 | String userId = SecurityUtils.getCurrentUserId(); 33 | SysUserTable sysUser = new SysUserTable(); 34 | sysUser.setUserId(userId); 35 | sysUser.setNickName(param.getNickName()); 36 | sysUser.setAvatarUrl(param.getAvatarUrl()); 37 | sysUser.setGender(param.getGender()); 38 | sysUserMapper.updateById(sysUser); 39 | } 40 | 41 | @Override 42 | public void changePassword(ChangePasswordParam param) { 43 | String oldPassword = param.getOldPassword(); 44 | String newPassword = param.getNewPassword(); 45 | AuthUser authUser = SecurityUtils.getCurrentUserDetail(); 46 | if (authUser == null) { 47 | throw new CommonRuntimeException("当前用户信息异常"); 48 | } 49 | if (!passwordEncoder.matches(oldPassword, authUser.getPassword())) { 50 | throw new CommonRuntimeException("原密码错误!"); 51 | } 52 | String encoded = passwordEncoder.encode(newPassword); 53 | SysUserTable sysUser = new SysUserTable(); 54 | sysUser.setUserId(authUser.getUserId()); 55 | sysUser.setPassword(encoded); 56 | sysUser.setLastPasswordResetTime(new Date()); 57 | sysUserMapper.updateById(sysUser); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/AbstractBaseTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import lombok.Data; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * @author duq 11 | * @date 2020/4/4 12 | */ 13 | @Data 14 | public abstract class AbstractBaseTable { 15 | @TableField(fill = FieldFill.INSERT) 16 | private String createdBy; 17 | 18 | @TableField(fill = FieldFill.INSERT) 19 | private Date createdDate; 20 | 21 | @TableField(fill = FieldFill.INSERT_UPDATE) 22 | private String lastModifiedBy; 23 | 24 | @TableField(fill = FieldFill.INSERT_UPDATE) 25 | private Date lastModifiedDate; 26 | } 27 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysAuthFolderTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.*; 7 | 8 | import java.io.Serializable; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @TableName("sys_auth_folder") 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class SysAuthFolderTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | @TableId(type = IdType.ASSIGN_UUID) 20 | private String authFolderId; 21 | 22 | private String authFolderName; 23 | 24 | private Integer displayIndex; 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysAuthTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.*; 7 | 8 | import java.io.Serializable; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @TableName("sys_auth") 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class SysAuthTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | @TableId(type = IdType.ASSIGN_UUID) 20 | private String authId; 21 | 22 | private String authValue; 23 | 24 | private String authName; 25 | 26 | private String authFolderId; 27 | 28 | private Integer displayIndex; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysConfigTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.*; 7 | 8 | import java.io.Serializable; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @TableName("sys_config") 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class SysConfigTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | @TableId(type = IdType.INPUT) 20 | private String configKey; 21 | 22 | private String configValue; 23 | 24 | private String configName; 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysDeptTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.io.Serializable; 10 | 11 | 12 | /** 13 | * @author duq 14 | * @date 2024/1/10 15 | */ 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | @TableName("sys_dept") 19 | public class SysDeptTable extends AbstractBaseTable implements Serializable { 20 | private static final long serialVersionUID = 1L; 21 | 22 | @TableId(type = IdType.ASSIGN_UUID) 23 | private String deptId; 24 | private String deptName; 25 | private String deptCode; 26 | private String parentId; 27 | private Integer displayIndex; 28 | } 29 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysFileTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author duq 13 | * @date 2024/2/15 14 | */ 15 | @Data 16 | @EqualsAndHashCode(callSuper = true) 17 | @TableName("sys_file") 18 | public class SysFileTable extends AbstractBaseTable implements Serializable { 19 | private static final long serialVersionUID = 1L; 20 | 21 | @TableId(type = IdType.ASSIGN_UUID) 22 | private String fileId; 23 | private String fileName; 24 | private String fileType; 25 | private Long fileSize; 26 | private Integer duration; 27 | private String sha256; 28 | private Integer storeType; 29 | private String storeInfo; 30 | private String remark; 31 | } 32 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysLogTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.io.Serializable; 12 | import java.util.Date; 13 | 14 | /** 15 | * 系统日志 16 | * 17 | * @author admin 18 | * @date 2022/7/17 19 | */ 20 | @Data 21 | @TableName("sys_log") 22 | @Builder 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | public class SysLogTable implements Serializable { 26 | private static final long serialVersionUID = 1L; 27 | @TableId(type = IdType.ASSIGN_UUID) 28 | private String logId; 29 | private String userId; 30 | private String username; 31 | private String nickName; 32 | private String ip; 33 | private String address; 34 | private String className; 35 | private String methodName; 36 | private String methodDesc; 37 | private String args; 38 | private String ua; 39 | private String requestUrl; 40 | private String requestType; 41 | private Integer status; 42 | private String errorInfo; 43 | private Long runTime; 44 | private Date createdDate; 45 | } 46 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysMenuTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.*; 7 | 8 | import java.io.Serializable; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @TableName("sys_menu") 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Builder 16 | public class SysMenuTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | @TableId(type = IdType.ASSIGN_UUID) 19 | private String menuId; 20 | /** 21 | * 菜单名称 22 | */ 23 | private String menuName; 24 | /** 25 | * 唯一标识 26 | */ 27 | private String menuCode; 28 | 29 | /** 30 | * 路由链接 31 | */ 32 | private String link; 33 | /** 34 | * 外部链接 35 | */ 36 | private String externalLink; 37 | /** 38 | * 介绍 39 | */ 40 | private String intro; 41 | /** 42 | * 图标 43 | */ 44 | private String icon; 45 | /** 46 | * 是否隐藏菜单 47 | */ 48 | private Integer hide; 49 | /** 50 | * 是否隐藏菜单 51 | */ 52 | private Integer hideChildren; 53 | /** 54 | * 显示顺序 55 | */ 56 | private Integer displayIndex; 57 | /** 58 | * 父级菜单id 59 | */ 60 | private String parentId; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysRoleAuthTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author duq 11 | * @date 2022/7/12 12 | */ 13 | @Data 14 | @EqualsAndHashCode(callSuper = true) 15 | @TableName("sys_role_auth") 16 | public class SysRoleAuthTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String roleId; 20 | private String authId; 21 | } 22 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysRoleMenuTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author duq 11 | * @date 2022/7/12 12 | */ 13 | @Data 14 | @EqualsAndHashCode(callSuper = true) 15 | @TableName("sys_role_menu") 16 | public class SysRoleMenuTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String roleId; 20 | private String menuId; 21 | } 22 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysRoleTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @author duq 13 | * @date 2022/7/12 14 | */ 15 | @Data 16 | @EqualsAndHashCode(callSuper = true) 17 | @TableName("sys_role") 18 | public class SysRoleTable extends AbstractBaseTable implements Serializable { 19 | private static final long serialVersionUID = 1L; 20 | 21 | @TableId(type = IdType.ASSIGN_UUID) 22 | private String roleId; 23 | private String roleValue; 24 | private String roleName; 25 | } 26 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysUserDeptTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.*; 5 | 6 | import java.io.Serializable; 7 | 8 | @EqualsAndHashCode(callSuper = true) 9 | @Data 10 | @TableName("sys_user_dept") 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class SysUserDeptTable extends AbstractBaseTable implements Serializable { 15 | private static final long serialVersionUID = 1L; 16 | private String userId; 17 | private String deptId; 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysUserRoleTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author duq 11 | * @date 2023/12/6 12 | */ 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | @TableName("sys_user_role") 16 | public class SysUserRoleTable extends AbstractBaseTable implements Serializable { 17 | private static final long serialVersionUID = 1L; 18 | private String userId; 19 | private String roleId; 20 | } 21 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/table/SysUserTable.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.table; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | import lombok.Data; 8 | import lombok.EqualsAndHashCode; 9 | 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | /** 14 | * @author duq 15 | * @date 2020/7/31 16 | */ 17 | @Data 18 | @EqualsAndHashCode(callSuper = true) 19 | @TableName("sys_user") 20 | public class SysUserTable extends AbstractBaseTable implements Serializable { 21 | private static final long serialVersionUID = 1L; 22 | @TableId(type = IdType.ASSIGN_UUID) 23 | private String userId; 24 | private String account; 25 | @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) 26 | private String password; 27 | private String nickName; 28 | private String avatarUrl; 29 | private Integer gender; 30 | private String phone; 31 | private String email; 32 | private Integer status; 33 | private String openid; 34 | private Date lastLoginTime; 35 | private Date lastPasswordResetTime; 36 | } 37 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/DqFileUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | 4 | /** 5 | * @author admin 6 | * @date 2018/8/30 7 | */ 8 | public class DqFileUtils { 9 | /** 10 | * 视频文件后缀 11 | */ 12 | public static final String[] VIDEO_FILE_EXTENSIONS = {"mp4", "wmv", "mov", "avi", "flv", "rm", "rmvb", "mpg", "mkv"}; 13 | /** 14 | * 音频文件后缀 15 | */ 16 | public static final String[] AUDIO_FILE_EXTENSIONS = {"mp3", "wav", "ogg", "wma"}; 17 | /** 18 | * 图片文件后缀 19 | */ 20 | public static final String[] IMAGE_FILE_EXTENSIONS = {"jpg", "jpeg", "bmp", "png", "gif"}; 21 | 22 | 23 | /** 24 | * 判断是否为视频格式 25 | */ 26 | public static boolean isVideo(String extension) { 27 | for (String s : VIDEO_FILE_EXTENSIONS) { 28 | if (s.equalsIgnoreCase(extension)) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | 35 | /** 36 | * 判断是否为音频格式 37 | */ 38 | public static boolean isAudio(String extension) { 39 | for (String s : AUDIO_FILE_EXTENSIONS) { 40 | if (s.equalsIgnoreCase(extension)) { 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | /** 48 | * 判断是否为图片格式 49 | */ 50 | public static boolean isPic(String extension) { 51 | for (String s : IMAGE_FILE_EXTENSIONS) { 52 | if (s.equalsIgnoreCase(extension)) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/IpIpFreeUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import net.ipip.ipdb.City; 4 | import net.ipip.ipdb.IPFormatException; 5 | import net.ipip.ipdb.InvalidDatabaseException; 6 | import org.apache.commons.io.IOUtils; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.core.io.ClassPathResource; 9 | 10 | import java.io.InputStream; 11 | 12 | /** 13 | * @author duqian 14 | * @date 2019/9/9 15 | */ 16 | public class IpIpFreeUtils { 17 | 18 | private static City cityDb; 19 | 20 | static { 21 | InputStream in = null; 22 | try { 23 | ClassPathResource path = new ClassPathResource("/files/ipipfree.ipdb"); 24 | in = path.getInputStream(); 25 | cityDb = new City(in); 26 | } catch (Exception ex) { 27 | ex.printStackTrace(); 28 | } finally { 29 | IOUtils.closeQuietly(in); 30 | } 31 | } 32 | 33 | public static String getAddressFromIp(String ip) { 34 | StringBuilder address = new StringBuilder(); 35 | try { 36 | if (ip.contains(":")) { 37 | return ""; 38 | } 39 | String[] cns = cityDb.find(ip, "CN"); 40 | for (String cn : cns) { 41 | if (StringUtils.isNotBlank(cn)) { 42 | address.append("-").append(cn); 43 | } 44 | } 45 | if (address.length() > 1) { 46 | return address.substring(1); 47 | } 48 | } catch (IPFormatException | InvalidDatabaseException e) { 49 | e.printStackTrace(); 50 | } 51 | return address.toString(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * @author duq 9 | * @date 2022/7/17 10 | */ 11 | public class JsonUtil { 12 | 13 | private static final ObjectMapper objectMapper = new ObjectMapper(); 14 | 15 | public static Object toObject(String jsonInString) { 16 | try { 17 | return objectMapper.readValue(jsonInString, Object.class); 18 | } catch (IOException e) { 19 | e.printStackTrace(); 20 | return null; 21 | } 22 | } 23 | 24 | public static String toString(Object obj) { 25 | try { 26 | return objectMapper.writeValueAsString(obj); 27 | } catch (IOException e) { 28 | e.printStackTrace(); 29 | return ""; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/MediaFileUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.io.FileUtils; 6 | import org.apache.commons.io.IOUtils; 7 | import ws.schild.jave.MultimediaObject; 8 | import ws.schild.jave.info.MultimediaInfo; 9 | 10 | import java.io.*; 11 | import java.nio.file.Files; 12 | 13 | /** 14 | * 音视频处理工具类 15 | * 16 | * @author duqian 17 | * @date 2020/8/3 18 | */ 19 | @Slf4j 20 | public class MediaFileUtils { 21 | 22 | /** 23 | * 获取音视频长度,单位:秒 24 | * 25 | * @param inputStream 26 | * @return 27 | */ 28 | public static Integer getDuration(InputStream inputStream, String fileName) { 29 | String mainName = FileUtil.mainName(fileName); 30 | String extName = FileUtil.extName(fileName); 31 | if (!DqFileUtils.isVideo(extName) && !DqFileUtils.isAudio(extName)) { 32 | return null; 33 | } 34 | File temp = null; 35 | OutputStream outputStream = null; 36 | try { 37 | temp = File.createTempFile(mainName, "." + extName); 38 | outputStream = Files.newOutputStream(temp.toPath()); 39 | IOUtils.copy(inputStream, outputStream); 40 | return getDuration(temp); 41 | } catch (IOException e) { 42 | return null; 43 | } finally { 44 | IOUtils.closeQuietly(outputStream); 45 | FileUtils.deleteQuietly(temp); 46 | } 47 | } 48 | 49 | /** 50 | * 获取音视频长度,单位:秒 51 | * 52 | * @param file 53 | * @return 54 | */ 55 | public static Integer getDuration(File file) { 56 | String fileName = file.getName(); 57 | String extName = FileUtil.extName(fileName); 58 | if (!DqFileUtils.isVideo(extName) && !DqFileUtils.isAudio(extName)) { 59 | return null; 60 | } 61 | MultimediaObject multimediaObject = new MultimediaObject(file); 62 | try { 63 | MultimediaInfo m = multimediaObject.getInfo(); 64 | long second = m.getDuration() / 1000; 65 | return (int) second; 66 | } catch (Exception e) { 67 | log.error("获取音视频长度异常", e); 68 | return null; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import com.dqv5.soccer.security.AuthUser; 4 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | 10 | import java.util.HashSet; 11 | 12 | /** 13 | * @author duq 14 | */ 15 | public final class SecurityUtils { 16 | 17 | /** 18 | * 获取当前用户 19 | */ 20 | public static AuthUser getCurrentUserDetail() { 21 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 22 | if (authentication == null) { 23 | return null; 24 | } 25 | Object principal = authentication.getPrincipal(); 26 | if (!(principal instanceof AuthUser)) { 27 | return null; 28 | } 29 | return (AuthUser) principal; 30 | } 31 | 32 | public static String getCurrentUserName() { 33 | return getCurrentUserDetail().getUsername(); 34 | } 35 | 36 | public static String getCurrentUserNickName() { 37 | return getCurrentUserDetail().getNickName(); 38 | } 39 | 40 | public static String getCurrentUserId() { 41 | return getCurrentUserDetail().getUserId(); 42 | } 43 | 44 | public static void refreshUserInfo() { 45 | String username = getCurrentUserName(); 46 | UserDetailsService userDetailsService = SpringUtils.getBean(UserDetailsService.class); 47 | UserDetails userDetails = userDetailsService.loadUserByUsername(username); 48 | Authentication authentication = new UsernamePasswordAuthenticationToken( 49 | userDetails, 50 | userDetails == null ? null : userDetails.getAuthorities() 51 | ); 52 | SecurityContextHolder.getContext().setAuthentication(authentication); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/SpringUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * 非@import显式注入,@Component是必须的,且该类必须与main同包或子包 10 | * 若非同包或子包,则需手动import 注入,有没有@Component都一样 11 | * 可复制到Test同包测试 12 | */ 13 | @Component 14 | public class SpringUtils implements ApplicationContextAware { 15 | 16 | private static ApplicationContext applicationContext = null; 17 | 18 | @Override 19 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 20 | if (SpringUtils.applicationContext == null) { 21 | SpringUtils.applicationContext = applicationContext; 22 | } 23 | } 24 | 25 | /** 26 | * 获取applicationContext 27 | * 28 | * @return 29 | */ 30 | public static ApplicationContext getApplicationContext() { 31 | return applicationContext; 32 | } 33 | 34 | /** 35 | * 通过name获取 Bean. 36 | * 37 | * @param name 38 | * @return 39 | */ 40 | public static Object getBean(String name) { 41 | return getApplicationContext().getBean(name); 42 | 43 | } 44 | 45 | /** 46 | * 通过class获取Bean. 47 | * 48 | * @param clazz 49 | * @param 50 | * @return 51 | */ 52 | public static T getBean(Class clazz) { 53 | return getApplicationContext().getBean(clazz); 54 | } 55 | 56 | /** 57 | * 通过name,以及Clazz返回指定的Bean 58 | * 59 | * @param name 60 | * @param clazz 61 | * @param 62 | * @return 63 | */ 64 | public static T getBean(String name, Class clazz) { 65 | return getApplicationContext().getBean(name, clazz); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/utils/TreeUtils.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.utils; 2 | 3 | import com.dqv5.soccer.pojo.SysDept; 4 | import com.dqv5.soccer.pojo.SysMenu; 5 | import com.dqv5.soccer.table.SysDeptTable; 6 | import com.dqv5.soccer.table.SysMenuTable; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Objects; 12 | import java.util.stream.Collectors; 13 | 14 | /** 15 | * @author duq 16 | * @date 2022/7/19 17 | */ 18 | public class TreeUtils { 19 | public static List buildMenuTree(List allMenus) { 20 | if (allMenus == null || allMenus.isEmpty()) { 21 | return new ArrayList<>(); 22 | } 23 | return getMenuChildren(allMenus, null); 24 | } 25 | 26 | public static List buildDeptTree(List allDepts) { 27 | if (allDepts == null || allDepts.isEmpty()) { 28 | return new ArrayList<>(); 29 | } 30 | return getDeptChildren(allDepts, null); 31 | } 32 | 33 | private static List getMenuChildren(List allMenus, String parentId) { 34 | if (allMenus == null || allMenus.isEmpty()) { 35 | return new ArrayList<>(); 36 | } 37 | return allMenus.stream() 38 | .filter(menu -> StringUtils.isBlank(parentId) ? StringUtils.isBlank(menu.getParentId()) : Objects.equals(parentId, menu.getParentId())) 39 | .map(SysMenu::of) 40 | .peek(sysMenu -> { 41 | sysMenu.setChildren(getMenuChildren(allMenus, sysMenu.getMenuId())); 42 | }) 43 | .collect(Collectors.toList()); 44 | } 45 | 46 | private static List getDeptChildren(List allDepts, String parentId) { 47 | if (allDepts == null || allDepts.isEmpty()) { 48 | return new ArrayList<>(); 49 | } 50 | return allDepts.stream() 51 | .filter(dept -> StringUtils.isBlank(parentId) ? StringUtils.isBlank(dept.getParentId()) : Objects.equals(parentId, dept.getParentId())) 52 | .map(SysDept::of) 53 | .peek(sysDept -> { 54 | sysDept.setChildren(getDeptChildren(allDepts, sysDept.getDeptId())); 55 | }) 56 | .collect(Collectors.toList()); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/PageController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import io.swagger.annotations.Api; 4 | import io.swagger.annotations.ApiOperation; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | /** 13 | * @author admin 14 | * @date 2022/7/17 15 | */ 16 | @Slf4j 17 | @Controller 18 | @Api(tags = "页面导航") 19 | public class PageController { 20 | 21 | @GetMapping("/") 22 | @ApiOperation("首页") 23 | public String index(HttpServletRequest request) { 24 | String url = request.getRequestURI(); 25 | url = "redirect:" + url + (url.endsWith("/") ? "" : "/") + "web/"; 26 | log.info("url:{}", url); 27 | return url; 28 | } 29 | 30 | @GetMapping("/web/") 31 | @ApiOperation("web端页面") 32 | public String web() { 33 | return "web/index"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/SysConfigController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.dqv5.soccer.common.AuthValue; 5 | import com.dqv5.soccer.common.RestReturn; 6 | import com.dqv5.soccer.common.RestReturnEntity; 7 | import com.dqv5.soccer.service.SysConfigService; 8 | import com.dqv5.soccer.table.SysConfigTable; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiOperation; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.security.access.prepost.PreAuthorize; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.annotation.Resource; 17 | import java.util.List; 18 | 19 | /** 20 | * @author duq 21 | * @date 2024/1/16 22 | */ 23 | @RestController 24 | @Api(tags = "系统配置") 25 | @RequestMapping("/api/config") 26 | @Slf4j 27 | public class SysConfigController { 28 | @Resource 29 | private SysConfigService sysConfigService; 30 | 31 | @GetMapping("/allList") 32 | @ApiOperation("获取所有配置") 33 | @PreAuthorize("hasAuthority('" + AuthValue.SYS_CONFIG_QUERY + "')") 34 | public ResponseEntity>> allList() { 35 | List list = sysConfigService.queryAll(); 36 | return RestReturn.ok(list); 37 | } 38 | 39 | @GetMapping("/allMap") 40 | @ApiOperation("获取所有配置") 41 | @PreAuthorize("hasAuthority('" + AuthValue.SYS_CONFIG_QUERY + "')") 42 | public ResponseEntity> allMap() { 43 | List list = sysConfigService.queryAll(); 44 | JSONObject result = new JSONObject(); 45 | for (SysConfigTable sysConfigTable : list) { 46 | result.put(sysConfigTable.getConfigKey(), sysConfigTable.getConfigValue()); 47 | } 48 | return RestReturn.ok(result); 49 | } 50 | 51 | @PostMapping("/set") 52 | @ApiOperation("保存配置") 53 | @PreAuthorize("hasAuthority('" + AuthValue.SYS_CONFIG_SET + "')") 54 | public ResponseEntity> insert(@RequestBody JSONObject param) { 55 | sysConfigService.setConfig(param); 56 | return RestReturn.ok(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/SysController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import com.dqv5.soccer.common.AuthValue; 4 | import com.dqv5.soccer.common.ConfigValue; 5 | import com.dqv5.soccer.common.RestReturn; 6 | import com.dqv5.soccer.common.RestReturnEntity; 7 | import com.dqv5.soccer.pojo.SysInfo; 8 | import com.dqv5.soccer.service.InitDataService; 9 | import com.dqv5.soccer.service.SysConfigService; 10 | import com.dqv5.soccer.table.SysConfigTable; 11 | import io.swagger.annotations.Api; 12 | import io.swagger.annotations.ApiOperation; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.security.access.prepost.PreAuthorize; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RequestMapping; 19 | import org.springframework.web.bind.annotation.RestController; 20 | 21 | import javax.annotation.Resource; 22 | import java.util.List; 23 | 24 | /** 25 | * @author duqian 26 | * @date 2022/7/19 27 | */ 28 | @RestController 29 | @RequestMapping("/api/sys") 30 | @Slf4j 31 | @Api(tags = "系统管理") 32 | public class SysController { 33 | @Resource 34 | private InitDataService initDataService; 35 | @Resource 36 | private SysConfigService sysConfigService; 37 | 38 | @GetMapping("/info") 39 | @ApiOperation("获取系统基本信息") 40 | public ResponseEntity> info() { 41 | SysInfo sysInfo = sysConfigService.getSysInfo(); 42 | return RestReturn.ok(sysInfo); 43 | } 44 | 45 | @PostMapping("/reInitData") 46 | @ApiOperation("重新初始化系统数据") 47 | @PreAuthorize("hasAuthority('" + AuthValue.SYS_RE_INIT_DATA + "')") 48 | public ResponseEntity> reInitData() { 49 | initDataService.initData(true); 50 | return RestReturn.ok(); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/SysFileController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import com.dqv5.soccer.common.RestReturn; 4 | import com.dqv5.soccer.common.RestReturnEntity; 5 | import com.dqv5.soccer.pojo.SysFile; 6 | import com.dqv5.soccer.service.SysFileService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | import org.springframework.web.multipart.MultipartFile; 13 | 14 | import javax.annotation.Resource; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | /** 18 | * @author duqian 19 | * @date 2024/1/23 20 | */ 21 | @RestController 22 | @RequestMapping("/api/file") 23 | @Slf4j 24 | @Api(tags = "文件管理") 25 | public class SysFileController { 26 | @Resource 27 | private SysFileService sysFileService; 28 | 29 | @PostMapping("/upload") 30 | @ApiOperation(value = "上传文件", notes = "返回文件地址") 31 | public ResponseEntity> uploadFile(@RequestParam MultipartFile file) { 32 | SysFile sysFile = sysFileService.uploadFile(file); 33 | return RestReturn.ok(sysFile); 34 | } 35 | 36 | @GetMapping("/info/{id}") 37 | @ApiOperation("获取文件信息") 38 | public ResponseEntity> getFileInfo(@PathVariable String id) { 39 | SysFile sysFile = sysFileService.getFileInfo(id); 40 | return RestReturn.ok(sysFile); 41 | } 42 | 43 | @GetMapping("/file/{id}") 44 | @ApiOperation("获取文件") 45 | public void downloadFile(@PathVariable String id, String dl, HttpServletResponse response) { 46 | sysFileService.downloadFile(id, dl, response); 47 | } 48 | 49 | @PostMapping("/delete/{id}") 50 | @ApiOperation("删除文件") 51 | public ResponseEntity> deleteFile(@PathVariable String id) { 52 | sysFileService.deleteFile(id); 53 | return RestReturn.ok(); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/SysLogController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import com.dqv5.soccer.common.AuthValue; 4 | import com.dqv5.soccer.common.RestReturn; 5 | import com.dqv5.soccer.common.RestReturnEntity; 6 | import com.dqv5.soccer.table.SysLogTable; 7 | import com.dqv5.soccer.service.SysLogService; 8 | import com.github.pagehelper.PageInfo; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiOperation; 11 | import lombok.extern.slf4j.Slf4j; 12 | import com.dqv5.soccer.common.Pageable; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.security.access.prepost.PreAuthorize; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.RequestMapping; 17 | import org.springframework.web.bind.annotation.RequestParam; 18 | import org.springframework.web.bind.annotation.RestController; 19 | 20 | import javax.annotation.Resource; 21 | 22 | /** 23 | * @author duqian 24 | * @date 2022/7/19 25 | */ 26 | @RestController 27 | @RequestMapping("/api/log") 28 | @Api(tags = "系统日志") 29 | @Slf4j 30 | public class SysLogController { 31 | @Resource 32 | private SysLogService sysLogService; 33 | 34 | @GetMapping("/list") 35 | @ApiOperation("获取日志列表") 36 | @PreAuthorize("hasAuthority('" + AuthValue.SYS_LOG_QUERY + "')") 37 | public ResponseEntity>> list(@RequestParam(defaultValue = "1") int pageNum, 38 | @RequestParam(defaultValue = "10") int pageSize) { 39 | Pageable pageable = Pageable.of(pageNum, pageSize); 40 | PageInfo pageInfo = sysLogService.queryListForPage(pageable); 41 | return RestReturn.ok(pageInfo); 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /soccer-server/src/main/java/com/dqv5/soccer/web/SysProfileController.java: -------------------------------------------------------------------------------- 1 | package com.dqv5.soccer.web; 2 | 3 | import com.dqv5.soccer.common.RestReturn; 4 | import com.dqv5.soccer.common.RestReturnEntity; 5 | import com.dqv5.soccer.pojo.ChangePasswordParam; 6 | import com.dqv5.soccer.pojo.UpdateProfileParam; 7 | import com.dqv5.soccer.security.AuthUser; 8 | import com.dqv5.soccer.service.SysProfileService; 9 | import com.dqv5.soccer.utils.SecurityUtils; 10 | import io.swagger.annotations.Api; 11 | import io.swagger.annotations.ApiOperation; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.annotation.Resource; 17 | 18 | /** 19 | * @author admin 20 | * @date 2024/1/22 21 | */ 22 | @Slf4j 23 | @RestController 24 | @Api(tags = "用户信息接口") 25 | @RequestMapping("/api/profile") 26 | public class SysProfileController { 27 | @Resource 28 | private SysProfileService sysProfileService; 29 | 30 | @GetMapping("/userInfo") 31 | @ApiOperation("获取用户信息") 32 | public ResponseEntity> userInfo() { 33 | AuthUser authUser = SecurityUtils.getCurrentUserDetail(); 34 | return RestReturn.ok(authUser); 35 | } 36 | 37 | @PostMapping("/updateProfile") 38 | @ApiOperation("更新用户信息") 39 | public ResponseEntity> updateProfile(@RequestBody UpdateProfileParam param) { 40 | sysProfileService.updateProfile(param); 41 | return RestReturn.ok(); 42 | } 43 | 44 | @PostMapping("/changePassword") 45 | @ApiOperation("用户修改密码") 46 | public ResponseEntity> changePassword(@RequestBody ChangePasswordParam param) { 47 | sysProfileService.changePassword(param); 48 | return RestReturn.ok(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/application-h2.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | datasource: 5 | driver-class-name: org.h2.Driver 6 | # url: jdbc:h2:tcp://localhost:9092/E:\workspace_personal\spring-boot-angular\1.data\soccer 7 | url: jdbc:h2:mem:soccer 8 | username: sa 9 | password: 111111 10 | logging: 11 | level: 12 | root: info 13 | com.dqv5: debug 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/application-pg.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | datasource: 5 | driver-class-name: org.postgresql.Driver 6 | url: jdbc:postgresql://localhost:5432/soccer 7 | username: postgres 8 | password: 123456 9 | logging: 10 | level: 11 | root: info 12 | com.dqv5: debug 13 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | datasource: 5 | driver-class-name: org.postgresql.Driver 6 | url: jdbc:postgresql://localhost:5432/soccer 7 | username: postgres 8 | password: 123456 9 | logging: 10 | file: 11 | path: logs 12 | logback: 13 | rollingpolicy: 14 | max-history: 365 15 | max-file-size: 50MB 16 | level: 17 | root: info 18 | com.dqv5: info 19 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: / 5 | spring: 6 | mvc: 7 | pathmatch: 8 | matching-strategy: ANT_PATH_MATCHER 9 | application: 10 | name: soccer-server 11 | thymeleaf: 12 | prefix: classpath:/static/ 13 | datasource: 14 | driver-class-name: org.h2.Driver 15 | url: jdbc:h2:mem:soccer 16 | username: sa 17 | password: 111111 18 | liquibase: 19 | enabled: true 20 | change-log: classpath:liquibase/common/db.changelog-master.xml 21 | database-change-log-table: LIQUIBASE_CHANGELOG 22 | database-change-log-lock-table: LIQUIBASE_CHANGELOG_LOCK 23 | servlet: 24 | multipart: 25 | max-file-size: 10MB 26 | max-request-size: 10MB 27 | web: 28 | resources: 29 | cache: 30 | cachecontrol: 31 | cache-public: true 32 | max-age: 86400 33 | knife4j: 34 | enable: true 35 | mybatis-plus: 36 | mapper-locations: classpath:/mapper/sqlMap/*.xml 37 | config-location: classpath:/mapper/mybatis-config.xml 38 | logging: 39 | pattern: 40 | console: '%d{yyyy-MM-dd HH:mm:ss} %clr(%5p) [%12.12t] %clr(%-50.50logger{49}){cyan} [%5.5L] : %m%n%wEx' 41 | level: 42 | root: info 43 | com.dqv5: debug 44 | 45 | soccer: 46 | system: 47 | log: true 48 | file-store: 49 | default: disk 50 | disk: 51 | enable: true 52 | root: /opt/soccer/file 53 | s3: 54 | enable: true 55 | endpoint: http://127.0.0.1:9000 56 | bucketName: soccer 57 | accessKey: minioadmin 58 | secretKey: minioadmin 59 | 60 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/files/ipipfree.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-server/src/main/resources/files/ipipfree.ipdb -------------------------------------------------------------------------------- /soccer-server/src/main/resources/liquibase/common/db.changelog-master.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/sqlMap/SysAuthMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 22 | 38 | 39 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/sqlMap/SysDeptMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/sqlMap/SysMenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 21 | 22 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/sqlMap/SysRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/mapper/sqlMap/SysUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 22 | 23 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/assets/logo-color.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ]> 6 | 10 | 11 | 12 | 15 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | ]> 6 | 10 | 11 | 12 | 15 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/assets/tmp/app-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Soccer", 4 | "description": "Springboot + Angular 开发框架" 5 | }, 6 | "user": { 7 | "name": "Admin", 8 | "avatar": "./assets/tmp/img/avatar.jpg", 9 | "email": "duqian42707@163.com" 10 | }, 11 | "menu": [ 12 | { 13 | "text": "主导航", 14 | "group": true, 15 | "hideInBreadcrumb": true, 16 | "children": [ 17 | { 18 | "text": "仪表盘", 19 | "icon": "anticon-dashboard", 20 | "children": [ 21 | { 22 | "text": "仪表盘", 23 | "link": "/dashboard" 24 | } 25 | ] 26 | }, 27 | { 28 | "text": "系统管理", 29 | "icon": "anticon-setting", 30 | "shortcutRoot": true, 31 | "children": [ 32 | { 33 | "text": "用户管理", 34 | "link": "/sys/user" 35 | }, 36 | { 37 | "text": "角色管理", 38 | "link": "/sys/role" 39 | }, 40 | { 41 | "text": "菜单管理", 42 | "link": "/sys/menu" 43 | }, 44 | { 45 | "text": "权限管理", 46 | "link": "/sys/auth" 47 | }, 48 | { 49 | "text": "系统日志", 50 | "link": "/sys/log" 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/assets/tmp/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-server/src/main/resources/static/web/assets/tmp/img/avatar.jpg -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/assets/zorro.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /soccer-server/src/main/resources/static/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duqian42707/spring-boot-angular/0869520eb3d71f543a4b2e797332be93a2a113e0/soccer-server/src/main/resources/static/web/favicon.ico --------------------------------------------------------------------------------