commit 304a6db5a51b91cbd68a81edeb6d194ec2170eef Author: unknown <610015241@qq.com> Date: Tue Dec 19 17:20:09 2023 +0800 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/cyf.sql b/cyf.sql new file mode 100644 index 0000000..19b4fef --- /dev/null +++ b/cyf.sql @@ -0,0 +1,194 @@ +-- MySQL dump 10.13 Distrib 8.0.34, for Win64 (x86_64) +-- +-- Host: 127.0.0.1 Database: xdb +-- ------------------------------------------------------ +-- Server version 8.0.34 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `x_equip` +-- + +DROP TABLE IF EXISTS `x_equip`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_equip` ( + `id` int NOT NULL AUTO_INCREMENT, + `form` varchar(100) DEFAULT NULL COMMENT 'form', + `focal` varchar(50) DEFAULT NULL, + `status` int DEFAULT NULL, + `deleted` int DEFAULT '0', + `x1` varchar(50) DEFAULT NULL, + `x2` varchar(50) DEFAULT NULL, + `x3` varchar(1000) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_equip` +-- + +LOCK TABLES `x_equip` WRITE; +/*!40000 ALTER TABLE `x_equip` DISABLE KEYS */; +INSERT INTO `x_equip` VALUES (3,'string','string',0,0,'string','string','string'),(4,'string','string',0,0,'string','string','string'),(5,'11','1',1,0,'11','11',NULL),(6,'4','3',NULL,0,NULL,'2',NULL),(7,'2',NULL,NULL,0,NULL,'5',NULL),(8,NULL,'1',0,1,NULL,'1234',NULL); +/*!40000 ALTER TABLE `x_equip` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `x_menu` +-- + +DROP TABLE IF EXISTS `x_menu`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_menu` ( + `menu_id` int NOT NULL AUTO_INCREMENT, + `component` varchar(100) DEFAULT NULL, + `path` varchar(100) DEFAULT NULL, + `redirect` varchar(100) DEFAULT NULL, + `name` varchar(100) DEFAULT NULL, + `title` varchar(100) DEFAULT NULL, + `icon` varchar(100) DEFAULT NULL, + `parent_id` int DEFAULT NULL, + `is_leaf` varchar(1) DEFAULT NULL, + `hidden` tinyint(1) DEFAULT NULL, + PRIMARY KEY (`menu_id`) +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_menu` +-- + +LOCK TABLES `x_menu` WRITE; +/*!40000 ALTER TABLE `x_menu` DISABLE KEYS */; +INSERT INTO `x_menu` VALUES (1,'Layout','/sys','/sys/user','sysManage','系统管理','userManage',0,'N',0),(2,'sys/user','user',NULL,'userList','用户列表','user',1,'Y',0),(3,'sys/role','role',NULL,'roleList','角色列表','roleManage',1,'Y',0),(4,'Layout','/test','/test/test1','test','功能测试','form',0,'N',0),(5,'test/test1','test1','','test1','测试点一','form',4,'Y',0),(6,'test/test2','test2','','test2','测试点二','form',4,'Y',0),(7,'test/test3','test3','','test3','测试点三','form',4,'Y',0); +/*!40000 ALTER TABLE `x_menu` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `x_role` +-- + +DROP TABLE IF EXISTS `x_role`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_role` ( + `role_id` int NOT NULL AUTO_INCREMENT, + `role_name` varchar(50) DEFAULT NULL, + `role_desc` varchar(100) DEFAULT NULL, + PRIMARY KEY (`role_id`) +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_role` +-- + +LOCK TABLES `x_role` WRITE; +/*!40000 ALTER TABLE `x_role` DISABLE KEYS */; +INSERT INTO `x_role` VALUES (1,'admin','超级管理员'),(3,'normal','普通用户'),(11,'researcher','科研人员'); +/*!40000 ALTER TABLE `x_role` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `x_role_menu` +-- + +DROP TABLE IF EXISTS `x_role_menu`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_role_menu` ( + `id` int NOT NULL AUTO_INCREMENT, + `role_id` int DEFAULT NULL, + `menu_id` int DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_role_menu` +-- + +LOCK TABLES `x_role_menu` WRITE; +/*!40000 ALTER TABLE `x_role_menu` DISABLE KEYS */; +INSERT INTO `x_role_menu` VALUES (16,1,1),(17,1,2),(18,1,3),(19,1,4),(20,1,5),(21,1,6),(22,1,7); +/*!40000 ALTER TABLE `x_role_menu` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `x_user` +-- + +DROP TABLE IF EXISTS `x_user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_user` ( + `id` int NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL, + `password` varchar(100) DEFAULT NULL, + `email` varchar(50) DEFAULT NULL, + `phone` varchar(20) DEFAULT NULL, + `status` int DEFAULT NULL, + `avatar` varchar(200) DEFAULT NULL, + `deleted` int DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb3; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_user` +-- + +LOCK TABLES `x_user` WRITE; +/*!40000 ALTER TABLE `x_user` DISABLE KEYS */; +INSERT INTO `x_user` VALUES (1,'admin','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','super@aliyun.com','18677778888',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',0),(2,'zhangsan','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','zhangsan@gmail.com','13966667777',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',1),(3,'lisi','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','lisi@gmail.com','13966667778',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',1),(4,'wangwu','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','wangwu@gmail.com','13966667772',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',1),(5,'zhaoer','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','zhaoer@gmail.com','13966667776',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',1),(6,'songliu','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','songliu@gmail.com','13966667771',1,'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',1),(7,'cyf','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','cyf@123.com','188',1,NULL,1),(8,'cyf','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','123@123.com','123',1,NULL,1),(9,'cyf1','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','1@1.com','123',0,NULL,1),(10,'12312','$2a$10$Sst9zuvoY19Dqp80/sDusO3SgPJ4He.XGI3N/tPNuySXa.xbtAsC.','1@1.com','123',1,NULL,1),(11,'xxx','$2a$10$Yv4VHO49/EFjvDJcGAiD7.pMFktkJKbaY1J0oZhy5.rxh8lvJPTTi','1@1.com','123333',0,NULL,1),(12,'test1','$2a$10$BT0OW2KzYwa4a18r1MJfiuYGYCAsMOFKTmdthxhxwcRgCUlmklbem','1@2.com','01111',1,NULL,1),(13,'12344','$2a$10$qJImekfPKUpAudL4.4NdLe6rMukVKTVySb/EOZFXSHDo1APb/3XHe','1@1.com','0',NULL,NULL,1),(14,'cyf1','$2a$10$IR7DZbw.8g7edttjZHk6teeRICcnHoe7n28eZQ83O0oMBDlGKklR.','1@1.com','12',1,NULL,1),(15,'cyf','$2a$10$gF2wNB6qu5xe.eUggHUFduTYVYTXMcKwi.dKPv7UhLfLRUqS8BDrK','0@0.com','0',1,NULL,0),(16,'string','$2a$10$Cp5QGRR0TNdmbSHZBDRyv.x7NLC1AxHMLNc2C2j4VfZUckrxTP7n.','string','string',0,'string',0); +/*!40000 ALTER TABLE `x_user` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `x_user_role` +-- + +DROP TABLE IF EXISTS `x_user_role`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `x_user_role` ( + `id` int NOT NULL AUTO_INCREMENT, + `user_id` int DEFAULT NULL, + `role_id` int DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `x_user_role` +-- + +LOCK TABLES `x_user_role` WRITE; +/*!40000 ALTER TABLE `x_user_role` DISABLE KEYS */; +INSERT INTO `x_user_role` VALUES (1,1,1),(13,16,0),(14,15,11); +/*!40000 ALTER TABLE `x_user_role` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2023-12-19 16:27:03 diff --git a/x-admin-web/.editorconfig b/x-admin-web/.editorconfig new file mode 100644 index 0000000..ea6e20f --- /dev/null +++ b/x-admin-web/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/x-admin-web/.env.development b/x-admin-web/.env.development new file mode 100644 index 0000000..7dc17ea --- /dev/null +++ b/x-admin-web/.env.development @@ -0,0 +1,5 @@ +# just a flag +ENV = 'development' + +# base api +VUE_APP_BASE_API = 'http://localhost:9999' diff --git a/x-admin-web/.env.production b/x-admin-web/.env.production new file mode 100644 index 0000000..80c8103 --- /dev/null +++ b/x-admin-web/.env.production @@ -0,0 +1,6 @@ +# just a flag +ENV = 'production' + +# base api +VUE_APP_BASE_API = '/prod-api' + diff --git a/x-admin-web/.env.staging b/x-admin-web/.env.staging new file mode 100644 index 0000000..a8793a0 --- /dev/null +++ b/x-admin-web/.env.staging @@ -0,0 +1,8 @@ +NODE_ENV = production + +# just a flag +ENV = 'staging' + +# base api +VUE_APP_BASE_API = '/stage-api' + diff --git a/x-admin-web/.eslintignore b/x-admin-web/.eslintignore new file mode 100644 index 0000000..e6529fc --- /dev/null +++ b/x-admin-web/.eslintignore @@ -0,0 +1,4 @@ +build/*.js +src/assets +public +dist diff --git a/x-admin-web/.eslintrc.js b/x-admin-web/.eslintrc.js new file mode 100644 index 0000000..c977505 --- /dev/null +++ b/x-admin-web/.eslintrc.js @@ -0,0 +1,198 @@ +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint', + sourceType: 'module' + }, + env: { + browser: true, + node: true, + es6: true, + }, + extends: ['plugin:vue/recommended', 'eslint:recommended'], + + // add your custom rules here + //it is base on https://github.com/vuejs/eslint-config-vue + rules: { + "vue/max-attributes-per-line": [2, { + "singleline": 10, + "multiline": { + "max": 1, + "allowFirstLine": false + } + }], + "vue/singleline-html-element-content-newline": "off", + "vue/multiline-html-element-content-newline":"off", + "vue/name-property-casing": ["error", "PascalCase"], + "vue/no-v-html": "off", + 'accessor-pairs': 2, + 'arrow-spacing': [2, { + 'before': true, + 'after': true + }], + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true + }], + 'camelcase': [0, { + 'properties': 'always' + }], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { + 'before': false, + 'after': true + }], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + 'curly': [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + 'eqeqeq': ["error", "always", {"null": "ignore"}], + 'generator-star-spacing': [2, { + 'before': true, + 'after': true + }], + 'handle-callback-err': [2, '^(err|error)$'], + 'indent': [2, 2, { + 'SwitchCase': 1 + }], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true + }], + 'keyword-spacing': [2, { + 'before': true, + 'after': true + }], + 'new-cap': [2, { + 'newIsCap': true, + 'capIsNew': false + }], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [2, { + 'allowLoop': false, + 'allowSwitch': false + }], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [2, { + 'max': 1 + }], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [2, { + 'defaultAssignment': false + }], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [2, { + 'vars': 'all', + 'args': 'none' + }], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [2, { + 'initialized': 'never' + }], + 'operator-linebreak': [2, 'after', { + 'overrides': { + '?': 'before', + ':': 'before' + } + }], + 'padded-blocks': [2, 'never'], + 'quotes': [2, 'single', { + 'avoidEscape': true, + 'allowTemplateLiterals': true + }], + 'semi': [2, 'never'], + 'semi-spacing': [2, { + 'before': false, + 'after': true + }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { + 'words': true, + 'nonwords': false + }], + 'spaced-comment': [2, 'always', { + 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] + }], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + 'yoda': [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': [2, 'always', { + objectsInObjects: false + }], + 'array-bracket-spacing': [2, 'never'] + } +} diff --git a/x-admin-web/.gitignore b/x-admin-web/.gitignore new file mode 100644 index 0000000..9ad28d2 --- /dev/null +++ b/x-admin-web/.gitignore @@ -0,0 +1,16 @@ +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +tests/**/coverage/ + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/x-admin-web/.travis.yml b/x-admin-web/.travis.yml new file mode 100644 index 0000000..f4be7a0 --- /dev/null +++ b/x-admin-web/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: 10 +script: npm run test +notifications: + email: false diff --git a/x-admin-web/LICENSE b/x-admin-web/LICENSE new file mode 100644 index 0000000..6151575 --- /dev/null +++ b/x-admin-web/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-present PanJiaChen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/x-admin-web/README-zh.md b/x-admin-web/README-zh.md new file mode 100644 index 0000000..5b6f7bd --- /dev/null +++ b/x-admin-web/README-zh.md @@ -0,0 +1,102 @@ +# vue-admin-template + +> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。 + +[线上地址](http://panjiachen.github.io/vue-admin-template) + +[国内访问](https://panjiachen.gitee.io/vue-admin-template) + +目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`。 + +## Extra + +如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control) + +## 相关项目 + +- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) + +- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) + +- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) + +- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312) + +写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目: + +- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2) +- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac) +- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35) +- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56) +- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836) + +## Build Setup + +```bash +# 克隆项目 +git clone https://github.com/PanJiaChen/vue-admin-template.git + +# 进入项目目录 +cd vue-admin-template + +# 安装依赖 +npm install + +# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 +npm install --registry=https://registry.npm.taobao.org + +# 启动服务 +npm run dev +``` + +浏览器访问 [http://localhost:9528](http://localhost:9528) + +## 发布 + +```bash +# 构建测试环境 +npm run build:stage + +# 构建生产环境 +npm run build:prod +``` + +## 其它 + +```bash +# 预览发布环境效果 +npm run preview + +# 预览发布环境效果 + 静态资源分析 +npm run preview -- --report + +# 代码格式检查 +npm run lint + +# 代码格式检查并自动修复 +npm run lint -- --fix +``` + +更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/) + +## 购买贴纸 + +你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。 + +## Demo + +![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) + +## Browsers support + +Modern browsers and Internet Explorer 10+. + +| [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | +| --------- | --------- | --------- | --------- | +| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions + +## License + +[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license. + +Copyright (c) 2017-present PanJiaChen diff --git a/x-admin-web/README.md b/x-admin-web/README.md new file mode 100644 index 0000000..b99f942 --- /dev/null +++ b/x-admin-web/README.md @@ -0,0 +1,91 @@ +# vue-admin-template + +English | [简体中文](./README-zh.md) + +> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint + +**Live demo:** http://panjiachen.github.io/vue-admin-template + + +**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`** + +## Build Setup + + +```bash +# clone the project +git clone https://github.com/PanJiaChen/vue-admin-template.git + +# enter the project directory +cd vue-admin-template + +# install dependency +npm install + +# develop +npm run dev +``` + +This will automatically open http://localhost:9528 + +## Build + +```bash +# build for test environment +npm run build:stage + +# build for production environment +npm run build:prod +``` + +## Advanced + +```bash +# preview the release environment effect +npm run preview + +# preview the release environment effect + static resource analysis +npm run preview -- --report + +# code format check +npm run lint + +# code format check and auto fix +npm run lint -- --fix +``` + +Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information + +## Demo + +![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) + +## Extra + +If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control) + +For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour)) + +## Related Project + +- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) + +- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) + +- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) + +- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312) + +## Browsers support + +Modern browsers and Internet Explorer 10+. + +| [IE / Edge](http://godban.github.io/browsers-support-badges/)
IE / Edge | [Firefox](http://godban.github.io/browsers-support-badges/)
Firefox | [Chrome](http://godban.github.io/browsers-support-badges/)
Chrome | [Safari](http://godban.github.io/browsers-support-badges/)
Safari | +| --------- | --------- | --------- | --------- | +| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions + +## License + +[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license. + +Copyright (c) 2017-present PanJiaChen diff --git a/x-admin-web/babel.config.js b/x-admin-web/babel.config.js new file mode 100644 index 0000000..fb82b27 --- /dev/null +++ b/x-admin-web/babel.config.js @@ -0,0 +1,14 @@ +module.exports = { + presets: [ + // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app + '@vue/cli-plugin-babel/preset' + ], + 'env': { + 'development': { + // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). + // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. + // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html + 'plugins': ['dynamic-import-node'] + } + } +} diff --git a/x-admin-web/build/index.js b/x-admin-web/build/index.js new file mode 100644 index 0000000..0c57de2 --- /dev/null +++ b/x-admin-web/build/index.js @@ -0,0 +1,35 @@ +const { run } = require('runjs') +const chalk = require('chalk') +const config = require('../vue.config.js') +const rawArgv = process.argv.slice(2) +const args = rawArgv.join(' ') + +if (process.env.npm_config_preview || rawArgv.includes('--preview')) { + const report = rawArgv.includes('--report') + + run(`vue-cli-service build ${args}`) + + const port = 9526 + const publicPath = config.publicPath + + var connect = require('connect') + var serveStatic = require('serve-static') + const app = connect() + + app.use( + publicPath, + serveStatic('./dist', { + index: ['index.html', '/'] + }) + ) + + app.listen(port, function () { + console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) + if (report) { + console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) + } + + }) +} else { + run(`vue-cli-service build ${args}`) +} diff --git a/x-admin-web/jest.config.js b/x-admin-web/jest.config.js new file mode 100644 index 0000000..143cdc8 --- /dev/null +++ b/x-admin-web/jest.config.js @@ -0,0 +1,24 @@ +module.exports = { + moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], + transform: { + '^.+\\.vue$': 'vue-jest', + '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': + 'jest-transform-stub', + '^.+\\.jsx?$': 'babel-jest' + }, + moduleNameMapper: { + '^@/(.*)$': '/src/$1' + }, + snapshotSerializers: ['jest-serializer-vue'], + testMatch: [ + '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' + ], + collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], + coverageDirectory: '/tests/unit/coverage', + // 'collectCoverage': true, + 'coverageReporters': [ + 'lcov', + 'text-summary' + ], + testURL: 'http://localhost/' +} diff --git a/x-admin-web/jsconfig.json b/x-admin-web/jsconfig.json new file mode 100644 index 0000000..ed079e2 --- /dev/null +++ b/x-admin-web/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": ["src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/x-admin-web/mock/index.js b/x-admin-web/mock/index.js new file mode 100644 index 0000000..c514c13 --- /dev/null +++ b/x-admin-web/mock/index.js @@ -0,0 +1,57 @@ +const Mock = require('mockjs') +const { param2Obj } = require('./utils') + +const user = require('./user') +const table = require('./table') + +const mocks = [ + ...user, + ...table +] + +// for front mock +// please use it cautiously, it will redefine XMLHttpRequest, +// which will cause many of your third-party libraries to be invalidated(like progress event). +function mockXHR() { + // mock patch + // https://github.com/nuysoft/Mock/issues/300 + Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send + Mock.XHR.prototype.send = function() { + if (this.custom.xhr) { + this.custom.xhr.withCredentials = this.withCredentials || false + + if (this.responseType) { + this.custom.xhr.responseType = this.responseType + } + } + this.proxy_send(...arguments) + } + + function XHR2ExpressReqWrap(respond) { + return function(options) { + let result = null + if (respond instanceof Function) { + const { body, type, url } = options + // https://expressjs.com/en/4x/api.html#req + result = respond({ + method: type, + body: JSON.parse(body), + query: param2Obj(url) + }) + } else { + result = respond + } + return Mock.mock(result) + } + } + + for (const i of mocks) { + Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) + } +} + +module.exports = { + mocks, + mockXHR +} + diff --git a/x-admin-web/mock/mock-server.js b/x-admin-web/mock/mock-server.js new file mode 100644 index 0000000..8941ec0 --- /dev/null +++ b/x-admin-web/mock/mock-server.js @@ -0,0 +1,81 @@ +const chokidar = require('chokidar') +const bodyParser = require('body-parser') +const chalk = require('chalk') +const path = require('path') +const Mock = require('mockjs') + +const mockDir = path.join(process.cwd(), 'mock') + +function registerRoutes(app) { + let mockLastIndex + const { mocks } = require('./index.js') + const mocksForServer = mocks.map(route => { + return responseFake(route.url, route.type, route.response) + }) + for (const mock of mocksForServer) { + app[mock.type](mock.url, mock.response) + mockLastIndex = app._router.stack.length + } + const mockRoutesLength = Object.keys(mocksForServer).length + return { + mockRoutesLength: mockRoutesLength, + mockStartIndex: mockLastIndex - mockRoutesLength + } +} + +function unregisterRoutes() { + Object.keys(require.cache).forEach(i => { + if (i.includes(mockDir)) { + delete require.cache[require.resolve(i)] + } + }) +} + +// for mock server +const responseFake = (url, type, respond) => { + return { + url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`), + type: type || 'get', + response(req, res) { + console.log('request invoke:' + req.path) + res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) + } + } +} + +module.exports = app => { + // parse app.body + // https://expressjs.com/en/4x/api.html#req.body + app.use(bodyParser.json()) + app.use(bodyParser.urlencoded({ + extended: true + })) + + const mockRoutes = registerRoutes(app) + var mockRoutesLength = mockRoutes.mockRoutesLength + var mockStartIndex = mockRoutes.mockStartIndex + + // watch files, hot reload mock server + chokidar.watch(mockDir, { + ignored: /mock-server/, + ignoreInitial: true + }).on('all', (event, path) => { + if (event === 'change' || event === 'add') { + try { + // remove mock routes stack + app._router.stack.splice(mockStartIndex, mockRoutesLength) + + // clear routes cache + unregisterRoutes() + + const mockRoutes = registerRoutes(app) + mockRoutesLength = mockRoutes.mockRoutesLength + mockStartIndex = mockRoutes.mockStartIndex + + console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) + } catch (error) { + console.log(chalk.redBright(error)) + } + } + }) +} diff --git a/x-admin-web/mock/table.js b/x-admin-web/mock/table.js new file mode 100644 index 0000000..bd0e013 --- /dev/null +++ b/x-admin-web/mock/table.js @@ -0,0 +1,29 @@ +const Mock = require('mockjs') + +const data = Mock.mock({ + 'items|30': [{ + id: '@id', + title: '@sentence(10, 20)', + 'status|1': ['published', 'draft', 'deleted'], + author: 'name', + display_time: '@datetime', + pageviews: '@integer(300, 5000)' + }] +}) + +module.exports = [ + { + url: '/vue-admin-template/table/list', + type: 'get', + response: config => { + const items = data.items + return { + code: 20000, + data: { + total: items.length, + items: items + } + } + } + } +] diff --git a/x-admin-web/mock/user.js b/x-admin-web/mock/user.js new file mode 100644 index 0000000..7555338 --- /dev/null +++ b/x-admin-web/mock/user.js @@ -0,0 +1,84 @@ + +const tokens = { + admin: { + token: 'admin-token' + }, + editor: { + token: 'editor-token' + } +} + +const users = { + 'admin-token': { + roles: ['admin'], + introduction: 'I am a super administrator', + avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + name: 'Super Admin' + }, + 'editor-token': { + roles: ['editor'], + introduction: 'I am an editor', + avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', + name: 'Normal Editor' + } +} + +module.exports = [ + // user login + { + url: '/vue-admin-template/user/login', + type: 'post', + response: config => { + const { username } = config.body + const token = tokens[username] + + // mock error + if (!token) { + return { + code: 60204, + message: 'Account and password are incorrect.' + } + } + + return { + code: 20000, + data: token + } + } + }, + + // get user info + { + url: '/vue-admin-template/user/info\.*', + type: 'get', + response: config => { + const { token } = config.query + const info = users[token] + + // mock error + if (!info) { + return { + code: 50008, + message: 'Login failed, unable to get user details.' + } + } + + return { + code: 20000, + data: info + } + } + }, + + // user logout + { + url: '/vue-admin-template/user/logout', + type: 'post', + response: _ => { + return { + code: 20000, + data: 'success' + } + } + } +] diff --git a/x-admin-web/mock/utils.js b/x-admin-web/mock/utils.js new file mode 100644 index 0000000..95cc27d --- /dev/null +++ b/x-admin-web/mock/utils.js @@ -0,0 +1,25 @@ +/** + * @param {string} url + * @returns {Object} + */ +function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +module.exports = { + param2Obj +} diff --git a/x-admin-web/package.json b/x-admin-web/package.json new file mode 100644 index 0000000..2413824 --- /dev/null +++ b/x-admin-web/package.json @@ -0,0 +1,62 @@ +{ + "name": "vue-admin-template", + "version": "4.4.0", + "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint", + "author": "Pan ", + "scripts": { + "dev": "vue-cli-service serve", + "build:prod": "vue-cli-service build", + "build:stage": "vue-cli-service build --mode staging", + "preview": "node build/index.js --preview", + "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", + "lint": "eslint --ext .js,.vue src", + "test:unit": "jest --clearCache && vue-cli-service test:unit", + "test:ci": "npm run lint && npm run test:unit" + }, + "dependencies": { + "axios": "0.18.1", + "core-js": "3.6.5", + "element-ui": "2.13.2", + "js-cookie": "2.2.0", + "normalize.css": "7.0.0", + "nprogress": "0.2.0", + "path-to-regexp": "2.4.0", + "vue": "2.6.10", + "vue-router": "3.0.6", + "vuex": "3.1.0" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "4.4.4", + "@vue/cli-plugin-eslint": "4.4.4", + "@vue/cli-plugin-unit-jest": "4.4.4", + "@vue/cli-service": "4.4.4", + "@vue/test-utils": "1.0.0-beta.29", + "autoprefixer": "9.5.1", + "babel-eslint": "10.1.0", + "babel-jest": "23.6.0", + "babel-plugin-dynamic-import-node": "2.3.3", + "chalk": "2.4.2", + "connect": "3.6.6", + "eslint": "6.7.2", + "eslint-plugin-vue": "6.2.2", + "html-webpack-plugin": "3.2.0", + "mockjs": "1.0.1-beta3", + "runjs": "4.3.2", + "sass": "1.26.8", + "sass-loader": "8.0.2", + "script-ext-html-webpack-plugin": "2.1.3", + "serve-static": "1.13.2", + "svg-sprite-loader": "4.1.3", + "svgo": "1.2.2", + "vue-template-compiler": "2.6.10" + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ], + "engines": { + "node": ">=8.9", + "npm": ">= 3.0.0" + }, + "license": "MIT" +} diff --git a/x-admin-web/postcss.config.js b/x-admin-web/postcss.config.js new file mode 100644 index 0000000..10473ef --- /dev/null +++ b/x-admin-web/postcss.config.js @@ -0,0 +1,8 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + 'plugins': { + // to edit target browsers: use "browserslist" field in package.json + 'autoprefixer': {} + } +} diff --git a/x-admin-web/public/favicon.ico b/x-admin-web/public/favicon.ico new file mode 100644 index 0000000..34b63ac Binary files /dev/null and b/x-admin-web/public/favicon.ico differ diff --git a/x-admin-web/public/index.html b/x-admin-web/public/index.html new file mode 100644 index 0000000..fa2be91 --- /dev/null +++ b/x-admin-web/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + <%= webpackConfig.name %> + + + +
+ + + diff --git a/x-admin-web/src/App.vue b/x-admin-web/src/App.vue new file mode 100644 index 0000000..0199c69 --- /dev/null +++ b/x-admin-web/src/App.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/x-admin-web/src/api/equipManage.js b/x-admin-web/src/api/equipManage.js new file mode 100644 index 0000000..6e2d4ba --- /dev/null +++ b/x-admin-web/src/api/equipManage.js @@ -0,0 +1,50 @@ +import request from '@/utils/request' + +export default{ + getEquipList(searchModel){ + return request({ + url: '/equip/list', + method: 'get', + params:{ + pageNo: searchModel.pageNo, + pageSize: searchModel.pageSize, + focal: searchModel.focal, + status: searchModel.status + } + }); + }, + addEquip(equip){ + return request({ + url: '/equip', + method: 'post', + data: equip + }); + }, + updateEquip(equip){ + return request({ + url: '/equip', + method: 'put', + data: equip + }); + }, + saveEquip(equip){ + if(equip.id == null && equip.id == undefined){ + return this.addEquip(equip); + } + return this.updateEquip(equip); + }, + getEquipById(id){ + return request({ + //url: '/equip/' + id, + url: `/equip/${id}`, + method: 'get' + }); + }, + deleteEquipById(id){ + return request({ + url: `/equip/${id}`, + method: 'delete' + }); + }, + +} \ No newline at end of file diff --git a/x-admin-web/src/api/menuManage.js b/x-admin-web/src/api/menuManage.js new file mode 100644 index 0000000..10ec046 --- /dev/null +++ b/x-admin-web/src/api/menuManage.js @@ -0,0 +1,10 @@ +import request from '@/utils/request' + +export default{ + getAllMenu(){ + return request({ + url: '/menu', + method: 'get' + }); + } +} \ No newline at end of file diff --git a/x-admin-web/src/api/roleManage.js b/x-admin-web/src/api/roleManage.js new file mode 100644 index 0000000..f6851be --- /dev/null +++ b/x-admin-web/src/api/roleManage.js @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +export default{ + getRoleList(searchModel){ + return request({ + url: '/role/list', + method: 'get', + params:{ + pageNo: searchModel.pageNo, + pageSize: searchModel.pageSize, + roleName: searchModel.roleName + } + }); + }, + addRole(role){ + return request({ + url: '/role', + method: 'post', + data: role + }); + }, + updateRole(role){ + return request({ + url: '/role', + method: 'put', + data: role + }); + }, + saveRole(role){ + if(role.roleId == null && role.roleId == undefined){ + return this.addRole(role); + } + return this.updateRole(role); + }, + getRoleById(id){ + return request({ + url: `/role/${id}`, + method: 'get' + }); + }, + deleteRoleById(id){ + return request({ + url: `/role/${id}`, + method: 'delete' + }); + }, + getAllRoleList(){ + return request({ + url: '/role/all', + method: 'get' + }); + }, +} \ No newline at end of file diff --git a/x-admin-web/src/api/table.js b/x-admin-web/src/api/table.js new file mode 100644 index 0000000..2752f52 --- /dev/null +++ b/x-admin-web/src/api/table.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getList(params) { + return request({ + url: '/vue-admin-template/table/list', + method: 'get', + params + }) +} diff --git a/x-admin-web/src/api/user.js b/x-admin-web/src/api/user.js new file mode 100644 index 0000000..de69f70 --- /dev/null +++ b/x-admin-web/src/api/user.js @@ -0,0 +1,24 @@ +import request from '@/utils/request' + +export function login(data) { + return request({ + url: '/user/login', + method: 'post', + data + }) +} + +export function getInfo(token) { + return request({ + url: '/user/info', + method: 'get', + params: { token } + }) +} + +export function logout() { + return request({ + url: '/user/logout', + method: 'post' + }) +} diff --git a/x-admin-web/src/api/userManage.js b/x-admin-web/src/api/userManage.js new file mode 100644 index 0000000..a6e2b68 --- /dev/null +++ b/x-admin-web/src/api/userManage.js @@ -0,0 +1,49 @@ +import request from '@/utils/request' + +export default{ + getUserList(searchModel){ + return request({ + url: '/user/list', + method: 'get', + params:{ + pageNo: searchModel.pageNo, + pageSize: searchModel.pageSize, + username: searchModel.username, + phone: searchModel.phone + } + }); + }, + addUser(user){ + return request({ + url: '/user', + method: 'post', + data: user + }); + }, + updateUser(user){ + return request({ + url: '/user', + method: 'put', + data: user + }); + }, + saveUser(user){ + if(user.id == null && user.id == undefined){ + return this.addUser(user); + } + return this.updateUser(user); + }, + getUserById(id){ + return request({ + //url: '/user/' + id, + url: `/user/${id}`, + method: 'get' + }); + }, + deleteUserById(id){ + return request({ + url: `/user/${id}`, + method: 'delete' + }); + }, +} \ No newline at end of file diff --git a/x-admin-web/src/assets/404_images/404.png b/x-admin-web/src/assets/404_images/404.png new file mode 100644 index 0000000..3d8e230 Binary files /dev/null and b/x-admin-web/src/assets/404_images/404.png differ diff --git a/x-admin-web/src/assets/404_images/404_cloud.png b/x-admin-web/src/assets/404_images/404_cloud.png new file mode 100644 index 0000000..c6281d0 Binary files /dev/null and b/x-admin-web/src/assets/404_images/404_cloud.png differ diff --git a/x-admin-web/src/assets/bg.jpg b/x-admin-web/src/assets/bg.jpg new file mode 100644 index 0000000..44c5987 Binary files /dev/null and b/x-admin-web/src/assets/bg.jpg differ diff --git a/x-admin-web/src/components/Breadcrumb/index.vue b/x-admin-web/src/components/Breadcrumb/index.vue new file mode 100644 index 0000000..66360ca --- /dev/null +++ b/x-admin-web/src/components/Breadcrumb/index.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/x-admin-web/src/components/Hamburger/index.vue b/x-admin-web/src/components/Hamburger/index.vue new file mode 100644 index 0000000..368b002 --- /dev/null +++ b/x-admin-web/src/components/Hamburger/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/x-admin-web/src/components/SvgIcon/index.vue b/x-admin-web/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..b07ded2 --- /dev/null +++ b/x-admin-web/src/components/SvgIcon/index.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/x-admin-web/src/icons/index.js b/x-admin-web/src/icons/index.js new file mode 100644 index 0000000..2c6b309 --- /dev/null +++ b/x-admin-web/src/icons/index.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import SvgIcon from '@/components/SvgIcon'// svg component + +// register globally +Vue.component('svg-icon', SvgIcon) + +const req = require.context('./svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys().map(requireContext) +requireAll(req) diff --git a/x-admin-web/src/icons/svg/dashboard.svg b/x-admin-web/src/icons/svg/dashboard.svg new file mode 100644 index 0000000..5317d37 --- /dev/null +++ b/x-admin-web/src/icons/svg/dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/example.svg b/x-admin-web/src/icons/svg/example.svg new file mode 100644 index 0000000..46f42b5 --- /dev/null +++ b/x-admin-web/src/icons/svg/example.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/eye-open.svg b/x-admin-web/src/icons/svg/eye-open.svg new file mode 100644 index 0000000..88dcc98 --- /dev/null +++ b/x-admin-web/src/icons/svg/eye-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/eye.svg b/x-admin-web/src/icons/svg/eye.svg new file mode 100644 index 0000000..16ed2d8 --- /dev/null +++ b/x-admin-web/src/icons/svg/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/form.svg b/x-admin-web/src/icons/svg/form.svg new file mode 100644 index 0000000..dcbaa18 --- /dev/null +++ b/x-admin-web/src/icons/svg/form.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/link.svg b/x-admin-web/src/icons/svg/link.svg new file mode 100644 index 0000000..48197ba --- /dev/null +++ b/x-admin-web/src/icons/svg/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/nested.svg b/x-admin-web/src/icons/svg/nested.svg new file mode 100644 index 0000000..06713a8 --- /dev/null +++ b/x-admin-web/src/icons/svg/nested.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/password.svg b/x-admin-web/src/icons/svg/password.svg new file mode 100644 index 0000000..e291d85 --- /dev/null +++ b/x-admin-web/src/icons/svg/password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/roleManage.svg b/x-admin-web/src/icons/svg/roleManage.svg new file mode 100644 index 0000000..d608969 --- /dev/null +++ b/x-admin-web/src/icons/svg/roleManage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/sys.svg b/x-admin-web/src/icons/svg/sys.svg new file mode 100644 index 0000000..f1b21fc --- /dev/null +++ b/x-admin-web/src/icons/svg/sys.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/table.svg b/x-admin-web/src/icons/svg/table.svg new file mode 100644 index 0000000..0e3dc9d --- /dev/null +++ b/x-admin-web/src/icons/svg/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/tree.svg b/x-admin-web/src/icons/svg/tree.svg new file mode 100644 index 0000000..dd4b7dd --- /dev/null +++ b/x-admin-web/src/icons/svg/tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/user.svg b/x-admin-web/src/icons/svg/user.svg new file mode 100644 index 0000000..0ba0716 --- /dev/null +++ b/x-admin-web/src/icons/svg/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svg/userManage.svg b/x-admin-web/src/icons/svg/userManage.svg new file mode 100644 index 0000000..f1b21fc --- /dev/null +++ b/x-admin-web/src/icons/svg/userManage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-admin-web/src/icons/svgo.yml b/x-admin-web/src/icons/svgo.yml new file mode 100644 index 0000000..d11906a --- /dev/null +++ b/x-admin-web/src/icons/svgo.yml @@ -0,0 +1,22 @@ +# replace default config + +# multipass: true +# full: true + +plugins: + + # - name + # + # or: + # - name: false + # - name: true + # + # or: + # - name: + # param1: 1 + # param2: 2 + +- removeAttrs: + attrs: + - 'fill' + - 'fill-rule' diff --git a/x-admin-web/src/layout/components/AppMain.vue b/x-admin-web/src/layout/components/AppMain.vue new file mode 100644 index 0000000..32dceff --- /dev/null +++ b/x-admin-web/src/layout/components/AppMain.vue @@ -0,0 +1,45 @@ + + + + + + + diff --git a/x-admin-web/src/layout/components/Navbar.vue b/x-admin-web/src/layout/components/Navbar.vue new file mode 100644 index 0000000..d11ce9c --- /dev/null +++ b/x-admin-web/src/layout/components/Navbar.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/x-admin-web/src/layout/components/Sidebar/FixiOSBug.js b/x-admin-web/src/layout/components/Sidebar/FixiOSBug.js new file mode 100644 index 0000000..bc14856 --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/FixiOSBug.js @@ -0,0 +1,26 @@ +export default { + computed: { + device() { + return this.$store.state.app.device + } + }, + mounted() { + // In order to fix the click on menu on the ios device will trigger the mouseleave bug + // https://github.com/PanJiaChen/vue-element-admin/issues/1135 + this.fixBugIniOS() + }, + methods: { + fixBugIniOS() { + const $subMenu = this.$refs.subMenu + if ($subMenu) { + const handleMouseleave = $subMenu.handleMouseleave + $subMenu.handleMouseleave = (e) => { + if (this.device === 'mobile') { + return + } + handleMouseleave(e) + } + } + } + } +} diff --git a/x-admin-web/src/layout/components/Sidebar/Item.vue b/x-admin-web/src/layout/components/Sidebar/Item.vue new file mode 100644 index 0000000..aa1f5da --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/Item.vue @@ -0,0 +1,41 @@ + + + diff --git a/x-admin-web/src/layout/components/Sidebar/Link.vue b/x-admin-web/src/layout/components/Sidebar/Link.vue new file mode 100644 index 0000000..530b3d5 --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/Link.vue @@ -0,0 +1,43 @@ + + + diff --git a/x-admin-web/src/layout/components/Sidebar/Logo.vue b/x-admin-web/src/layout/components/Sidebar/Logo.vue new file mode 100644 index 0000000..148775e --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/Logo.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/x-admin-web/src/layout/components/Sidebar/SidebarItem.vue b/x-admin-web/src/layout/components/Sidebar/SidebarItem.vue new file mode 100644 index 0000000..a418c3d --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/SidebarItem.vue @@ -0,0 +1,95 @@ + + + diff --git a/x-admin-web/src/layout/components/Sidebar/index.vue b/x-admin-web/src/layout/components/Sidebar/index.vue new file mode 100644 index 0000000..52847d0 --- /dev/null +++ b/x-admin-web/src/layout/components/Sidebar/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/x-admin-web/src/layout/components/TagsView/ScrollPane.vue b/x-admin-web/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..0d5ac5a --- /dev/null +++ b/x-admin-web/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/x-admin-web/src/layout/components/TagsView/index.vue b/x-admin-web/src/layout/components/TagsView/index.vue new file mode 100644 index 0000000..897564e --- /dev/null +++ b/x-admin-web/src/layout/components/TagsView/index.vue @@ -0,0 +1,310 @@ + + + + + + + diff --git a/x-admin-web/src/layout/components/index.js b/x-admin-web/src/layout/components/index.js new file mode 100644 index 0000000..9fc98d6 --- /dev/null +++ b/x-admin-web/src/layout/components/index.js @@ -0,0 +1,4 @@ +export { default as Navbar } from './Navbar' +export { default as Sidebar } from './Sidebar' +export { default as AppMain } from './AppMain' +export { default as TagsView } from './TagsView' diff --git a/x-admin-web/src/layout/index.vue b/x-admin-web/src/layout/index.vue new file mode 100644 index 0000000..00c9246 --- /dev/null +++ b/x-admin-web/src/layout/index.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/x-admin-web/src/layout/mixin/ResizeHandler.js b/x-admin-web/src/layout/mixin/ResizeHandler.js new file mode 100644 index 0000000..e8d0df8 --- /dev/null +++ b/x-admin-web/src/layout/mixin/ResizeHandler.js @@ -0,0 +1,45 @@ +import store from '@/store' + +const { body } = document +const WIDTH = 992 // refer to Bootstrap's responsive design + +export default { + watch: { + $route(route) { + if (this.device === 'mobile' && this.sidebar.opened) { + store.dispatch('app/closeSideBar', { withoutAnimation: false }) + } + } + }, + beforeMount() { + window.addEventListener('resize', this.$_resizeHandler) + }, + beforeDestroy() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + mounted() { + const isMobile = this.$_isMobile() + if (isMobile) { + store.dispatch('app/toggleDevice', 'mobile') + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_isMobile() { + const rect = body.getBoundingClientRect() + return rect.width - 1 < WIDTH + }, + $_resizeHandler() { + if (!document.hidden) { + const isMobile = this.$_isMobile() + store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') + + if (isMobile) { + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + } + } + } +} diff --git a/x-admin-web/src/main.js b/x-admin-web/src/main.js new file mode 100644 index 0000000..c5d6f13 --- /dev/null +++ b/x-admin-web/src/main.js @@ -0,0 +1,43 @@ +import Vue from 'vue' + +import 'normalize.css/normalize.css' // A modern alternative to CSS resets + +import ElementUI from 'element-ui' +import 'element-ui/lib/theme-chalk/index.css' +import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n + +import '@/styles/index.scss' // global css + +import App from './App' +import store from './store' +import router from './router' + +import '@/icons' // icon +import '@/permission' // permission control + +/** + * If you don't want to use mock-server + * you want to use MockJs for mock api + * you can execute: mockXHR() + * + * Currently MockJs will be used in the production environment, + * please remove it before going online ! ! ! + */ +if (process.env.NODE_ENV === 'production') { + const { mockXHR } = require('../mock') + mockXHR() +} + +// set ElementUI lang to EN +Vue.use(ElementUI, { locale }) +// 如果想要中文版 element-ui,按如下方式声明 +// Vue.use(ElementUI) + +Vue.config.productionTip = false + +new Vue({ + el: '#app', + router, + store, + render: h => h(App) +}) diff --git a/x-admin-web/src/permission.js b/x-admin-web/src/permission.js new file mode 100644 index 0000000..9279100 --- /dev/null +++ b/x-admin-web/src/permission.js @@ -0,0 +1,98 @@ +import router from './router' +import store from './store' +import { Message } from 'element-ui' +import NProgress from 'nprogress' // progress bar +import 'nprogress/nprogress.css' // progress bar style +import { getToken } from '@/utils/auth' // get token from cookie +import getPageTitle from '@/utils/get-page-title' + +import Layout from '@/layout' + +NProgress.configure({ showSpinner: false }) // NProgress Configuration + +const whiteList = ['/login'] // no redirect whitelist + +router.beforeEach(async(to, from, next) => { + // start progress bar + NProgress.start() + + // set page title + document.title = getPageTitle(to.meta.title) + + // determine whether the user has logged in + const hasToken = getToken() + + if (hasToken) { + if (to.path === '/login') { + // if is logged in, redirect to the home page + next({ path: '/' }) + NProgress.done() + } else { + const hasGetUserInfo = store.getters.name + if (hasGetUserInfo) { + next() + } else { + try { + // get user info + await store.dispatch('user/getInfo') + + // 路由转换 + let myRoutes = myFilterAsyncRoutes(store.getters.menuList); + // 404 + myRoutes.push({ + path: '*', + redirect: '/404', + hidden: true + }); + // 动态添加路由 + router.addRoutes(myRoutes); + // 存至全局变量 + global.myRoutes = myRoutes; + + next({...to,replace:true}) // 防止刷新后页面空白 + //next() + } catch (error) { + // remove token and go to login page to re-login + await store.dispatch('user/resetToken') + Message.error(error || 'Has Error') + next(`/login?redirect=${to.path}`) + NProgress.done() + } + } + } + } else { + /* has no token*/ + + if (whiteList.indexOf(to.path) !== -1) { + // in the free login whitelist, go directly + next() + } else { + // other pages that do not have permission to access are redirected to the login page. + next(`/login?redirect=${to.path}`) + NProgress.done() + } + } +}) + +router.afterEach(() => { + // finish progress bar + NProgress.done() +}) + + +function myFilterAsyncRoutes(menuList) { + menuList.filter(menu => { + if (menu.component === 'Layout') { + menu.component = Layout + console.log(menu.component); + } else { + menu.component = require(`@/views/${menu.component}.vue`).default + } + // 递归处理子菜单 + if (menu.children && menu.children.length) { + menu.children = myFilterAsyncRoutes(menu.children) + } + return true + }) + return menuList; +} diff --git a/x-admin-web/src/router/index.js b/x-admin-web/src/router/index.js new file mode 100644 index 0000000..2c4034c --- /dev/null +++ b/x-admin-web/src/router/index.js @@ -0,0 +1,120 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +/* Layout */ +import Layout from '@/layout' + +/** + * Note: sub-menu only appear when route children.length >= 1 + * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html + * + * hidden: true if set true, item will not show in the sidebar(default is false) + * alwaysShow: true if set true, will always show the root menu + * if not set alwaysShow, when item has more than one children route, + * it will becomes nested mode, otherwise not show the root menu + * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb + * name:'router-name' the name is used by (must set!!!) + * meta : { + roles: ['admin','editor'] control the page roles (you can set multiple roles) + title: 'title' the name show in sidebar and breadcrumb (recommend set) + icon: 'svg-name'/'el-icon-x' the icon show in the sidebar + breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) + activeMenu: '/example/list' if set path, the sidebar will highlight the path you set + } + */ + +/** + * constantRoutes + * a base page that does not have permission requirements + * all roles can be accessed + */ +export const constantRoutes = [ + { + path: '/login', + component: () => import('@/views/login/index'), + hidden: true + }, + + { + path: '/404', + component: () => import('@/views/404'), + hidden: true + }, + + { + path: '/', + component: Layout, + redirect: '/dashboard', + children: [{ + path: 'dashboard', + name: 'Dashboard', + component: () => import('@/views/dashboard/index'), + meta: { title: '主页', icon: 'dashboard' ,affix: true} + }] + }, + { + path: '/', + component: Layout, + redirect: '/', + children: [{ + path: 'workbench', + name: 'workbench', + component: () => import('@/views/workbench/workbench'), + meta: { title: '个人工作台', icon: 'dashboard' ,affix: true} + }] + }, + + { + path: '/', + component: Layout, + redirect: '/equipment', + children: [{ + path: 'equipment', + name: 'Dashboard', + component: () => import('@/views/equipment/equilist'), + meta: { title: '设备列表', icon: 'dashboard' ,affix: true} + }] + }, + { + path: '/', + component: Layout, + redirect: '/task', + children: [{ + path: 'task', + name: 'task', + component: () => import('@/views/task/task'), + meta: { title: '数据查询', icon: 'dashboard' ,affix: true} + }] + }, + { + path: '/', + component: Layout, + redirect: '/task', + children: [{ + path: 'task', + name: 'task', + component: () => import('@/views/task/task'), + meta: { title: '审计日志', icon: 'dashboard' ,affix: true} + }] + }, + + +] + +const createRouter = () => new Router({ + // mode: 'history', // require service support + scrollBehavior: () => ({ y: 0 }), + routes: constantRoutes +}) + +const router = createRouter() + +// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465 +export function resetRouter() { + const newRouter = createRouter() + router.matcher = newRouter.matcher // reset router +} + +export default router diff --git a/x-admin-web/src/settings.js b/x-admin-web/src/settings.js new file mode 100644 index 0000000..1fecd1a --- /dev/null +++ b/x-admin-web/src/settings.js @@ -0,0 +1,16 @@ +module.exports = { + + title: '智能动作采集平台', + + /** + * @type {boolean} true | false + * @description Whether fix the header + */ + fixedHeader: false, + + /** + * @type {boolean} true | false + * @description Whether show the logo in sidebar + */ + sidebarLogo: false +} diff --git a/x-admin-web/src/store/getters.js b/x-admin-web/src/store/getters.js new file mode 100644 index 0000000..8f07c7a --- /dev/null +++ b/x-admin-web/src/store/getters.js @@ -0,0 +1,13 @@ +const getters = { + sidebar: state => state.app.sidebar, + device: state => state.app.device, + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + menuList: state => state.user.menuList, + + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, + permission_routes: state => state.permission.routes +} +export default getters diff --git a/x-admin-web/src/store/index.js b/x-admin-web/src/store/index.js new file mode 100644 index 0000000..bf429a5 --- /dev/null +++ b/x-admin-web/src/store/index.js @@ -0,0 +1,21 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import getters from './getters' +import app from './modules/app' +import settings from './modules/settings' +import user from './modules/user' +import tagsView from './modules/tagsView' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + app, + settings, + user, + tagsView + }, + getters +}) + +export default store diff --git a/x-admin-web/src/store/modules/app.js b/x-admin-web/src/store/modules/app.js new file mode 100644 index 0000000..7ea7e33 --- /dev/null +++ b/x-admin-web/src/store/modules/app.js @@ -0,0 +1,48 @@ +import Cookies from 'js-cookie' + +const state = { + sidebar: { + opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, + withoutAnimation: false + }, + device: 'desktop' +} + +const mutations = { + TOGGLE_SIDEBAR: state => { + state.sidebar.opened = !state.sidebar.opened + state.sidebar.withoutAnimation = false + if (state.sidebar.opened) { + Cookies.set('sidebarStatus', 1) + } else { + Cookies.set('sidebarStatus', 0) + } + }, + CLOSE_SIDEBAR: (state, withoutAnimation) => { + Cookies.set('sidebarStatus', 0) + state.sidebar.opened = false + state.sidebar.withoutAnimation = withoutAnimation + }, + TOGGLE_DEVICE: (state, device) => { + state.device = device + } +} + +const actions = { + toggleSideBar({ commit }) { + commit('TOGGLE_SIDEBAR') + }, + closeSideBar({ commit }, { withoutAnimation }) { + commit('CLOSE_SIDEBAR', withoutAnimation) + }, + toggleDevice({ commit }, device) { + commit('TOGGLE_DEVICE', device) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/x-admin-web/src/store/modules/permission.js b/x-admin-web/src/store/modules/permission.js new file mode 100644 index 0000000..aeb5ee5 --- /dev/null +++ b/x-admin-web/src/store/modules/permission.js @@ -0,0 +1,69 @@ +import { asyncRoutes, constantRoutes } from '@/router' + +/** + * Use meta.role to determine if the current user has permission + * @param roles + * @param route + */ +function hasPermission(roles, route) { + if (route.meta && route.meta.roles) { + return roles.some(role => route.meta.roles.includes(role)) + } else { + return true + } +} + +/** + * Filter asynchronous routing tables by recursion + * @param routes asyncRoutes + * @param roles + */ +export function filterAsyncRoutes(routes, roles) { + const res = [] + + routes.forEach(route => { + const tmp = { ...route } + if (hasPermission(roles, tmp)) { + if (tmp.children) { + tmp.children = filterAsyncRoutes(tmp.children, roles) + } + res.push(tmp) + } + }) + + return res +} + +const state = { + routes: [], + addRoutes: [] +} + +const mutations = { + SET_ROUTES: (state, routes) => { + state.addRoutes = routes + state.routes = constantRoutes.concat(routes) + } +} + +const actions = { + generateRoutes({ commit }, roles) { + return new Promise(resolve => { + let accessedRoutes + if (roles.includes('admin')) { + accessedRoutes = asyncRoutes || [] + } else { + accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) + } + commit('SET_ROUTES', accessedRoutes) + resolve(accessedRoutes) + }) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/x-admin-web/src/store/modules/settings.js b/x-admin-web/src/store/modules/settings.js new file mode 100644 index 0000000..b3f33f8 --- /dev/null +++ b/x-admin-web/src/store/modules/settings.js @@ -0,0 +1,32 @@ +import defaultSettings from '@/settings' + +const { showSettings, fixedHeader, sidebarLogo } = defaultSettings + +const state = { + showSettings: showSettings, + fixedHeader: fixedHeader, + sidebarLogo: sidebarLogo +} + +const mutations = { + CHANGE_SETTING: (state, { key, value }) => { + // eslint-disable-next-line no-prototype-builtins + if (state.hasOwnProperty(key)) { + state[key] = value + } + } +} + +const actions = { + changeSetting({ commit }, data) { + commit('CHANGE_SETTING', data) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/x-admin-web/src/store/modules/tagsView.js b/x-admin-web/src/store/modules/tagsView.js new file mode 100644 index 0000000..57e7242 --- /dev/null +++ b/x-admin-web/src/store/modules/tagsView.js @@ -0,0 +1,160 @@ +const state = { + visitedViews: [], + cachedViews: [] +} + +const mutations = { + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (!view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + }, + DEL_CACHED_VIEW: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + index > -1 && state.cachedViews.splice(index, 1) + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + if (index > -1) { + state.cachedViews = state.cachedViews.slice(index, index + 1) + } else { + // if index = -1, there is no cached tags + state.cachedViews = [] + } + }, + + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/x-admin-web/src/store/modules/user.js b/x-admin-web/src/store/modules/user.js new file mode 100644 index 0000000..110ad6a --- /dev/null +++ b/x-admin-web/src/store/modules/user.js @@ -0,0 +1,102 @@ +import { login, logout, getInfo } from '@/api/user' +import { getToken, setToken, removeToken } from '@/utils/auth' +import { resetRouter } from '@/router' + +const getDefaultState = () => { + return { + token: getToken(), + name: '', + avatar: '', + menuList: [] + } +} + +const state = getDefaultState() + +const mutations = { + RESET_STATE: (state) => { + Object.assign(state, getDefaultState()) + }, + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_MENU_LIST: (state, menuList) => { + state.menuList = menuList + } +} + +const actions = { + // user login + login({ commit }, userInfo) { + const { username, password } = userInfo + return new Promise((resolve, reject) => { + login({ username: username.trim(), password: password }).then(response => { + const { data } = response + commit('SET_TOKEN', data.token) + setToken(data.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // get user info + getInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo(state.token).then(response => { + const { data } = response + + if (!data) { + reject('Verification failed, please Login again.') + } + + const { name, avatar, menuList } = data + + commit('SET_NAME', name) + commit('SET_AVATAR', avatar) + commit('SET_MENU_LIST', menuList) + resolve(data) + }).catch(error => { + reject(error) + }) + }) + }, + + // user logout + logout({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + removeToken() // must remove token first + resetRouter() + commit('RESET_STATE') + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // remove token + resetToken({ commit }) { + return new Promise(resolve => { + removeToken() // must remove token first + commit('RESET_STATE') + resolve() + }) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/x-admin-web/src/styles/element-ui.scss b/x-admin-web/src/styles/element-ui.scss new file mode 100644 index 0000000..0062411 --- /dev/null +++ b/x-admin-web/src/styles/element-ui.scss @@ -0,0 +1,49 @@ +// cover some element-ui styles + +.el-breadcrumb__inner, +.el-breadcrumb__inner a { + font-weight: 400 !important; +} + +.el-upload { + input[type="file"] { + display: none !important; + } +} + +.el-upload__input { + display: none; +} + + +// to fixed https://github.com/ElemeFE/element/issues/2461 +.el-dialog { + transform: none; + left: 0; + position: relative; + margin: 0 auto; +} + +// refine element ui upload +.upload-container { + .el-upload { + width: 100%; + + .el-upload-dragger { + width: 100%; + height: 200px; + } + } +} + +// dropdown +.el-dropdown-menu { + a { + display: block + } +} + +// to fix el-date-picker css style +.el-range-separator { + box-sizing: content-box; +} diff --git a/x-admin-web/src/styles/index.scss b/x-admin-web/src/styles/index.scss new file mode 100644 index 0000000..3b4da51 --- /dev/null +++ b/x-admin-web/src/styles/index.scss @@ -0,0 +1,65 @@ +@import './variables.scss'; +@import './mixin.scss'; +@import './transition.scss'; +@import './element-ui.scss'; +@import './sidebar.scss'; + +body { + height: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; +} + +label { + font-weight: 700; +} + +html { + height: 100%; + box-sizing: border-box; +} + +#app { + height: 100%; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } +} + +// main-container global css +.app-container { + padding: 20px; +} diff --git a/x-admin-web/src/styles/mixin.scss b/x-admin-web/src/styles/mixin.scss new file mode 100644 index 0000000..36b74bb --- /dev/null +++ b/x-admin-web/src/styles/mixin.scss @@ -0,0 +1,28 @@ +@mixin clearfix { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin scrollBar { + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } +} + +@mixin relative { + position: relative; + width: 100%; + height: 100%; +} diff --git a/x-admin-web/src/styles/sidebar.scss b/x-admin-web/src/styles/sidebar.scss new file mode 100644 index 0000000..94760cc --- /dev/null +++ b/x-admin-web/src/styles/sidebar.scss @@ -0,0 +1,226 @@ +#app { + + .main-container { + min-height: 100%; + transition: margin-left .28s; + margin-left: $sideBarWidth; + position: relative; + } + + .sidebar-container { + transition: width 0.28s; + width: $sideBarWidth !important; + background-color: $menuBg; + height: 100%; + position: fixed; + font-size: 0px; + top: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: hidden; + + // reset element-ui css + .horizontal-collapse-transition { + transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; + } + + .scrollbar-wrapper { + overflow-x: hidden !important; + } + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + + .el-scrollbar { + height: 100%; + } + + &.has-logo { + .el-scrollbar { + height: calc(100% - 50px); + } + } + + .is-horizontal { + display: none; + } + + a { + display: inline-block; + width: 100%; + overflow: hidden; + } + + .svg-icon { + margin-right: 16px; + } + + .sub-el-icon { + margin-right: 12px; + margin-left: -2px; + } + + .el-menu { + border: none; + height: 100%; + width: 100% !important; + } + + // menu hover + .submenu-title-noDropdown, + .el-submenu__title { + &:hover { + background-color: $menuHover !important; + } + } + + .is-active>.el-submenu__title { + color: $subMenuActiveText !important; + } + + & .nest-menu .el-submenu>.el-submenu__title, + & .el-submenu .el-menu-item { + min-width: $sideBarWidth !important; + background-color: $subMenuBg !important; + + &:hover { + background-color: $subMenuHover !important; + } + } + } + + .hideSidebar { + .sidebar-container { + width: 54px !important; + } + + .main-container { + margin-left: 54px; + } + + .submenu-title-noDropdown { + padding: 0 !important; + position: relative; + + .el-tooltip { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + + .sub-el-icon { + margin-left: 19px; + } + } + } + + .el-submenu { + overflow: hidden; + + &>.el-submenu__title { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + + .sub-el-icon { + margin-left: 19px; + } + + .el-submenu__icon-arrow { + display: none; + } + } + } + + .el-menu--collapse { + .el-submenu { + &>.el-submenu__title { + &>span { + height: 0; + width: 0; + overflow: hidden; + visibility: hidden; + display: inline-block; + } + } + } + } + } + + .el-menu--collapse .el-menu .el-submenu { + min-width: $sideBarWidth !important; + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar-container { + transition: transform .28s; + width: $sideBarWidth !important; + } + + &.hideSidebar { + .sidebar-container { + pointer-events: none; + transition-duration: 0.3s; + transform: translate3d(-$sideBarWidth, 0, 0); + } + } + } + + .withoutAnimation { + + .main-container, + .sidebar-container { + transition: none; + } + } +} + +// when menu collapsed +.el-menu--vertical { + &>.el-menu { + .svg-icon { + margin-right: 16px; + } + .sub-el-icon { + margin-right: 12px; + margin-left: -2px; + } + } + + .nest-menu .el-submenu>.el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: $menuHover !important; + } + } + + // the scroll bar appears when the subMenu is too long + >.el-menu--popup { + max-height: 100vh; + overflow-y: auto; + + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } + } +} diff --git a/x-admin-web/src/styles/transition.scss b/x-admin-web/src/styles/transition.scss new file mode 100644 index 0000000..4cb27cc --- /dev/null +++ b/x-admin-web/src/styles/transition.scss @@ -0,0 +1,48 @@ +// global transition css + +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/* fade-transform */ +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all .5s; +} + +.fade-transform-enter { + opacity: 0; + transform: translateX(-30px); +} + +.fade-transform-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* breadcrumb transition */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all .5s; +} + +.breadcrumb-enter, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} + +.breadcrumb-move { + transition: all .5s; +} + +.breadcrumb-leave-active { + position: absolute; +} diff --git a/x-admin-web/src/styles/variables.scss b/x-admin-web/src/styles/variables.scss new file mode 100644 index 0000000..be55772 --- /dev/null +++ b/x-admin-web/src/styles/variables.scss @@ -0,0 +1,25 @@ +// sidebar +$menuText:#bfcbd9; +$menuActiveText:#409EFF; +$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951 + +$menuBg:#304156; +$menuHover:#263445; + +$subMenuBg:#1f2d3d; +$subMenuHover:#001528; + +$sideBarWidth: 210px; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + menuText: $menuText; + menuActiveText: $menuActiveText; + subMenuActiveText: $subMenuActiveText; + menuBg: $menuBg; + menuHover: $menuHover; + subMenuBg: $subMenuBg; + subMenuHover: $subMenuHover; + sideBarWidth: $sideBarWidth; +} diff --git a/x-admin-web/src/utils/auth.js b/x-admin-web/src/utils/auth.js new file mode 100644 index 0000000..059af18 --- /dev/null +++ b/x-admin-web/src/utils/auth.js @@ -0,0 +1,15 @@ +import Cookies from 'js-cookie' + +const TokenKey = 'vue_admin_template_token' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} diff --git a/x-admin-web/src/utils/get-page-title.js b/x-admin-web/src/utils/get-page-title.js new file mode 100644 index 0000000..64be362 --- /dev/null +++ b/x-admin-web/src/utils/get-page-title.js @@ -0,0 +1,10 @@ +import defaultSettings from '@/settings' + +const title = defaultSettings.title + +export default function getPageTitle(pageTitle) { + if (pageTitle) { + return `${pageTitle} - ${title}` + } + return `${title}` +} diff --git a/x-admin-web/src/utils/index.js b/x-admin-web/src/utils/index.js new file mode 100644 index 0000000..4830c04 --- /dev/null +++ b/x-admin-web/src/utils/index.js @@ -0,0 +1,117 @@ +/** + * Created by PanJiaChen on 16/11/18. + */ + +/** + * Parse the time to string + * @param {(Object|string|number)} time + * @param {string} cFormat + * @returns {string | null} + */ +export function parseTime(time, cFormat) { + if (arguments.length === 0 || !time) { + return null + } + const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string')) { + if ((/^[0-9]+$/.test(time))) { + // support "1548221490638" + time = parseInt(time) + } else { + // support safari + // https://stackoverflow.com/questions/4310953/invalid-date-in-safari + time = time.replace(new RegExp(/-/gm), '/') + } + } + + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { + const value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] } + return value.toString().padStart(2, '0') + }) + return time_str +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return ( + d.getMonth() + + 1 + + '月' + + d.getDate() + + '日' + + d.getHours() + + '时' + + d.getMinutes() + + '分' + ) + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} diff --git a/x-admin-web/src/utils/request.js b/x-admin-web/src/utils/request.js new file mode 100644 index 0000000..2fb95ac --- /dev/null +++ b/x-admin-web/src/utils/request.js @@ -0,0 +1,85 @@ +import axios from 'axios' +import { MessageBox, Message } from 'element-ui' +import store from '@/store' +import { getToken } from '@/utils/auth' + +// create an axios instance +const service = axios.create({ + baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url + // withCredentials: true, // send cookies when cross-domain requests + timeout: 5000 // request timeout +}) + +// request interceptor +service.interceptors.request.use( + config => { + // do something before request is sent + + if (store.getters.token) { + // let each request carry token + // ['X-Token'] is a custom headers key + // please modify it according to the actual situation + config.headers['X-Token'] = getToken() + } + return config + }, + error => { + // do something with request error + console.log(error) // for debug + return Promise.reject(error) + } +) + +// response interceptor +service.interceptors.response.use( + /** + * If you want to get http information such as headers or status + * Please return response => response + */ + + /** + * Determine the request status by custom code + * Here is just an example + * You can also judge the status by HTTP Status Code + */ + response => { + const res = response.data + + // if the custom code is not 20000, it is judged as an error. + if (res.code !== 20000) { + Message({ + message: res.message || 'Error', + type: 'error', + duration: 5 * 1000 + }) + + // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; + if (res.code === 50008 || res.code === 50012 || res.code === 50014) { + // to re-login + MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { + confirmButtonText: 'Re-Login', + cancelButtonText: 'Cancel', + type: 'warning' + }).then(() => { + store.dispatch('user/resetToken').then(() => { + location.reload() + }) + }) + } + return Promise.reject(new Error(res.message || 'Error')) + } else { + return res + } + }, + error => { + console.log('err' + error) // for debug + Message({ + message: error.message, + type: 'error', + duration: 5 * 1000 + }) + return Promise.reject(error) + } +) + +export default service diff --git a/x-admin-web/src/utils/validate.js b/x-admin-web/src/utils/validate.js new file mode 100644 index 0000000..0c7f643 --- /dev/null +++ b/x-admin-web/src/utils/validate.js @@ -0,0 +1,21 @@ +/** + * Created by PanJiaChen on 16/11/18. + */ + +/** + * @param {string} path + * @returns {Boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + // const valid_map = ['admin', 'editor'] + // return valid_map.indexOf(str.trim()) >= 0 + return true; +} diff --git a/x-admin-web/src/views/404.vue b/x-admin-web/src/views/404.vue new file mode 100644 index 0000000..1791f55 --- /dev/null +++ b/x-admin-web/src/views/404.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/x-admin-web/src/views/dashboard/index.vue b/x-admin-web/src/views/dashboard/index.vue new file mode 100644 index 0000000..f468272 --- /dev/null +++ b/x-admin-web/src/views/dashboard/index.vue @@ -0,0 +1,33 @@ + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/equipment/equilist.vue b/x-admin-web/src/views/equipment/equilist.vue new file mode 100644 index 0000000..c03bc91 --- /dev/null +++ b/x-admin-web/src/views/equipment/equilist.vue @@ -0,0 +1,233 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/form/index.vue b/x-admin-web/src/views/form/index.vue new file mode 100644 index 0000000..f4d66d3 --- /dev/null +++ b/x-admin-web/src/views/form/index.vue @@ -0,0 +1,85 @@ + + + + + + diff --git a/x-admin-web/src/views/login/index.vue b/x-admin-web/src/views/login/index.vue new file mode 100644 index 0000000..b88280f --- /dev/null +++ b/x-admin-web/src/views/login/index.vue @@ -0,0 +1,241 @@ + + + + + + + diff --git a/x-admin-web/src/views/nested/menu1/index.vue b/x-admin-web/src/views/nested/menu1/index.vue new file mode 100644 index 0000000..30cb670 --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/index.vue @@ -0,0 +1,7 @@ + diff --git a/x-admin-web/src/views/nested/menu1/menu1-1/index.vue b/x-admin-web/src/views/nested/menu1/menu1-1/index.vue new file mode 100644 index 0000000..27e173a --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/menu1-1/index.vue @@ -0,0 +1,7 @@ + diff --git a/x-admin-web/src/views/nested/menu1/menu1-2/index.vue b/x-admin-web/src/views/nested/menu1/menu1-2/index.vue new file mode 100644 index 0000000..0c86276 --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/menu1-2/index.vue @@ -0,0 +1,7 @@ + diff --git a/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue b/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue new file mode 100644 index 0000000..f87d88f --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue @@ -0,0 +1,5 @@ + diff --git a/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue b/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue new file mode 100644 index 0000000..d88789f --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue @@ -0,0 +1,5 @@ + diff --git a/x-admin-web/src/views/nested/menu1/menu1-3/index.vue b/x-admin-web/src/views/nested/menu1/menu1-3/index.vue new file mode 100644 index 0000000..f7cd073 --- /dev/null +++ b/x-admin-web/src/views/nested/menu1/menu1-3/index.vue @@ -0,0 +1,5 @@ + diff --git a/x-admin-web/src/views/nested/menu2/index.vue b/x-admin-web/src/views/nested/menu2/index.vue new file mode 100644 index 0000000..19dd48f --- /dev/null +++ b/x-admin-web/src/views/nested/menu2/index.vue @@ -0,0 +1,5 @@ + diff --git a/x-admin-web/src/views/sys/role.vue b/x-admin-web/src/views/sys/role.vue new file mode 100644 index 0000000..8f5a47f --- /dev/null +++ b/x-admin-web/src/views/sys/role.vue @@ -0,0 +1,265 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/sys/user.vue b/x-admin-web/src/views/sys/user.vue new file mode 100644 index 0000000..8d9dcf9 --- /dev/null +++ b/x-admin-web/src/views/sys/user.vue @@ -0,0 +1,294 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/table/index.vue b/x-admin-web/src/views/table/index.vue new file mode 100644 index 0000000..a1ed847 --- /dev/null +++ b/x-admin-web/src/views/table/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/x-admin-web/src/views/task/task.vue b/x-admin-web/src/views/task/task.vue new file mode 100644 index 0000000..fc48093 --- /dev/null +++ b/x-admin-web/src/views/task/task.vue @@ -0,0 +1,93 @@ + + + \ No newline at end of file diff --git a/x-admin-web/src/views/test/test1.vue b/x-admin-web/src/views/test/test1.vue new file mode 100644 index 0000000..6ed0d08 --- /dev/null +++ b/x-admin-web/src/views/test/test1.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/test/test2.vue b/x-admin-web/src/views/test/test2.vue new file mode 100644 index 0000000..319b0f7 --- /dev/null +++ b/x-admin-web/src/views/test/test2.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/test/test3.vue b/x-admin-web/src/views/test/test3.vue new file mode 100644 index 0000000..4bae5eb --- /dev/null +++ b/x-admin-web/src/views/test/test3.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/x-admin-web/src/views/tree/index.vue b/x-admin-web/src/views/tree/index.vue new file mode 100644 index 0000000..89c6b01 --- /dev/null +++ b/x-admin-web/src/views/tree/index.vue @@ -0,0 +1,78 @@ + + + + diff --git a/x-admin-web/src/views/workbench/workbench.vue b/x-admin-web/src/views/workbench/workbench.vue new file mode 100644 index 0000000..424cc65 --- /dev/null +++ b/x-admin-web/src/views/workbench/workbench.vue @@ -0,0 +1,61 @@ + + + \ No newline at end of file diff --git a/x-admin-web/tests/unit/.eslintrc.js b/x-admin-web/tests/unit/.eslintrc.js new file mode 100644 index 0000000..958d51b --- /dev/null +++ b/x-admin-web/tests/unit/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + jest: true + } +} diff --git a/x-admin-web/tests/unit/components/Breadcrumb.spec.js b/x-admin-web/tests/unit/components/Breadcrumb.spec.js new file mode 100644 index 0000000..1d94c8f --- /dev/null +++ b/x-admin-web/tests/unit/components/Breadcrumb.spec.js @@ -0,0 +1,98 @@ +import { mount, createLocalVue } from '@vue/test-utils' +import VueRouter from 'vue-router' +import ElementUI from 'element-ui' +import Breadcrumb from '@/components/Breadcrumb/index.vue' + +const localVue = createLocalVue() +localVue.use(VueRouter) +localVue.use(ElementUI) + +const routes = [ + { + path: '/', + name: 'home', + children: [{ + path: 'dashboard', + name: 'dashboard' + }] + }, + { + path: '/menu', + name: 'menu', + children: [{ + path: 'menu1', + name: 'menu1', + meta: { title: 'menu1' }, + children: [{ + path: 'menu1-1', + name: 'menu1-1', + meta: { title: 'menu1-1' } + }, + { + path: 'menu1-2', + name: 'menu1-2', + redirect: 'noredirect', + meta: { title: 'menu1-2' }, + children: [{ + path: 'menu1-2-1', + name: 'menu1-2-1', + meta: { title: 'menu1-2-1' } + }, + { + path: 'menu1-2-2', + name: 'menu1-2-2' + }] + }] + }] + }] + +const router = new VueRouter({ + routes +}) + +describe('Breadcrumb.vue', () => { + const wrapper = mount(Breadcrumb, { + localVue, + router + }) + it('dashboard', () => { + router.push('/dashboard') + const len = wrapper.findAll('.el-breadcrumb__inner').length + expect(len).toBe(1) + }) + it('normal route', () => { + router.push('/menu/menu1') + const len = wrapper.findAll('.el-breadcrumb__inner').length + expect(len).toBe(2) + }) + it('nested route', () => { + router.push('/menu/menu1/menu1-2/menu1-2-1') + const len = wrapper.findAll('.el-breadcrumb__inner').length + expect(len).toBe(4) + }) + it('no meta.title', () => { + router.push('/menu/menu1/menu1-2/menu1-2-2') + const len = wrapper.findAll('.el-breadcrumb__inner').length + expect(len).toBe(3) + }) + // it('click link', () => { + // router.push('/menu/menu1/menu1-2/menu1-2-2') + // const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') + // const second = breadcrumbArray.at(1) + // console.log(breadcrumbArray) + // const href = second.find('a').attributes().href + // expect(href).toBe('#/menu/menu1') + // }) + // it('noRedirect', () => { + // router.push('/menu/menu1/menu1-2/menu1-2-1') + // const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') + // const redirectBreadcrumb = breadcrumbArray.at(2) + // expect(redirectBreadcrumb.contains('a')).toBe(false) + // }) + it('last breadcrumb', () => { + router.push('/menu/menu1/menu1-2/menu1-2-1') + const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') + const redirectBreadcrumb = breadcrumbArray.at(3) + expect(redirectBreadcrumb.contains('a')).toBe(false) + }) +}) diff --git a/x-admin-web/tests/unit/components/Hamburger.spec.js b/x-admin-web/tests/unit/components/Hamburger.spec.js new file mode 100644 index 0000000..01ea303 --- /dev/null +++ b/x-admin-web/tests/unit/components/Hamburger.spec.js @@ -0,0 +1,18 @@ +import { shallowMount } from '@vue/test-utils' +import Hamburger from '@/components/Hamburger/index.vue' +describe('Hamburger.vue', () => { + it('toggle click', () => { + const wrapper = shallowMount(Hamburger) + const mockFn = jest.fn() + wrapper.vm.$on('toggleClick', mockFn) + wrapper.find('.hamburger').trigger('click') + expect(mockFn).toBeCalled() + }) + it('prop isActive', () => { + const wrapper = shallowMount(Hamburger) + wrapper.setProps({ isActive: true }) + expect(wrapper.contains('.is-active')).toBe(true) + wrapper.setProps({ isActive: false }) + expect(wrapper.contains('.is-active')).toBe(false) + }) +}) diff --git a/x-admin-web/tests/unit/components/SvgIcon.spec.js b/x-admin-web/tests/unit/components/SvgIcon.spec.js new file mode 100644 index 0000000..31467a9 --- /dev/null +++ b/x-admin-web/tests/unit/components/SvgIcon.spec.js @@ -0,0 +1,22 @@ +import { shallowMount } from '@vue/test-utils' +import SvgIcon from '@/components/SvgIcon/index.vue' +describe('SvgIcon.vue', () => { + it('iconClass', () => { + const wrapper = shallowMount(SvgIcon, { + propsData: { + iconClass: 'test' + } + }) + expect(wrapper.find('use').attributes().href).toBe('#icon-test') + }) + it('className', () => { + const wrapper = shallowMount(SvgIcon, { + propsData: { + iconClass: 'test' + } + }) + expect(wrapper.classes().length).toBe(1) + wrapper.setProps({ className: 'test' }) + expect(wrapper.classes().includes('test')).toBe(true) + }) +}) diff --git a/x-admin-web/tests/unit/utils/formatTime.spec.js b/x-admin-web/tests/unit/utils/formatTime.spec.js new file mode 100644 index 0000000..24e165b --- /dev/null +++ b/x-admin-web/tests/unit/utils/formatTime.spec.js @@ -0,0 +1,30 @@ +import { formatTime } from '@/utils/index.js' + +describe('Utils:formatTime', () => { + const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" + const retrofit = 5 * 1000 + + it('ten digits timestamp', () => { + expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分') + }) + it('test now', () => { + expect(formatTime(+new Date() - 1)).toBe('刚刚') + }) + it('less two minute', () => { + expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前') + }) + it('less two hour', () => { + expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前') + }) + it('less one day', () => { + expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前') + }) + it('more than one day', () => { + expect(formatTime(d)).toBe('7月13日17时54分') + }) + it('format', () => { + expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') + expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') + expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') + }) +}) diff --git a/x-admin-web/tests/unit/utils/param2Obj.spec.js b/x-admin-web/tests/unit/utils/param2Obj.spec.js new file mode 100644 index 0000000..e106ed8 --- /dev/null +++ b/x-admin-web/tests/unit/utils/param2Obj.spec.js @@ -0,0 +1,14 @@ +import { param2Obj } from '@/utils/index.js' +describe('Utils:param2Obj', () => { + const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95' + + it('param2Obj test', () => { + expect(param2Obj(url)).toEqual({ + name: 'bill', + age: '29', + sex: '1', + field: window.btoa('test'), + key: '测试' + }) + }) +}) diff --git a/x-admin-web/tests/unit/utils/parseTime.spec.js b/x-admin-web/tests/unit/utils/parseTime.spec.js new file mode 100644 index 0000000..56045af --- /dev/null +++ b/x-admin-web/tests/unit/utils/parseTime.spec.js @@ -0,0 +1,35 @@ +import { parseTime } from '@/utils/index.js' + +describe('Utils:parseTime', () => { + const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" + it('timestamp', () => { + expect(parseTime(d)).toBe('2018-07-13 17:54:01') + }) + it('timestamp string', () => { + expect(parseTime((d + ''))).toBe('2018-07-13 17:54:01') + }) + it('ten digits timestamp', () => { + expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01') + }) + it('new Date', () => { + expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01') + }) + it('format', () => { + expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') + expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') + expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') + }) + it('get the day of the week', () => { + expect(parseTime(d, '{a}')).toBe('五') // 星期五 + }) + it('get the day of the week', () => { + expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日 + }) + it('empty argument', () => { + expect(parseTime()).toBeNull() + }) + + it('null', () => { + expect(parseTime(null)).toBeNull() + }) +}) diff --git a/x-admin-web/tests/unit/utils/validate.spec.js b/x-admin-web/tests/unit/utils/validate.spec.js new file mode 100644 index 0000000..f774905 --- /dev/null +++ b/x-admin-web/tests/unit/utils/validate.spec.js @@ -0,0 +1,17 @@ +import { validUsername, isExternal } from '@/utils/validate.js' + +describe('Utils:validate', () => { + it('validUsername', () => { + expect(validUsername('admin')).toBe(true) + expect(validUsername('editor')).toBe(true) + expect(validUsername('xxxx')).toBe(false) + }) + it('isExternal', () => { + expect(isExternal('https://github.com/PanJiaChen/vue-element-admin')).toBe(true) + expect(isExternal('http://github.com/PanJiaChen/vue-element-admin')).toBe(true) + expect(isExternal('github.com/PanJiaChen/vue-element-admin')).toBe(false) + expect(isExternal('/dashboard')).toBe(false) + expect(isExternal('./dashboard')).toBe(false) + expect(isExternal('dashboard')).toBe(false) + }) +}) diff --git a/x-admin-web/vue.config.js b/x-admin-web/vue.config.js new file mode 100644 index 0000000..47e96f7 --- /dev/null +++ b/x-admin-web/vue.config.js @@ -0,0 +1,125 @@ +'use strict' +const path = require('path') +const defaultSettings = require('./src/settings.js') + +function resolve(dir) { + return path.join(__dirname, dir) +} + +const name = defaultSettings.title || 'vue Admin Template' // page title + +// If your port is set to 80, +// use administrator privileges to execute the command line. +// For example, Mac: sudo npm run +// You can change the port by the following methods: +// port = 9528 npm run dev OR npm run dev --port = 9528 +const port = 8888 // dev port + +// All configuration item explanations can be find in https://cli.vuejs.org/config/ +module.exports = { + /** + * You will need to set publicPath if you plan to deploy your site under a sub path, + * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/, + * then publicPath should be set to "/bar/". + * In most cases please use '/' !!! + * Detail: https://cli.vuejs.org/config/#publicpath + */ + publicPath: '/', + outputDir: 'dist', + assetsDir: 'static', + lintOnSave: false, + productionSourceMap: false, + devServer: { + port: port, + open: false, + overlay: { + warnings: false, + errors: true + }, + //before: require('./mock/mock-server.js') + }, + configureWebpack: { + // provide the app's title in webpack's name field, so that + // it can be accessed in index.html to inject the correct title. + name: name, + resolve: { + alias: { + '@': resolve('src') + } + } + }, + chainWebpack(config) { + // it can improve the speed of the first screen, it is recommended to turn on preload + // config.plugins.delete('preload') + + // when there are many pages, it will cause too many meaningless requests + config.plugins.delete('prefetch') + + // set svg-sprite-loader + config.module + .rule('svg') + .exclude.add(resolve('src/icons')) + .end() + config.module + .rule('icons') + .test(/\.svg$/) + .include.add(resolve('src/icons')) + .end() + .use('svg-sprite-loader') + .loader('svg-sprite-loader') + .options({ + symbolId: 'icon-[name]' + }) + .end() + + // set preserveWhitespace + config.module + .rule('vue') + .use('vue-loader') + .loader('vue-loader') + .tap(options => { + options.compilerOptions.preserveWhitespace = true + return options + }) + .end() + + config + .when(process.env.NODE_ENV !== 'development', + config => { + config + .plugin('ScriptExtHtmlWebpackPlugin') + .after('html') + .use('script-ext-html-webpack-plugin', [{ + // `runtime` must same as runtimeChunk name. default is `runtime` + inline: /runtime\..*\.js$/ + }]) + .end() + config + .optimization.splitChunks({ + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // only package third parties that are initially dependent + }, + elementUI: { + name: 'chunk-elementUI', // split elementUI into a single package + priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app + test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm + }, + commons: { + name: 'chunk-commons', + test: resolve('src/components'), // can customize your rules + minChunks: 3, // minimum common number + priority: 5, + reuseExistingChunk: true + } + } + }) + config.optimization.runtimeChunk('single') + } + ) + } +} diff --git a/x-admin/x-admin/.gitignore b/x-admin/x-admin/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/x-admin/x-admin/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/x-admin/x-admin/.mvn/wrapper/maven-wrapper.jar b/x-admin/x-admin/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..bf82ff0 Binary files /dev/null and b/x-admin/x-admin/.mvn/wrapper/maven-wrapper.jar differ diff --git a/x-admin/x-admin/.mvn/wrapper/maven-wrapper.properties b/x-admin/x-admin/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..ca5ab4b --- /dev/null +++ b/x-admin/x-admin/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/EquipController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/EquipController.java new file mode 100644 index 0000000..f69214d --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/EquipController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/equip") +public class EquipController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/MenuController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/MenuController.java new file mode 100644 index 0000000..8abdc59 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/MenuController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/menu") +public class MenuController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/RoleController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/RoleController.java new file mode 100644 index 0000000..852359a --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/RoleController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/role") +public class RoleController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/RoleMenuController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/RoleMenuController.java new file mode 100644 index 0000000..03bf995 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/RoleMenuController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/roleMenu") +public class RoleMenuController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/UserController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/UserController.java new file mode 100644 index 0000000..2df2269 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/UserController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/user") +public class UserController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/controller/UserRoleController.java b/x-admin/x-admin/codes/com/lantu/sys/controller/UserRoleController.java new file mode 100644 index 0000000..7dc4ebe --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/controller/UserRoleController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Controller +@RequestMapping("/sys/userRole") +public class UserRoleController { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/Equip.java b/x-admin/x-admin/codes/com/lantu/sys/entity/Equip.java new file mode 100644 index 0000000..4fa50ce --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/Equip.java @@ -0,0 +1,111 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_equip") +@ApiModel(value = "Equip对象", description = "") +public class Equip implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private String form; + + private String focal; + + private Integer status; + + private Integer deleted; + + private String x1; + + private String x2; + + private String x3; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getForm() { + return form; + } + + public void setForm(String form) { + this.form = form; + } + public String getFocal() { + return focal; + } + + public void setFocal(String focal) { + this.focal = focal; + } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + public Integer getDeleted() { + return deleted; + } + + public void setDeleted(Integer deleted) { + this.deleted = deleted; + } + public String getx1() { + return x1; + } + + public void setx1(String x1) { + this.x1 = x1; + } + public String getx2() { + return x2; + } + + public void setx2(String x2) { + this.x2 = x2; + } + public String getx3() { + return x3; + } + + public void setx3(String x3) { + this.x3 = x3; + } + + @Override + public String toString() { + return "Equip{" + + "id=" + id + + ", form=" + form + + ", focal=" + focal + + ", status=" + status + + ", deleted=" + deleted + + ", x1=" + x1 + + ", x2=" + x2 + + ", x3=" + x3 + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/Menu.java b/x-admin/x-admin/codes/com/lantu/sys/entity/Menu.java new file mode 100644 index 0000000..7dc3d75 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/Menu.java @@ -0,0 +1,131 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_menu") +@ApiModel(value = "Menu对象", description = "") +public class Menu implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "menu_id", type = IdType.AUTO) + private Integer menuId; + + private String component; + + private String path; + + private String redirect; + + private String name; + + private String title; + + private String icon; + + private Integer parentId; + + private String isLeaf; + + private Boolean hidden; + + public Integer getMenuId() { + return menuId; + } + + public void setMenuId(Integer menuId) { + this.menuId = menuId; + } + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + public String getRedirect() { + return redirect; + } + + public void setRedirect(String redirect) { + this.redirect = redirect; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + public Integer getParentId() { + return parentId; + } + + public void setParentId(Integer parentId) { + this.parentId = parentId; + } + public String getIsLeaf() { + return isLeaf; + } + + public void setIsLeaf(String isLeaf) { + this.isLeaf = isLeaf; + } + public Boolean getHidden() { + return hidden; + } + + public void setHidden(Boolean hidden) { + this.hidden = hidden; + } + + @Override + public String toString() { + return "Menu{" + + "menuId=" + menuId + + ", component=" + component + + ", path=" + path + + ", redirect=" + redirect + + ", name=" + name + + ", title=" + title + + ", icon=" + icon + + ", parentId=" + parentId + + ", isLeaf=" + isLeaf + + ", hidden=" + hidden + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/Role.java b/x-admin/x-admin/codes/com/lantu/sys/entity/Role.java new file mode 100644 index 0000000..d23e42b --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/Role.java @@ -0,0 +1,61 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_role") +@ApiModel(value = "Role对象", description = "") +public class Role implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "role_id", type = IdType.AUTO) + private Integer roleId; + + private String roleName; + + private String roleDesc; + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + public String getRoleDesc() { + return roleDesc; + } + + public void setRoleDesc(String roleDesc) { + this.roleDesc = roleDesc; + } + + @Override + public String toString() { + return "Role{" + + "roleId=" + roleId + + ", roleName=" + roleName + + ", roleDesc=" + roleDesc + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/RoleMenu.java b/x-admin/x-admin/codes/com/lantu/sys/entity/RoleMenu.java new file mode 100644 index 0000000..c94ae39 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/RoleMenu.java @@ -0,0 +1,61 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_role_menu") +@ApiModel(value = "RoleMenu对象", description = "") +public class RoleMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Integer roleId; + + private Integer menuId; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + public Integer getMenuId() { + return menuId; + } + + public void setMenuId(Integer menuId) { + this.menuId = menuId; + } + + @Override + public String toString() { + return "RoleMenu{" + + "id=" + id + + ", roleId=" + roleId + + ", menuId=" + menuId + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/User.java b/x-admin/x-admin/codes/com/lantu/sys/entity/User.java new file mode 100644 index 0000000..a96284c --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/User.java @@ -0,0 +1,111 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_user") +@ApiModel(value = "User对象", description = "") +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private String username; + + private String password; + + private String email; + + private String phone; + + private Integer status; + + private String avatar; + + private Integer deleted; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + public Integer getDeleted() { + return deleted; + } + + public void setDeleted(Integer deleted) { + this.deleted = deleted; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", username=" + username + + ", password=" + password + + ", email=" + email + + ", phone=" + phone + + ", status=" + status + + ", avatar=" + avatar + + ", deleted=" + deleted + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/entity/UserRole.java b/x-admin/x-admin/codes/com/lantu/sys/entity/UserRole.java new file mode 100644 index 0000000..d5b9b74 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/entity/UserRole.java @@ -0,0 +1,61 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_user_role") +@ApiModel(value = "UserRole对象", description = "") +public class UserRole implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + private Integer userId; + + private Integer roleId; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + @Override + public String toString() { + return "UserRole{" + + "id=" + id + + ", userId=" + userId + + ", roleId=" + roleId + + "}"; + } +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/EquipMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/EquipMapper.java new file mode 100644 index 0000000..7048410 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/EquipMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Equip; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface EquipMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/MenuMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/MenuMapper.java new file mode 100644 index 0000000..cd0ecf2 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/MenuMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Menu; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface MenuMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMapper.java new file mode 100644 index 0000000..3d3ac30 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Role; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface RoleMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMenuMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMenuMapper.java new file mode 100644 index 0000000..08fd938 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/RoleMenuMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.RoleMenu; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface RoleMenuMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/UserMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/UserMapper.java new file mode 100644 index 0000000..f30cf9f --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/UserMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.User; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface UserMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/mapper/UserRoleMapper.java b/x-admin/x-admin/codes/com/lantu/sys/mapper/UserRoleMapper.java new file mode 100644 index 0000000..5a20c15 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/mapper/UserRoleMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.UserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface UserRoleMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IEquipService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IEquipService.java new file mode 100644 index 0000000..624638d --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IEquipService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Equip; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IEquipService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IMenuService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IMenuService.java new file mode 100644 index 0000000..cef81d5 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IMenuService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Menu; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IMenuService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IRoleMenuService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IRoleMenuService.java new file mode 100644 index 0000000..29edf4e --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IRoleMenuService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.RoleMenu; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IRoleMenuService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IRoleService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IRoleService.java new file mode 100644 index 0000000..23a8351 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IRoleService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Role; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IRoleService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IUserRoleService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IUserRoleService.java new file mode 100644 index 0000000..dd979d8 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IUserRoleService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.UserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IUserRoleService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/IUserService.java b/x-admin/x-admin/codes/com/lantu/sys/service/IUserService.java new file mode 100644 index 0000000..254e630 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/IUserService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.User; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IUserService extends IService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/EquipServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/EquipServiceImpl.java new file mode 100644 index 0000000..09a19c8 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/EquipServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.Equip; +import com.lantu.sys.mapper.EquipMapper; +import com.lantu.sys.service.IEquipService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class EquipServiceImpl extends ServiceImpl implements IEquipService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/MenuServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/MenuServiceImpl.java new file mode 100644 index 0000000..6610756 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/MenuServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.Menu; +import com.lantu.sys.mapper.MenuMapper; +import com.lantu.sys.service.IMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class MenuServiceImpl extends ServiceImpl implements IMenuService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleMenuServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleMenuServiceImpl.java new file mode 100644 index 0000000..4041fdb --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleMenuServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.RoleMenu; +import com.lantu.sys.mapper.RoleMenuMapper; +import com.lantu.sys.service.IRoleMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class RoleMenuServiceImpl extends ServiceImpl implements IRoleMenuService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..2933bd9 --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/RoleServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.Role; +import com.lantu.sys.mapper.RoleMapper; +import com.lantu.sys.service.IRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class RoleServiceImpl extends ServiceImpl implements IRoleService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserRoleServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..4913d3d --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.UserRole; +import com.lantu.sys.mapper.UserRoleMapper; +import com.lantu.sys.service.IUserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class UserRoleServiceImpl extends ServiceImpl implements IUserRoleService { + +} diff --git a/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserServiceImpl.java b/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..15895ea --- /dev/null +++ b/x-admin/x-admin/codes/com/lantu/sys/service/impl/UserServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.User; +import com.lantu.sys.mapper.UserMapper; +import com.lantu.sys.service.IUserService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + +} diff --git a/x-admin/x-admin/mvnw b/x-admin/x-admin/mvnw new file mode 100644 index 0000000..8a8fb22 --- /dev/null +++ b/x-admin/x-admin/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/x-admin/x-admin/mvnw.cmd b/x-admin/x-admin/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/x-admin/x-admin/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/x-admin/x-admin/pom.xml b/x-admin/x-admin/pom.xml new file mode 100644 index 0000000..0747807 --- /dev/null +++ b/x-admin/x-admin/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.16 + + + com.lantu + x-admin + 0.0.1-SNAPSHOT + x-admin + x-admin + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.mysql + mysql-connector-j + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.2 + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.7 + + + com.baomidou + mybatis-plus-generator + 3.5.2 + + + + org.freemarker + freemarker + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + + + + + + + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + io.springfox + springfox-boot-starter + 3.0.0 + + + + org.springframework.security + spring-security-core + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/x-admin/x-admin/src/main/java/com/lantu/XAdminApplication.java b/x-admin/x-admin/src/main/java/com/lantu/XAdminApplication.java new file mode 100644 index 0000000..4b1582e --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/XAdminApplication.java @@ -0,0 +1,24 @@ +package com.lantu; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@SpringBootApplication +@MapperScan("com.lantu.*.mapper") +public class XAdminApplication { + + public static void main(String[] args) { + + SpringApplication.run(XAdminApplication.class, args); + } + + @Bean + public PasswordEncoder passwordEncoder(){ + return new BCryptPasswordEncoder(); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/common/utils/JwtUtil.java b/x-admin/x-admin/src/main/java/com/lantu/common/utils/JwtUtil.java new file mode 100644 index 0000000..0ef8ddf --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/common/utils/JwtUtil.java @@ -0,0 +1,65 @@ +package com.lantu.common.utils; + +import com.alibaba.fastjson2.JSON; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtBuilder; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; +import java.util.Date; +import java.util.UUID; + +/** + * 作者:cyf + * 描述:无 + */ +@Component +public class JwtUtil { + // 有效期 + private static final long JWT_EXPIRE = 30*60*1000L; //半小时 + // 令牌秘钥 + private static final String JWT_KEY = "123456"; + + public String createToken(Object data){ + // 当前时间 + long currentTime = System.currentTimeMillis(); + // 过期时间 + long expTime = currentTime+JWT_EXPIRE; + // 构建jwt + JwtBuilder builder = Jwts.builder() + .setId(UUID.randomUUID()+"") + .setSubject(JSON.toJSONString(data)) + .setIssuer("system") + .setIssuedAt(new Date(currentTime)) + .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY)) + .setExpiration(new Date(expTime)); + return builder.compact(); + } + + private SecretKey encodeSecret(String key){ + byte[] encode = Base64.getEncoder().encode(key.getBytes()); + SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES"); + return aes; + } + + public Claims parseToken(String token){ + Claims body = Jwts.parser() + .setSigningKey(encodeSecret(JWT_KEY)) + .parseClaimsJws(token) + .getBody(); + return body; + } + + public T parseToken(String token,Class clazz){ + Claims body = Jwts.parser() + .setSigningKey(encodeSecret(JWT_KEY)) + .parseClaimsJws(token) + .getBody(); + return JSON.parseObject(body.getSubject(),clazz); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/common/vo/Result.java b/x-admin/x-admin/src/main/java/com/lantu/common/vo/Result.java new file mode 100644 index 0000000..fda3c0d --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/common/vo/Result.java @@ -0,0 +1,47 @@ +package com.lantu.common.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 作者:cyf + * 描述:无 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Result { + private Integer code; + private String message; + private T data; + + public static Result success(){ + return new Result<>(20000,"success", null); + } + public static Result success(T data){ + return new Result<>(20000,"success", data); + } + public static Result success(T data, String message){ + return new Result<>(20000,message, data); + } + public static Result success(String message){ + return new Result<>(20000,message, null); + } + public static Result fail(){ + return new Result<>(20001,"fail",null); + } + + public static Result fail(Integer code){ + return new Result<>(code,"fail",null); + } + + public static Result fail(Integer code, String message){ + return new Result<>(code,message,null); + } + + public static Result fail( String message){ + return new Result<>(20001,message,null); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/config/MpConfig.java b/x-admin/x-admin/src/main/java/com/lantu/config/MpConfig.java new file mode 100644 index 0000000..084f3fb --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/config/MpConfig.java @@ -0,0 +1,21 @@ +package com.lantu.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 作者:cyf + * 描述:无 + */ +@Configuration +public class MpConfig { + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/config/MyCorsConfig.java b/x-admin/x-admin/src/main/java/com/lantu/config/MyCorsConfig.java new file mode 100644 index 0000000..af24ac7 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/config/MyCorsConfig.java @@ -0,0 +1,28 @@ +package com.lantu.config; + +import org.springframework.web.filter.CorsFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +/** + * 作者:cyf + * 描述:无 + */ +@Configuration +public class MyCorsConfig { + @Bean + public CorsFilter corsFilter(){ + CorsConfiguration configuration = new CorsConfiguration(); + configuration.addAllowedOrigin("http://localhost:8888"); + configuration.setAllowCredentials(true); + configuration.addAllowedMethod("*"); + configuration.addAllowedHeader("*"); + + UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", configuration); + + return new CorsFilter(urlBasedCorsConfigurationSource); + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/config/MyInterceptorConfig.java b/x-admin/x-admin/src/main/java/com/lantu/config/MyInterceptorConfig.java new file mode 100644 index 0000000..8209b29 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/config/MyInterceptorConfig.java @@ -0,0 +1,32 @@ +package com.lantu.config; + +import com.lantu.interceptor.JwtValidateInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 作者:cyf + * 描述:无 + */ +@Configuration +public class MyInterceptorConfig implements WebMvcConfigurer { + @Autowired + private JwtValidateInterceptor jwtValidateInterceptor; + @Override + public void addInterceptors(InterceptorRegistry registry) { + InterceptorRegistration registration = registry.addInterceptor(jwtValidateInterceptor); + registration.addPathPatterns("/**") + .excludePathPatterns( + "/user/login", + "/user/info", + "/user/logout", + "/error", + "/swagger-ui/**", + "/swagger-resources/**", + "/v3/**" + ); + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/config/MyRedisConfig.java b/x-admin/x-admin/src/main/java/com/lantu/config/MyRedisConfig.java new file mode 100644 index 0000000..00ecaaf --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/config/MyRedisConfig.java @@ -0,0 +1,58 @@ +package com.lantu.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.TimeZone; + +/** + * 作者:cyf + * 描述:无 + */ + +@Configuration +public class MyRedisConfig { + + @Resource + private RedisConnectionFactory factory; + + @Bean + public RedisTemplate redisTemplate(){ + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(factory); + + redisTemplate.setKeySerializer(new StringRedisSerializer()); + + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); + redisTemplate.setValueSerializer(serializer); + + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + om.setTimeZone(TimeZone.getDefault()); + om.configure(MapperFeature.USE_ANNOTATIONS, false); + om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + om.setSerializationInclusion(JsonInclude.Include.NON_NULL); + serializer.setObjectMapper(om); + + return redisTemplate; + } +} + diff --git a/x-admin/x-admin/src/main/java/com/lantu/config/MySwaggerConfig.java b/x-admin/x-admin/src/main/java/com/lantu/config/MySwaggerConfig.java new file mode 100644 index 0000000..29ca2d1 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/config/MySwaggerConfig.java @@ -0,0 +1,65 @@ +package com.lantu.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.oas.annotations.EnableOpenApi; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.Collections; +import java.util.List; + + +/** + * 作者:cyf + * 描述:无 + */ +@Configuration +@EnableOpenApi +@EnableWebMvc +public class MySwaggerConfig { + @Bean + public Docket api() { + return new Docket(DocumentationType.OAS_30) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.lantu")) + .paths(PathSelectors.any()) + .build() + .securitySchemes(Collections.singletonList(securityScheme())) + .securityContexts(Collections.singletonList(securityContext())); + } + private SecurityScheme securityScheme() { + //return new ApiKey("Authorization", "Authorization", "header"); + return new ApiKey("X-Token", "X-Token", "header"); + } + private SecurityContext securityContext() { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("^(?!auth).*$")) + .build(); + } + + private List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return Collections.singletonList( + new SecurityReference("X-Token", authorizationScopes)); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("神盾局特工管理系统接口文档") + .description("全网最简单的SpringBoot+Vue前后端分离项目实战") + .version("1.0") + .contact(new Contact("qqcn", "http://www.qqcn.cn", "qqcn@aliyun.com")) + .build(); + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/interceptor/JwtValidateInterceptor.java b/x-admin/x-admin/src/main/java/com/lantu/interceptor/JwtValidateInterceptor.java new file mode 100644 index 0000000..50f7e09 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/interceptor/JwtValidateInterceptor.java @@ -0,0 +1,42 @@ +package com.lantu.interceptor; + +import com.alibaba.fastjson2.JSON; +import com.lantu.common.utils.JwtUtil; +import com.lantu.common.vo.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 作者:cyf + * 描述:无 + */ +@Component +@Slf4j +public class JwtValidateInterceptor implements HandlerInterceptor { + @Autowired + private JwtUtil jwtUtil; + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = request.getHeader("X-Token"); + log.debug(request.getRequestURI() + "需要验证" + token); + if (token != null){ + try { + jwtUtil.parseToken(token); + log.debug(request.getRequestURI() + "验证通过"); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + } + log.debug(request.getRequestURI() + "验证失败,禁止访问"); + response.setContentType("application/json;charset=utf-8"); + Result fail = Result.fail(20003, "jwt无效,请重新登录"); + response.getWriter().write(JSON.toJSONString(fail)); + return false; //拦截 + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/EquipController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/EquipController.java new file mode 100644 index 0000000..d805807 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/EquipController.java @@ -0,0 +1,76 @@ +package com.lantu.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lantu.common.vo.Result; +import com.lantu.sys.entity.Equip; +import com.lantu.sys.service.IEquipService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@RestController +@RequestMapping("/equip") +public class EquipController { + @Autowired + private IEquipService equipService; + + @PostMapping + public Result addEquip(@RequestBody Equip equip){ + equipService.addEquip(equip); + return Result.success("新增设备成功"); + } + + @PutMapping + public Result updateEquip(@RequestBody Equip equip){ + equipService.updateById(equip); + return Result.success("修改设备成功"); + } + + @GetMapping("/{id}") + public Result getEquipById(@PathVariable("id") Integer id){ + Equip equip= equipService.getById(id); + return Result.success(equip); + } + + @DeleteMapping("/{id}") + public Result deleteEquipById(@PathVariable("id") Integer id){ + equipService.removeById(id); + return Result.success("删除设备成功"); + } + + + @GetMapping("/list") + public Result> getEquipList(@RequestParam(value = "status",required = false) String status, + @RequestParam(value = "facol",required = false) String facol, + @RequestParam(value = "pageNo") Long pageNo, + @RequestParam(value = "pageSize") Long pageSize){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(StringUtils.hasLength(status),Equip::getx2,status); + wrapper.eq(StringUtils.hasLength(facol),Equip::getFocal,facol); + wrapper.orderByDesc(Equip::getId); + Page page = new Page<>(pageNo,pageSize); + equipService.page(page,wrapper); + Map data = new HashMap<>(); + data.put("total",page.getTotal()); + data.put("rows",page.getRecords()); + return Result.success(data); + + + } + + + + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/MenuController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/MenuController.java new file mode 100644 index 0000000..d0ca912 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/MenuController.java @@ -0,0 +1,36 @@ +package com.lantu.sys.controller; + +import com.lantu.common.vo.Result; +import com.lantu.sys.entity.Menu; +import com.lantu.sys.service.IMenuService; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@RestController +@RequestMapping("/sys/menu") +public class MenuController { + @Autowired + private IMenuService menuService; + + @ApiOperation("查询所有菜单数据") + @GetMapping + public Result> getAllMenu(){ + List menuList = menuService.getAllMenu(); + + return Result.success(menuList); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleController.java new file mode 100644 index 0000000..192e8ba --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleController.java @@ -0,0 +1,78 @@ +package com.lantu.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lantu.common.vo.Result; +import com.lantu.sys.entity.Role; +import com.lantu.sys.service.IRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@RestController +@RequestMapping("/role") +public class RoleController { + @Autowired + private IRoleService roleService; + + @GetMapping("/list") + public Result> getRoleList(@RequestParam(value = "roleName",required = false) String roleName, + @RequestParam(value = "pageNo") Long pageNo, + @RequestParam(value = "pageSize") Long pageSize){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(StringUtils.hasLength(roleName),Role::getRoleName,roleName); + wrapper.orderByDesc(Role::getRoleId); + Page page = new Page<>(pageNo,pageSize); + + roleService.page(page,wrapper); + Map data = new HashMap<>(); + data.put("total",page.getTotal()); + data.put("rows",page.getRecords()); + return Result.success(data); + + + } + + @PostMapping + public Result addRole(@RequestBody Role role){ + roleService.addRole(role); + return Result.success("新增角色成功"); + } + + @PutMapping + public Result updateRole(@RequestBody Role role){ + roleService.updateRole(role); + return Result.success("修改角色成功"); + } + + @GetMapping("/{id}") + public Result getRoleById(@PathVariable("id") Integer id){ + Role role = roleService.getRoleById(id); + return Result.success(role); + } + + @DeleteMapping("/{id}") + public Result deleteRoleById(@PathVariable("id") Integer id){ + roleService.deleteRoleById(id); + return Result.success("删除角色成功"); + } + + @GetMapping("/all") + public Result> getAllRole(){ + List roleList = roleService.list(); + return Result.success(roleList); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleMenuController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleMenuController.java new file mode 100644 index 0000000..1d5c715 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/RoleMenuController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Controller +@RequestMapping("/sys/roleMenu") +public class RoleMenuController { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserController.java new file mode 100644 index 0000000..658ebb8 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserController.java @@ -0,0 +1,117 @@ +package com.lantu.sys.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lantu.common.vo.Result; +import com.lantu.sys.entity.User; +import com.lantu.sys.service.IUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Api(tags = {"用户接口列表"}) +@RestController +@RequestMapping("/user") +//@CrossOrigin 跨域 +public class UserController { + @Autowired + private IUserService userService; + + @Autowired + private PasswordEncoder passwordEncoder; + + @GetMapping("/all") + public Result> getAllUser() { + List list = userService.list(); + return Result.success(list, "查询成功"); + } + @ApiOperation("用户登录") + + @PostMapping("/login") + public Result> login(@RequestBody User user){ + Map data = userService.login(user); + if (data != null) { + return Result.success(data); + } + return Result.fail(20002, "用户名或密码错误"); + } + + @GetMapping("/info") + public Result> getUserInfo(@RequestParam("token") String token){ + //根据token获取用户信息 + Map data = userService.getUserInfo(token); + if (data != null){ + return Result.success(data); + } + return Result.fail(20003,"登录信息无效,请重新登录"); + } + + + + @PostMapping("/logout") + public Result logout(@RequestHeader("X-token") String token){ + userService.logout(token); + return Result.success(); + } + @GetMapping("/list") + public Result> getUserList(@RequestParam(value = "username",required = false) String username, + @RequestParam(value = "phone",required = false) String phone, + @RequestParam(value = "pageNo") Long pageNo, + @RequestParam(value = "pageSize") Long pageSize){ + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(StringUtils.hasLength(username),User::getUsername,username); + wrapper.eq(StringUtils.hasLength(phone),User::getPhone,phone); + wrapper.orderByDesc(User::getId); + Page page = new Page<>(pageNo,pageSize); + + userService.page(page,wrapper); + Map data = new HashMap<>(); + data.put("total",page.getTotal()); + data.put("rows",page.getRecords()); + return Result.success(data); + + + } + + @PostMapping + public Result addUser(@RequestBody User user){ + user.setPassword(passwordEncoder.encode(user.getPassword())); + userService.addUser(user); + return Result.success("新增用户成功"); + } + + @PutMapping + public Result updateUser(@RequestBody User user){ + user.setPassword(null); + userService.updateUser(user); + return Result.success("修改用户成功"); + } + + @GetMapping("/{id}") + public Result getUserById(@PathVariable("id") Integer id){ + User user = userService.getUserById(id); + return Result.success(user); + } + + @DeleteMapping("/{id}") + public Result deleteUserById(@PathVariable("id") Integer id){ + userService.deleteUserById(id); + return Result.success("删除用户成功"); + } + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserRoleController.java b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserRoleController.java new file mode 100644 index 0000000..086e1c1 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/controller/UserRoleController.java @@ -0,0 +1,18 @@ +package com.lantu.sys.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; + +/** + *

+ * 前端控制器 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Controller +@RequestMapping("/sys/userRole") +public class UserRoleController { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Equip.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Equip.java new file mode 100644 index 0000000..ed116bc --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Equip.java @@ -0,0 +1,103 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@TableName("x_equip") +@ApiModel(value = "Equip对象", description = "") +public class Equip implements Serializable { + + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + private String form; + private String focal; + private Integer status; + private Integer deleted; + private String x1; + private String x2; + private String x3; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getForm() { + return form; + } + + public void setForm(String form) { + this.form = form; + } + public String getFocal() { + return focal; + } + + public void setFocal(String focal) { + this.focal = focal; + } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + public Integer getDeleted() { + return deleted; + } + + public void setDeleted(Integer deleted) { + this.deleted = deleted; + } + public String getx1() { + return x1; + } + + public void setx1(String x1) { + this.x1 = x1; + } + public String getx2() { + return x2; + } + + public void setx2(String x2) { + this.x2 = x2; + } + public String getx3() { + return x3; + } + + public void setx3(String x3) { + this.x3 = x3; + } + + @Override + public String toString() { + return "Equip{" + + "id=" + id + + ", form=" + form + + ", focal=" + focal + + ", status=" + status + + ", deleted=" + deleted + + ", x1=" + x1 + + ", x2=" + x2 + + ", x3=" + x3 + + "}"; + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Menu.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Menu.java new file mode 100644 index 0000000..025cd09 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Menu.java @@ -0,0 +1,59 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@TableName("x_menu") +@Data +@ApiModel(value = "Menu对象", description = "") +public class Menu implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "menu_id", type = IdType.AUTO) + private Integer menuId; + private String component; + private String path; + private String redirect; + private String name; + private String title; + private String icon; + private Integer parentId; + private String isLeaf; + private Boolean hidden; + + @TableField(exist = false) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + @TableField(exist = false) + private Map meta; + public Map getMeta(){ + meta = new HashMap<>(); + meta.put("title",title); + meta.put("icon",icon); + return meta; + + } + + + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Role.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Role.java new file mode 100644 index 0000000..9ba663f --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/Role.java @@ -0,0 +1,68 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@TableName("x_role") +@Data +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(value = "Role对象", description = "") +public class Role implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "role_id", type = IdType.AUTO) + private Integer roleId; + private String roleName; + private String roleDesc; + + @TableField(exist = false) + private List menuIdList; + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + public String getRoleDesc() { + return roleDesc; + } + + public void setRoleDesc(String roleDesc) { + this.roleDesc = roleDesc; + } + + @Override + public String toString() { + return "Role{" + + "roleId=" + roleId + + ", roleName=" + roleName + + ", roleDesc=" + roleDesc + + "}"; + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/RoleMenu.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/RoleMenu.java new file mode 100644 index 0000000..523d5d5 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/RoleMenu.java @@ -0,0 +1,68 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@TableName("x_role_menu") +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "RoleMenu对象", description = "") +public class RoleMenu implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + private Integer roleId; + private Integer menuId; + + + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + public Integer getMenuId() { + return menuId; + } + + public void setMenuId(Integer menuId) { + this.menuId = menuId; + } + + @Override + public String toString() { + return "RoleMenu{" + + "id=" + id + + ", roleId=" + roleId + + ", menuId=" + menuId + + "}"; + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/User.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/User.java new file mode 100644 index 0000000..fa7e56a --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/User.java @@ -0,0 +1,108 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@TableName("x_user") +@Data +@ApiModel(value = "User对象", description = "") +public class User implements Serializable { + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + private String username; + private String password; + private String email; + private String phone; + private Integer status; + private String avatar; + private Integer deleted; + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + public Integer getDeleted() { + return deleted; + } + + public void setDeleted(Integer deleted) { + this.deleted = deleted; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", username=" + username + + ", password=" + password + + ", email=" + email + + ", phone=" + phone + + ", status=" + status + + ", avatar=" + avatar + + ", deleted=" + deleted + + "}"; + } + + @TableField(exist = false) + private List roleIdList; +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/entity/UserRole.java b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/UserRole.java new file mode 100644 index 0000000..df816df --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/entity/UserRole.java @@ -0,0 +1,63 @@ +package com.lantu.sys.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@TableName("x_user_role") +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel(value = "UserRole对象", description = "") +public class UserRole implements Serializable { + + private static final long serialVersionUID = 1L; + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + private Integer userId; + private Integer roleId; + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + @Override + public String toString() { + return "UserRole{" + + "id=" + id + + ", userId=" + userId + + ", roleId=" + roleId + + "}"; + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/EquipMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/EquipMapper.java new file mode 100644 index 0000000..7048410 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/EquipMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Equip; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface EquipMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/MenuMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/MenuMapper.java new file mode 100644 index 0000000..a165d1c --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/MenuMapper.java @@ -0,0 +1,20 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Menu; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface MenuMapper extends BaseMapper { + public List getMenuListByUserId(@Param("userId") Integer userdId, @Param("pid") Integer pid); + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMapper.java new file mode 100644 index 0000000..fd08b8b --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.Role; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface RoleMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMenuMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMenuMapper.java new file mode 100644 index 0000000..5ff3094 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/RoleMenuMapper.java @@ -0,0 +1,19 @@ +package com.lantu.sys.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lantu.sys.entity.RoleMenu; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface RoleMenuMapper extends BaseMapper { + public List getMenuIdListByRoleId(Integer roleId); + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserMapper.java new file mode 100644 index 0000000..3289f19 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserMapper.java @@ -0,0 +1,19 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.User; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface UserMapper extends BaseMapper { + public List getRoleNameByUserId(Integer userId); + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserRoleMapper.java b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserRoleMapper.java new file mode 100644 index 0000000..0332ea8 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/mapper/UserRoleMapper.java @@ -0,0 +1,16 @@ +package com.lantu.sys.mapper; + +import com.lantu.sys.entity.UserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface UserRoleMapper extends BaseMapper { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IEquipService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IEquipService.java new file mode 100644 index 0000000..7918837 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IEquipService.java @@ -0,0 +1,17 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Equip; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +public interface IEquipService extends IService { + + void addEquip(Equip equip); +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IMenuService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IMenuService.java new file mode 100644 index 0000000..9a3a82c --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IMenuService.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Menu; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface IMenuService extends IService { + + List getAllMenu(); + List getMenuListByUserId(Integer userId); +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleMenuService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleMenuService.java new file mode 100644 index 0000000..24c54a8 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleMenuService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.RoleMenu; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface IRoleMenuService extends IService { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleService.java new file mode 100644 index 0000000..9f41d23 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IRoleService.java @@ -0,0 +1,23 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.Role; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface IRoleService extends IService { + + void addRole(Role role); + + Role getRoleById(Integer id); + + void updateRole(Role role); + + void deleteRoleById(Integer id); +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserRoleService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserRoleService.java new file mode 100644 index 0000000..d85bcf6 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserRoleService.java @@ -0,0 +1,16 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.UserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface IUserRoleService extends IService { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserService.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserService.java new file mode 100644 index 0000000..e9e236b --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/IUserService.java @@ -0,0 +1,31 @@ +package com.lantu.sys.service; + +import com.lantu.sys.entity.User; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.Map; + +/** + *

+ * 服务类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +public interface IUserService extends IService { + + Map login(User user); + + Map getUserInfo(String token); + + void logout(String token); + + void addUser(User user); + + User getUserById(Integer id); + + void updateUser(User user); + + void deleteUserById(Integer id); +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/EquipServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/EquipServiceImpl.java new file mode 100644 index 0000000..048c25f --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/EquipServiceImpl.java @@ -0,0 +1,26 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.Equip; +import com.lantu.sys.mapper.EquipMapper; +import com.lantu.sys.service.IEquipService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-11-15 + */ +@Service +public class EquipServiceImpl extends ServiceImpl implements IEquipService { + + @Override + @Transactional + public void addEquip(Equip equip) { + this.baseMapper.insert(equip); + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/MenuServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/MenuServiceImpl.java new file mode 100644 index 0000000..0eab458 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/MenuServiceImpl.java @@ -0,0 +1,71 @@ +package com.lantu.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.lantu.sys.entity.Menu; +import com.lantu.sys.mapper.MenuMapper; +import com.lantu.sys.service.IMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Service +public class MenuServiceImpl extends ServiceImpl implements IMenuService { + + + @Override + public List getAllMenu() { + //一级菜单 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Menu::getParentId, 0); + List menuList = this.list(wrapper); + //填充子菜单 + setMenuChildren(menuList); + + return menuList; + } + + + + private void setMenuChildren(List menuList) { + if (menuList != null){ + for (Menu menu: menuList) { + LambdaQueryWrapper subWrapper = new LambdaQueryWrapper<>(); + subWrapper.eq(Menu::getParentId, menu.getMenuId()); + List subMenuList = this.list(subWrapper); + menu.setChildren(subMenuList); + //递归 + setMenuChildren(subMenuList); + } + } + } + @Override + public List getMenuListByUserId(Integer userId) { + //一级菜单 + List menuList = this.baseMapper.getMenuListByUserId(userId, 0); + //子菜单 + setMenuChildrenByUserId(userId, menuList); + + return menuList; + } + + private void setMenuChildrenByUserId(Integer userId, List menuList) { + if (null != menuList){ + for (Menu menu : menuList){ + List subMenuList = this.baseMapper.getMenuListByUserId(userId, menu.getMenuId()); + menu.setChildren(subMenuList); + //递归 + setMenuChildrenByUserId(userId, subMenuList); + } + + } + } +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleMenuServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleMenuServiceImpl.java new file mode 100644 index 0000000..c50d263 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleMenuServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.RoleMenu; +import com.lantu.sys.mapper.RoleMenuMapper; +import com.lantu.sys.service.IRoleMenuService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Service +public class RoleMenuServiceImpl extends ServiceImpl implements IRoleMenuService { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..6f1839c --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/RoleServiceImpl.java @@ -0,0 +1,78 @@ +package com.lantu.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lantu.sys.entity.Role; +import com.lantu.sys.entity.RoleMenu; +import com.lantu.sys.mapper.RoleMapper; +import com.lantu.sys.mapper.RoleMenuMapper; +import com.lantu.sys.service.IRoleService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Service +public class RoleServiceImpl extends ServiceImpl implements IRoleService { + + @Resource + private RoleMenuMapper roleMenuMapper; + + @Override + @Transactional + public void addRole(Role role) { + //写入角色表 + this.baseMapper.insert(role); + //写入角色菜单关系表 + if (null != role.getMenuIdList()) { + for (Integer menuId : role.getMenuIdList()) { + roleMenuMapper.insert(new RoleMenu(null, role.getRoleId(), menuId)); + } + } + } + + @Override + public Role getRoleById(Integer id) { + Role role = this.baseMapper.selectById(id); + List menuIdList = roleMenuMapper.getMenuIdListByRoleId(id); + role.setMenuIdList(menuIdList); + return role; + } + + @Override + @Transactional + public void updateRole(Role role) { + //修改角色表 + this.baseMapper.updateById(role); + //删除原有权限 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(RoleMenu::getRoleId, role.getRoleId()); + roleMenuMapper.delete(wrapper); + //新增权限 + if (null != role.getMenuIdList()) { + for (Integer menuId : role.getMenuIdList()) { + roleMenuMapper.insert(new RoleMenu(null, role.getRoleId(), menuId)); + } + + + } + } + + @Override + public void deleteRoleById(Integer id) { + this.baseMapper.deleteById(id); + //删除权限 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(RoleMenu::getRoleId, id); + roleMenuMapper.delete(wrapper); + } +} \ No newline at end of file diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserRoleServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..06fbec3 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,20 @@ +package com.lantu.sys.service.impl; + +import com.lantu.sys.entity.UserRole; +import com.lantu.sys.mapper.UserRoleMapper; +import com.lantu.sys.service.IUserRoleService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Service +public class UserRoleServiceImpl extends ServiceImpl implements IUserRoleService { + +} diff --git a/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserServiceImpl.java b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..d8fdc68 --- /dev/null +++ b/x-admin/x-admin/src/main/java/com/lantu/sys/service/impl/UserServiceImpl.java @@ -0,0 +1,188 @@ +package com.lantu.sys.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lantu.common.utils.JwtUtil; +import com.lantu.sys.entity.Menu; +import com.lantu.sys.entity.User; +import com.lantu.sys.entity.UserRole; +import com.lantu.sys.mapper.UserMapper; +import com.lantu.sys.mapper.UserRoleMapper; +import com.lantu.sys.service.IMenuService; +import com.lantu.sys.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author cyf + * @since 2023-10-08 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + + @Autowired + private RedisTemplate redisTemplate; + + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private IMenuService menuService; + + @Autowired + private JwtUtil jwtUtil; + + @Autowired + private UserRoleMapper userRoleMapper; + @Override + public Map login(User user) { + //根据用户名和密码查询 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(User::getUsername,user.getUsername()); + User loginUser = this.baseMapper.selectOne(wrapper); + //结果不为空,并且密码和传入密码是匹配的,则生成token,并将用户信息存入redis + if (loginUser != null && passwordEncoder.matches(user.getPassword(), loginUser.getPassword())){ + // 暂时用UUID,终极方案是jwt +// String key = "user:" + UUID.randomUUID(); + + // 存入redis + loginUser.setPassword(null); +// redisTemplate.opsForValue().set(key,loginUser,30, TimeUnit.MINUTES); + String token = jwtUtil.createToken(loginUser); + //返回数据 + Map data = new HashMap<>(); + data.put("token",token); + return data; + } + return null; + } +// @Override +// public Map login(User user) { +// //根据用户名和密码查询 +// LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); +// wrapper.eq(User::getUsername,user.getUsername()); +// wrapper.eq(User::getPassword,user.getPassword()); +// User loginUser = this.baseMapper.selectOne(wrapper); +// //结果不为空,则生成token,并将用户信息存入redis +// if (loginUser != null){ +// // 暂时用UUID,终极方案是jwt +// String key = "user:" + UUID.randomUUID(); +// // 存入redis +// loginUser.setPassword(null); +// redisTemplate.opsForValue().set(key,loginUser,30, TimeUnit.MINUTES); +// +// //返回数据 +// Map data = new HashMap<>(); +// data.put("token",key); +// return data; +// } +// return null; +// } + + @Override + public Map getUserInfo(String token) { + //根据token获取用户信息,redis +// Object obj = redisTemplate.opsForValue().get(token); + User loginUser = null; + try { + loginUser = jwtUtil.parseToken(token, User.class); + } catch (Exception e) { + e.printStackTrace(); + } + if (loginUser != null){ +// User loginUser = JSON.parseObject(JSON.toJSONString(obj),User.class); + Map data = new HashMap<>(); + data.put("name", loginUser.getUsername()); + data.put("avatar", loginUser.getAvatar()); + //角色 + List rolelist = this.baseMapper.getRoleNameByUserId(loginUser.getId()); + data.put("roles",rolelist); + + //权限列表 + List menuList = menuService.getMenuListByUserId(loginUser.getId()); + data.put("menuList",menuList); + + return data; + + } + return null; + } + + @Override + public void logout(String token) { + +// redisTemplate.delete(token); + } + + @Override + @Transactional + public void addUser(User user) { + // 写入用户表 + this.baseMapper.insert(user); + //写入用户角色表 + List roleIdList = user.getRoleIdList(); + if (roleIdList != null){ + for (Integer roleId : roleIdList) { + userRoleMapper.insert(new UserRole(null, user.getId(), roleId)); + } + } + + } + + @Override + public User getUserById(Integer id) { + User user = this.baseMapper.selectById(id); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserRole::getUserId, id); + List userRoleList = userRoleMapper.selectList(wrapper); + + List roleIdList = userRoleList.stream() + .map(userRole -> {return userRole.getRoleId();}) + .collect(Collectors.toList()); + user.setRoleIdList(roleIdList); + return user; + } + + @Override + @Transactional + public void updateUser(User user) { + //更新用户表 + this.baseMapper.updateById(user); + //删除原有角色 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserRole::getUserId, user.getId()); + userRoleMapper.delete(wrapper); + //设置新角色 + List roleIdList = user.getRoleIdList(); + if (roleIdList != null){ + for (Integer roleId : roleIdList) { + userRoleMapper.insert(new UserRole(null, user.getId(), roleId)); + } + } + + } + + @Override + public void deleteUserById(Integer id) { + this.baseMapper.deleteById(id); + //删除原有角色 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserRole::getUserId, id); + userRoleMapper.delete(wrapper); + } + +} diff --git a/x-admin/x-admin/src/main/resources/application.yml b/x-admin/x-admin/src/main/resources/application.yml new file mode 100644 index 0000000..a0fc8ce --- /dev/null +++ b/x-admin/x-admin/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: 9999 + +spring: + datasource: + username: root + password: 123456 + url: jdbc:mysql:///xdb + redis: + port: 6379 + host: localhost +logging: + level: + com.lantu: debug + +#mybatis-plus: +# mapper-locations: +# classpath: mappersys\*.xml +mybatis-plus: + global-config: + db-config: + logic-delete-field: deleted + logic-not-delete-value: 0 + logic-delete-value: 1 + type-aliases-package: com.lantu.*.entity \ No newline at end of file diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/EquipMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/EquipMapper.xml new file mode 100644 index 0000000..dd169e3 --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/EquipMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/MenuMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/MenuMapper.xml new file mode 100644 index 0000000..7f96635 --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/MenuMapper.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/RoleMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/RoleMapper.xml new file mode 100644 index 0000000..211ff02 --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/RoleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/RoleMenuMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/RoleMenuMapper.xml new file mode 100644 index 0000000..81e8dad --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/RoleMenuMapper.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/UserMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/UserMapper.xml new file mode 100644 index 0000000..77c4fd3 --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/UserMapper.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/x-admin/x-admin/src/main/resources/mapper/sys/UserRoleMapper.xml b/x-admin/x-admin/src/main/resources/mapper/sys/UserRoleMapper.xml new file mode 100644 index 0000000..fd92297 --- /dev/null +++ b/x-admin/x-admin/src/main/resources/mapper/sys/UserRoleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/x-admin/x-admin/src/test/java/com/lantu/CodeGenerator.java b/x-admin/x-admin/src/test/java/com/lantu/CodeGenerator.java new file mode 100644 index 0000000..75e02ea --- /dev/null +++ b/x-admin/x-admin/src/test/java/com/lantu/CodeGenerator.java @@ -0,0 +1,40 @@ +package com.lantu; + +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; + +import java.util.Collections; + +/** + * 作者:cyf + * 描述:无 + */ +public class CodeGenerator { + public static void main(String[] args) { + String url = "jdbc:mysql:///xdb"; + String username = "root"; + String password = "123456"; + String moduleName = "sys"; + String tables = "x_user,x_role,x_menu,x_user_role,x_role_menu,x_equip"; + String mapperlocation = "D:\\pingtai\\x-admin\\x-admin\\src\\main\\resources\\mapper\\" + moduleName; + FastAutoGenerator.create(url, username, password) + .globalConfig(builder -> { + builder.author("cyf") // 设置作者 + .enableSwagger() // 开启 swagger 模式 +// .fileOverride() // 覆盖已生成文件 + .outputDir("D:\\pingtai\\x-admin\\x-admin\\codes"); // 指定输出目录 + }) + .packageConfig(builder -> { + builder.parent("com.lantu") // 设置父包名 + .moduleName(moduleName) // 设置父包模块名 + .pathInfo(Collections.singletonMap(OutputFile.xml, mapperlocation)); // 设置mapperXml生成路径 + }) + .strategyConfig(builder -> { + builder.addInclude(tables) // 设置需要生成的表名 + .addTablePrefix("x_"); // 设置过滤表前缀 + }) + .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板 + .execute(); + } +}