Browse Source

Merge branch 'gin-vue-admin_v2_dev' of https://github.com/flipped-aurora/gin-vue-admin into gin-vue-admin_v2_dev

klausY 4 years ago
parent
commit
1133c0fd12

+ 4 - 1
README-zh_CN.md

@@ -219,7 +219,10 @@ swag init
 (2)模板使用
 > Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/ (v1.0版本视频,v2.0操作相同目录不同)
 
-(3)golang基础教学视频录制中...
+(3)2.0目录以及开发体验
+> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
+
+(4)golang基础教学视频录制中...
 > https://space.bilibili.com/322210472/channel/detail?cid=108884
 
 ## 8. 联系方式

+ 6 - 3
README.md

@@ -216,12 +216,15 @@ backend code file: model\dnModel\api.go
 ### 7.2 Video courses
 
 (1) Development environment course
-> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/    (coming soon)
+> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/
     
 (2) Template course
-> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/    (coming soon)
+> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/
 
-(3) Golang basic course (coming soon)
+(3)2.0 version introduction and development experience
+> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
+
+(4) Golang basic course (coming soon)
 
 > https://space.bilibili.com/322210472/channel/detail?cid=108884
 

+ 43 - 0
server/api/v1/sys_auto_code.go

@@ -6,6 +6,7 @@ import (
 	"gin-vue-admin/model"
 	"gin-vue-admin/service"
 	"github.com/gin-gonic/gin"
+	"net/url"
 	"os"
 )
 
@@ -20,6 +21,48 @@ import (
 func CreateTemp(c *gin.Context) {
 	var a model.AutoCodeStruct
 	_ = c.ShouldBindJSON(&a)
+	if a.AutoCreateApiToSql {
+		apiList := [5]model.SysApi{
+			{
+				Path:        "/" + a.Abbreviation + "/" + "create" + a.StructName,
+				Description: "新增" + a.StructName,
+				ApiGroup:    a.Abbreviation,
+				Method:      "POST",
+			},
+			{
+				Path:        "/" + a.Abbreviation + "/" + "delete" + a.StructName,
+				Description: "删除" + a.StructName,
+				ApiGroup:    a.Abbreviation,
+				Method:      "DELETE",
+			},
+			{
+				Path:        "/" + a.Abbreviation + "/" + "update" + a.StructName,
+				Description: "更新" + a.StructName,
+				ApiGroup:    a.Abbreviation,
+				Method:      "POST",
+			},
+			{
+				Path:        "/" + a.Abbreviation + "/" + "find" + a.StructName,
+				Description: "根据ID获取" + a.StructName,
+				ApiGroup:    a.Abbreviation,
+				Method:      "GET",
+			},
+			{
+				Path:        "/" + a.Abbreviation + "/" + "get" + a.StructName + "List",
+				Description: "获取" + a.StructName + "列表",
+				ApiGroup:    a.Abbreviation,
+				Method:      "GET",
+			},
+		}
+		for _, v := range apiList {
+			errC := service.CreateApi(v)
+			if errC != nil {
+				c.Writer.Header().Add("success", "false")
+				c.Writer.Header().Add("msg", url.QueryEscape(fmt.Sprintf("自动化创建失败,%v,请自行清空垃圾数据", errC)))
+				return
+			}
+		}
+	}
 	err := service.CreateTemp(a)
 	if err != nil {
 		response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)

+ 13 - 5
server/db/qmplus.sql

@@ -11,7 +11,7 @@
  Target Server Version : 50644
  File Encoding         : 65001
 
- Date: 24/04/2020 10:28:38
+ Date: 30/04/2020 20:47:13
 */
 
 SET NAMES utf8mb4;
@@ -3833,7 +3833,13 @@ CREATE TABLE `exa_file_upload_and_downloads`  (
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_file_upload_and_downloads_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_exa_file_upload_and_downloads_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Records of exa_file_upload_and_downloads
+-- ----------------------------
+INSERT INTO `exa_file_upload_and_downloads` VALUES (17, '2020-04-26 11:51:39', '2020-04-26 11:51:39', NULL, '10.png', 'http://qmplusimg.henrongyi.top/158787308910.png', 'png', '158787308910.png');
+INSERT INTO `exa_file_upload_and_downloads` VALUES (19, '2020-04-27 15:48:38', '2020-04-27 15:48:38', NULL, 'logo.png', 'http://qmplusimg.henrongyi.top/1587973709logo.png', 'png', '1587973709logo.png');
 
 -- ----------------------------
 -- Table structure for exa_files
@@ -4040,6 +4046,7 @@ INSERT INTO `sys_authority_menus` VALUES ('888', 38);
 INSERT INTO `sys_authority_menus` VALUES ('888', 40);
 INSERT INTO `sys_authority_menus` VALUES ('888', 41);
 INSERT INTO `sys_authority_menus` VALUES ('888', 42);
+INSERT INTO `sys_authority_menus` VALUES ('888', 45);
 INSERT INTO `sys_authority_menus` VALUES ('8881', 1);
 INSERT INTO `sys_authority_menus` VALUES ('8881', 2);
 INSERT INTO `sys_authority_menus` VALUES ('8881', 18);
@@ -4092,16 +4099,16 @@ CREATE TABLE `sys_base_menus`  (
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_base_menus_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_sys_base_menus_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 45 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 46 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_base_menus
 -- ----------------------------
 INSERT INTO `sys_base_menus` VALUES (1, '2019-09-19 22:05:18', '2020-04-24 10:16:42', NULL, 0, 0, 'dashboard', 'dashboard', 0, 'view/dashboard/index.vue', '仪表盘', 'setting', '仪表盘', 1, 0, 0);
-INSERT INTO `sys_base_menus` VALUES (2, '2019-09-19 22:06:17', '2020-04-24 10:16:43', NULL, 0, 0, 'test', 'test', 0, 'view/test/index.vue', '测试菜单', 'info', '测试菜单', 2, 0, 0);
+INSERT INTO `sys_base_menus` VALUES (2, '2019-09-19 22:06:17', '2020-04-30 17:50:34', NULL, 0, 0, 'about', 'about', 0, 'view/about/index.vue', '关于我们', 'info', '测试菜单', 7, 0, 0);
 INSERT INTO `sys_base_menus` VALUES (3, '2019-09-19 22:06:38', '2020-04-24 10:16:43', NULL, 0, 0, 'admin', 'superAdmin', 0, 'view/superAdmin/index.vue', '超级管理员', 'user-solid', '超级管理员', 3, 0, 0);
 INSERT INTO `sys_base_menus` VALUES (4, '2019-09-19 22:11:53', '2020-04-24 10:16:42', NULL, 0, 3, 'authority', 'authority', 0, 'view/superAdmin/authority/authority.vue', '角色管理', 's-custom', '角色管理', 1, 0, 0);
-INSERT INTO `sys_base_menus` VALUES (5, '2019-09-19 22:13:18', '2020-04-24 10:16:43', NULL, 0, 3, 'menu', 'menu', 0, 'view/superAdmin/menu/menu.vue', '菜单管理', 's-order', '菜单管理', 2, 0, 0);
+INSERT INTO `sys_base_menus` VALUES (5, '2019-09-19 22:13:18', '2020-04-30 17:45:27', NULL, 0, 3, 'menu', 'menu', 0, 'view/superAdmin/menu/menu.vue', '菜单管理', 's-order', '菜单管理', 2, 1, 0);
 INSERT INTO `sys_base_menus` VALUES (6, '2019-09-19 22:13:36', '2020-04-24 10:16:43', NULL, 0, 3, 'api', 'api', 0, 'view/superAdmin/api/api.vue', 'api管理', 's-platform', 'api管理', 3, 1, 0);
 INSERT INTO `sys_base_menus` VALUES (17, '2019-10-09 15:12:29', '2020-04-24 10:16:43', NULL, 0, 3, 'user', 'user', 0, 'view/superAdmin/user/user.vue', '用户管理', 'coordinate', '用户管理', 4, 0, 0);
 INSERT INTO `sys_base_menus` VALUES (18, '2019-10-15 22:27:22', '2020-04-24 10:16:43', NULL, 0, 0, 'person', 'person', 1, 'view/person/person.vue', '个人信息', 'user-solid', '个人信息', 4, 0, 0);
@@ -4117,6 +4124,7 @@ INSERT INTO `sys_base_menus` VALUES (38, '2020-03-29 21:31:03', '2020-04-24 10:1
 INSERT INTO `sys_base_menus` VALUES (40, '2020-03-29 21:35:10', '2020-04-24 10:16:43', NULL, 0, 38, 'autoCode', 'autoCode', 0, 'view/systemTools/autoCode/index.vue', '代码生成器', 'cpu', '代码生成器', 1, 0, 0);
 INSERT INTO `sys_base_menus` VALUES (41, '2020-03-29 21:36:26', '2020-04-24 10:16:43', NULL, 0, 38, 'formCreate', 'formCreate', 0, 'view/systemTools/formCreate/index.vue', '表单生成器', 'magic-stick', '表单生成器', 2, 0, 0);
 INSERT INTO `sys_base_menus` VALUES (42, '2020-04-02 14:19:36', '2020-04-24 10:16:43', NULL, 0, 38, 'system', 'system', 0, 'view/systemTools/system/system.vue', '系统配置', 's-operation', '系统配置', 3, 0, 0);
+INSERT INTO `sys_base_menus` VALUES (45, '2020-04-29 17:19:34', '2020-04-30 17:44:44', NULL, 0, 0, 'iconList', 'iconList', 0, 'view/iconList/index.vue', '图标集合', 'star-on', NULL, 2, 0, 0);
 
 -- ----------------------------
 -- Table structure for sys_data_authority_id

+ 5 - 4
server/model/sys_auto_code.go

@@ -2,10 +2,11 @@ package model
 
 // 初始版本自动化代码工具
 type AutoCodeStruct struct {
-	StructName   string  `json:"structName"`
-	PackageName  string  `json:"packageName"`
-	Abbreviation string  `json:"abbreviation"`
-	Fields       []Field `json:"fields"`
+	StructName         string  `json:"structName"`
+	PackageName        string  `json:"packageName"`
+	Abbreviation       string  `json:"abbreviation"`
+	AutoCreateApiToSql bool    `json:"autoCreateApiToSql"`
+	Fields             []Field `json:"fields"`
 }
 
 type Field struct {

+ 9 - 9
server/resource/template/fe/table.vue.tpl

@@ -2,7 +2,7 @@
   <div>
     <div class="search-term">
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
-      <!-- 此处可使用表单生成器生成搜索条件 -->
+            此处请使用表单生成器生成form填充 表单默认绑定 formData 如手动修改过请自行修改key
         <el-form-item>
           <el-button @click="openDialog" type="primary">新增</el-button>
         </el-form-item>
@@ -50,7 +50,7 @@
     ></el-pagination>
 
     <el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="弹窗操作">
-      <!-- 此处请使用表单生成器生成form填充  -->
+      此处请使用表单生成器生成form填充 表单默认绑定 formData 如手动修改过请自行修改key
       <div class="dialog-footer" slot="footer">
         <el-button @click="closeDialog">取 消</el-button>
         <el-button @click="enterDialog" type="primary">确 定</el-button>
@@ -66,7 +66,7 @@ import {
     update{{.StructName}},
     find{{.StructName}},
     get{{.StructName}}List
-} from "@/api/{{.StructName}}";  //  此处请自行替换地址
+} from "@/api/{{.PackageName}}";  //  此处请自行替换地址
 import { formatTimeToStr } from "@/utils/data";
 import infoList from "@/components/mixins/infoList";
 
@@ -79,7 +79,7 @@ export default {
       dialogFormVisible: false,
       visible: false,
       type: "",
-      form: {
+      formData: {
         {{range .Fields}}{{.FieldJson}}:null,{{ end }}
       }
     };
@@ -99,13 +99,13 @@ export default {
       const res = await find{{.StructName}}({ ID: row.ID });
       this.type = "update";
       if (res.code == 0) {
-        this.form = res.data.re{{.Abbreviation}};
+        this.formData = res.data.re{{.Abbreviation}};
         this.dialogFormVisible = true;
       }
     },
     closeDialog() {
       this.dialogFormVisible = false;
-      this.form = {
+      this.formData = {
         {{range .Fields}}
           {{.FieldJson}}:null,{{ end }}
       };
@@ -125,13 +125,13 @@ export default {
       let res;
       switch (this.type) {
         case "create":
-          res = await create{{.StructName}}(this.form);
+          res = await create{{.StructName}}(this.formData);
           break;
         case "update":
-          res = await update{{.StructName}}(this.form);
+          res = await update{{.StructName}}(this.formData);
           break;
         default:
-          res = await create{{.StructName}}(this.form);
+          res = await create{{.StructName}}(this.formData);
           break;
       }
 

+ 34 - 13
web/package-lock.json

@@ -2878,7 +2878,8 @@
             "version": "4.6.0",
             "resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz",
             "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-            "dev": true
+            "dev": true,
+            "optional": true
         },
         "coa": {
             "version": "2.0.2",
@@ -5245,7 +5246,8 @@
                 "ansi-regex": {
                     "version": "2.1.1",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "aproba": {
                     "version": "1.2.0",
@@ -5266,12 +5268,14 @@
                 "balanced-match": {
                     "version": "1.0.0",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "brace-expansion": {
                     "version": "1.1.11",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "balanced-match": "^1.0.0",
                         "concat-map": "0.0.1"
@@ -5286,17 +5290,20 @@
                 "code-point-at": {
                     "version": "1.1.0",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "concat-map": {
                     "version": "0.0.1",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "console-control-strings": {
                     "version": "1.1.0",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "core-util-is": {
                     "version": "1.0.2",
@@ -5413,7 +5420,8 @@
                 "inherits": {
                     "version": "2.0.3",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "ini": {
                     "version": "1.3.5",
@@ -5425,6 +5433,7 @@
                     "version": "1.0.0",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "number-is-nan": "^1.0.0"
                     }
@@ -5439,6 +5448,7 @@
                     "version": "3.0.4",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "brace-expansion": "^1.1.7"
                     }
@@ -5446,12 +5456,14 @@
                 "minimist": {
                     "version": "0.0.8",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "minipass": {
                     "version": "2.3.5",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "safe-buffer": "^5.1.2",
                         "yallist": "^3.0.0"
@@ -5470,6 +5482,7 @@
                     "version": "0.5.1",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "minimist": "0.0.8"
                     }
@@ -5550,7 +5563,8 @@
                 "number-is-nan": {
                     "version": "1.0.1",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "object-assign": {
                     "version": "4.1.1",
@@ -5562,6 +5576,7 @@
                     "version": "1.4.0",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "wrappy": "1"
                     }
@@ -5647,7 +5662,8 @@
                 "safe-buffer": {
                     "version": "5.1.2",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "safer-buffer": {
                     "version": "2.1.2",
@@ -5683,6 +5699,7 @@
                     "version": "1.0.2",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "code-point-at": "^1.0.0",
                         "is-fullwidth-code-point": "^1.0.0",
@@ -5702,6 +5719,7 @@
                     "version": "3.0.1",
                     "bundled": true,
                     "dev": true,
+                    "optional": true,
                     "requires": {
                         "ansi-regex": "^2.0.0"
                     }
@@ -5745,12 +5763,14 @@
                 "wrappy": {
                     "version": "1.0.2",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 },
                 "yallist": {
                     "version": "3.0.3",
                     "bundled": true,
-                    "dev": true
+                    "dev": true,
+                    "optional": true
                 }
             }
         },
@@ -9872,7 +9892,8 @@
             "version": "4.0.8",
             "resolved": "https://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz",
             "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
-            "dev": true
+            "dev": true,
+            "optional": true
         },
         "rx-lite-aggregates": {
             "version": "4.0.8",

BIN
web/public/favicon.ico


+ 1 - 0
web/src/App.vue

@@ -18,5 +18,6 @@ export default {
 #app {
   background: #eee;
   height: 100vh;
+  overflow: hidden;
 }
 </style>

File diff suppressed because it is too large
+ 0 - 0
web/src/assets/background.svg


BIN
web/src/assets/docs.png


BIN
web/src/assets/github.png


BIN
web/src/assets/logo_login.png


BIN
web/src/assets/video.png


BIN
web/src/assets/yuque.png


+ 0 - 5
web/src/style/main.scss

@@ -664,11 +664,6 @@ li {
     }
 }
 
-// el-form
-.el-form {
-    background-color: #fff;
-    padding: 10px 0;
-}
 
 .el-row {
     padding: 10px 0;

+ 1 - 1
web/src/utils/request.js

@@ -60,7 +60,7 @@ service.interceptors.response.use(
         } else {
             Message({
                 showClose: true,
-                message: response.data.msg,
+                message: response.data.msg||decodeURI(response.headers.msg),
                 type: 'error',
                 onClose: () => {
                     if (response.data.data && response.data.data.reload) {

+ 0 - 1
web/src/view/dashboard/index.vue

@@ -168,7 +168,6 @@ export default {
 
 <style lang="scss" scoped>
     .big{
-        width: 100%;
         background-color: rgb(243,243,243);;
         .top{
             width: 98%;

+ 68 - 78
web/src/view/example/customer/customer.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-      <div class="search-term">
+    <div class="search-term">
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
         <el-form-item>
           <el-button @click="openDialog" type="primary">新增客户</el-button>
@@ -25,22 +25,19 @@
       <el-table-column label="按钮组">
         <template slot-scope="scope">
           <el-button @click="updateCustomer(scope.row)" size="small" type="text">变更</el-button>
-          <el-popover
-          placement="top"
-          width="160"
-          v-model="scope.row.visible">
-          <p>确定要删除吗?</p>
-          <div style="text-align: right; margin: 0">
-            <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
-            <el-button type="primary" size="mini" @click="deleteCustomer(scope.row)">确定</el-button>
-          </div>
-          <el-button type="text" size="mini" slot="reference">删除</el-button>
-        </el-popover>
+          <el-popover placement="top" width="160" v-model="scope.row.visible">
+            <p>确定要删除吗?</p>
+            <div style="text-align: right; margin: 0">
+              <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
+              <el-button type="primary" size="mini" @click="deleteCustomer(scope.row)">确定</el-button>
+            </div>
+            <el-button type="text" size="mini" slot="reference">删除</el-button>
+          </el-popover>
         </template>
       </el-table-column>
     </el-table>
 
-      <el-pagination
+    <el-pagination
       :current-page="page"
       :page-size="pageSize"
       :page-sizes="[10, 30, 50, 100]"
@@ -64,108 +61,101 @@
         <el-button @click="closeDialog">取 消</el-button>
         <el-button @click="enterDialog" type="primary">确 定</el-button>
       </div>
-    </el-dialog>
-    在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示
+    </el-dialog>在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示
   </div>
 </template>
 
 <script>
-
 import {
   createExaCustomer,
   updateExaCustomer,
   deleteExaCustomer,
   getExaCustomer,
   getExaCustomerList
-} from '@/api/customer'
-import { formatTimeToStr } from '@/utils/data'
-import infoList from '@/components/mixins/infoList'
-import { mapGetters } from 'vuex'
+} from "@/api/customer";
+import { formatTimeToStr } from "@/utils/data";
+import infoList from "@/components/mixins/infoList";
 
 export default {
-  name: 'Customer',
-   mixins: [infoList],
-  data(){
-    return{
+  name: "Customer",
+  mixins: [infoList],
+  data() {
+    return {
       listApi: getExaCustomerList,
-      dialogFormVisible:false,
-      visible:false,
-      type:"",
-      form:{
-        customerName:"",
-        customerPhoneData:""
+      dialogFormVisible: false,
+      visible: false,
+      type: "",
+      form: {
+        customerName: "",
+        customerPhoneData: ""
       }
-    }
-  },
-  computed:{
-    ...mapGetters('user', ['token'])
+    };
   },
-   filters: {
+  filters: {
     formatDate: function(time) {
-      if (time != null && time != '') {
-        var date = new Date(time)
-        return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
+      if (time != null && time != "") {
+        var date = new Date(time);
+        return formatTimeToStr(date, "yyyy-MM-dd hh:mm:ss");
       } else {
-        return ''
+        return "";
       }
     }
   },
-  methods:{
-    async updateCustomer(row){
-      const res = await getExaCustomer({ID:row.ID})
-      this.type = "update"
-      if(res.code == 0){
-        this.form = res.data.customer        
-        this.dialogFormVisible = true
+  methods: {
+    async updateCustomer(row) {
+      const res = await getExaCustomer({ ID: row.ID });
+      this.type = "update";
+      if (res.code == 0) {
+        this.form = res.data.customer;
+        this.dialogFormVisible = true;
       }
     },
-    closeDialog(){
-      this.dialogFormVisible = false
+    closeDialog() {
+      this.dialogFormVisible = false;
       this.form = {
-        customerName:"",
-        customerPhoneData:""
-      }
+        customerName: "",
+        customerPhoneData: ""
+      };
     },
-    async deleteCustomer(row){
-      this.visible = false
-      const res = await deleteExaCustomer({ID:row.ID})
-      if (res.code == 0){
+    async deleteCustomer(row) {
+      this.visible = false;
+      const res = await deleteExaCustomer({ ID: row.ID });
+      if (res.code == 0) {
         this.$message({
-          type:"success",
-          message:"删除成功"
-        })
-         this.getTableData()
+          type: "success",
+          message: "删除成功"
+        });
+        this.getTableData();
       }
     },
-    async enterDialog(){
-      let res 
+    async enterDialog() {
+      let res;
       switch (this.type) {
         case "create":
-          res =await createExaCustomer(this.form)
-             break;
+          res = await createExaCustomer(this.form);
+          break;
         case "update":
-           res =await updateExaCustomer(this.form)
-              break;
+          res = await updateExaCustomer(this.form);
+          break;
         default:
-          res =await createExaCustomer(this.form)
-             break;
-
+          res = await createExaCustomer(this.form);
+          break;
       }
-     
-      if(res.code == 0){
-        this.closeDialog()
-        this.getTableData()
+
+      if (res.code == 0) {
+        this.closeDialog();
+        this.getTableData();
       }
     },
-     openDialog() {
-      this.type = "create"
-      this.dialogFormVisible = true
+    openDialog() {
+      this.type = "create";
+      this.dialogFormVisible = true;
     }
   },
-  created(){
-    this.getTableData()
+  created() {
+    this.getTableData();
   }
-}
+};
 </script>
 
 <style>

+ 15 - 5
web/src/view/layout/aside/historyComponent/history.vue

@@ -36,10 +36,17 @@ export default {
       left: 0,
       top: 0,
       isCollapse: false,
+      isMobile:false,
       rightActive: ''
     }
   },
   created() {
+    this.$bus.on('mobile',(isMobile)=>{
+      this.isMobile = isMobile
+    })
+    this.$bus.on('collapse',(isCollapse)=>{
+      this.isCollapse = isCollapse
+    })
     const initHistorys = [
       {
         name: 'dashboard',
@@ -52,10 +59,10 @@ export default {
       JSON.parse(sessionStorage.getItem('historys')) || initHistorys
     this.setTab(this.$route)
   },
-  mounted() {
-    this.$bus.on('totalCollapse', () => {
-      this.isCollapse = !this.isCollapse
-    })
+
+  beforeDestroy(){
+    this.$bus.off('collapse')
+    this.$bus.off('mobile')
   },
   methods: {
     openContextMenu(e) {
@@ -66,10 +73,13 @@ export default {
         this.contextMenuVisible = true
         let width
         if (this.isCollapse) {
-          width = 60
+          width = 54
         } else {
           width = 220
         }
+        if(this.isMobile){
+          width = 0
+        }
         this.left = e.clientX - width
         this.top = e.clientY + 10
         this.rightActive = e.srcElement.id.split('-')[1]

+ 1 - 4
web/src/view/layout/aside/index.vue

@@ -50,9 +50,7 @@ export default {
      if(screenWidth<1000){
        this.isCollapse = !this.isCollapse
       }
-    this.$bus.on('totalCollapse', () => {
-      this.isCollapse = !this.isCollapse
-    })
+
      this.$bus.on('collapse', (item) => {
       this.isCollapse = item
     })
@@ -64,7 +62,6 @@ export default {
     }
   },
   beforeDestroy() {
-    this.$bus.off('totalCollapse')
     this.$bus.off('collapse')
   }
 }

+ 138 - 136
web/src/view/layout/index.vue

@@ -8,45 +8,47 @@
       <!-- 分块滑动功能 -->
       <el-main class="main-cont main-right">
         <transition mode="out-in" name="el-fade-in-linear">
-          <div class="topfix" :style="{width: `calc(100% - ${isCollapse?'54px':'220px'})`}">
-        <el-header class="header-cont">
-          <div @click="totalCollapse" class="menu-total">
-            <i class="el-icon-s-unfold" v-if="isCollapse"></i>
-            <i class="el-icon-s-fold" v-else></i>
-          </div>
-          <el-breadcrumb class="breadcrumb" separator-class="el-icon-arrow-right">
-          <el-breadcrumb-item
-            :key="item.path"
-            v-for="item in matched.slice(1,matched.length)"
-          >{{item.meta.title}}</el-breadcrumb-item>
-        </el-breadcrumb>
-          <div class="fl-right right-box">
-            <el-dropdown>
-              <span class="el-dropdown-link">
-                <img :src="userInfo.headerImg" height="30" width="30" />
-                {{userInfo.title}}
-                <i class="el-icon-arrow-down"></i>
-              </span>
-              <el-dropdown-menu class="dropdown-group" slot="dropdown">
-                <el-dropdown-item>
-                  <span>
-                    更多信息
-                    <el-badge is-dot />
+          <div
+            class="topfix"
+            :style="{width: `calc(100% - ${isMobile?'0px':isCollapse?'54px':'220px'})`}"
+          >
+            <el-header class="header-cont">
+              <div @click="totalCollapse" class="menu-total">
+                <i class="el-icon-s-unfold" v-if="isCollapse"></i>
+                <i class="el-icon-s-fold" v-else></i>
+              </div>
+              <el-breadcrumb class="breadcrumb" separator-class="el-icon-arrow-right">
+                <el-breadcrumb-item
+                  :key="item.path"
+                  v-for="item in matched.slice(1,matched.length)"
+                >{{item.meta.title}}</el-breadcrumb-item>
+              </el-breadcrumb>
+              <div class="fl-right right-box">
+                <el-dropdown>
+                  <span class="el-dropdown-link">
+                    <img :src="userInfo.headerImg" height="30" width="30" />
+                    {{userInfo.title}}
+                    <i class="el-icon-arrow-down"></i>
                   </span>
-                </el-dropdown-item>
-                <el-dropdown-item @click.native="showPassword=true" icon="el-icon-s-custom">修改密码</el-dropdown-item>
-                <el-dropdown-item @click.native="toPerson" icon="el-icon-s-custom">个人信息</el-dropdown-item>
-                <el-dropdown-item @click.native="LoginOut" icon="el-icon-table-lamp">登 出</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-
+                  <el-dropdown-menu class="dropdown-group" slot="dropdown">
+                    <el-dropdown-item>
+                      <span>
+                        更多信息
+                        <el-badge is-dot />
+                      </span>
+                    </el-dropdown-item>
+                    <el-dropdown-item @click.native="showPassword=true" icon="el-icon-s-custom">修改密码</el-dropdown-item>
+                    <el-dropdown-item @click.native="toPerson" icon="el-icon-s-custom">个人信息</el-dropdown-item>
+                    <el-dropdown-item @click.native="LoginOut" icon="el-icon-table-lamp">登 出</el-dropdown-item>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
+            </el-header>
+            <!-- 当前面包屑用路由自动生成可根据需求修改 -->
+            <!--
+            :to="{ path: item.path }" 暂时注释不用-->
+            <HistoryComponent />
           </div>
-        </el-header>
-        <!-- 当前面包屑用路由自动生成可根据需求修改 -->
-        <!--
-        :to="{ path: item.path }" 暂时注释不用-->
-        <HistoryComponent />
-        </div>
         </transition>
         <transition mode="out-in" name="el-fade-in-linear">
           <keep-alive>
@@ -54,43 +56,38 @@
           </keep-alive>
         </transition>
         <transition mode="out-in" name="el-fade-in-linear">
-            <router-view v-if="!$route.meta.keepAlive" class="admin-box"></router-view>
+          <router-view v-if="!$route.meta.keepAlive" class="admin-box"></router-view>
         </transition>
       </el-main>
     </el-container>
-               <el-dialog
-              title="修改密码"
-              :visible.sync="showPassword"
-              @close="clearPassword"
-              width="360px"
-            >
-              <el-form ref="modifyPwdForm" :model="pwdModify" :rules="rules" label-width="80px">
-                <el-form-item prop="password" :minlength="6" label="原密码">
-                  <el-input v-model="pwdModify.password" show-password></el-input>
-                </el-form-item>
-                <el-form-item prop="newPassword" :minlength="6" label="新密码">
-                  <el-input v-model="pwdModify.newPassword" show-password></el-input>
-                </el-form-item>
-                <el-form-item prop="confirmPassword" :minlength="6" label="确认密码">
-                  <el-input v-model="pwdModify.confirmPassword" show-password></el-input>
-                </el-form-item>
-              </el-form>
-              <div slot="footer" class="dialog-footer">
-                <el-button @click="showPassword=false">取 消</el-button>
-                <el-button type="primary" @click="savePassword">确 定</el-button>
-              </div>
-            </el-dialog>
+    <el-dialog title="修改密码" :visible.sync="showPassword" @close="clearPassword" width="360px">
+      <el-form ref="modifyPwdForm" :model="pwdModify" :rules="rules" label-width="80px">
+        <el-form-item prop="password" :minlength="6" label="原密码">
+          <el-input v-model="pwdModify.password" show-password></el-input>
+        </el-form-item>
+        <el-form-item prop="newPassword" :minlength="6" label="新密码">
+          <el-input v-model="pwdModify.newPassword" show-password></el-input>
+        </el-form-item>
+        <el-form-item prop="confirmPassword" :minlength="6" label="确认密码">
+          <el-input v-model="pwdModify.confirmPassword" show-password></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="showPassword=false">取 消</el-button>
+        <el-button type="primary" @click="savePassword">确 定</el-button>
+      </div>
+    </el-dialog>
   </el-container>
 </template>
 
 <script>
-import Aside from '@/view/layout/aside'
-import HistoryComponent from '@/view/layout/aside/historyComponent/history'
+import Aside from "@/view/layout/aside";
+import HistoryComponent from "@/view/layout/aside/historyComponent/history";
 
-import { mapGetters, mapActions } from 'vuex'
-import { changePassword } from '@/api/user'
+import { mapGetters, mapActions } from "vuex";
+import { changePassword } from "@/api/user";
 export default {
-  name: 'Layout',
+  name: "Layout",
   data() {
     return {
       isCollapse: false,
@@ -101,59 +98,49 @@ export default {
       pwdModify: {},
       rules: {
         password: [
-          { required: true, message: '请输入密码', trigger: 'blur' },
-          { min: 6, message: '最少6个字符', trigger: 'blur' }
+          { required: true, message: "请输入密码", trigger: "blur" },
+          { min: 6, message: "最少6个字符", trigger: "blur" }
         ],
         newPassword: [
-          { required: true, message: '请输入新密码', trigger: 'blur' },
-          { min: 6, message: '最少6个字符', trigger: 'blur' }
+          { required: true, message: "请输入新密码", trigger: "blur" },
+          { min: 6, message: "最少6个字符", trigger: "blur" }
         ],
         confirmPassword: [
-          { required: true, message: '请输入确认密码', trigger: 'blur' },
-          { min: 6, message: '最少6个字符', trigger: 'blur' },
+          { required: true, message: "请输入确认密码", trigger: "blur" },
+          { min: 6, message: "最少6个字符", trigger: "blur" },
           {
             validator: (rule, value, callback) => {
               if (value !== this.pwdModify.newPassword) {
-                callback(new Error('两次密码不一致'))
+                callback(new Error("两次密码不一致"));
               } else {
-                callback()
+                callback();
               }
             },
-            trigger: 'blur'
+            trigger: "blur"
           }
         ]
-      },
-
-    }
+      }
+    };
   },
   components: {
-    Aside,HistoryComponent
-  },
-  created() {
-    let screenWidth = document.body.clientWidth
-    if (screenWidth < 1000) {
-      this.isMobile = true
-      this.isSider = false
-      this.isCollapse = !this.isCollapse
-    } else {
-      this.isMobile = false
-    }
+    Aside,
+    HistoryComponent
   },
   methods: {
-    ...mapActions('user', ['LoginOut']),
+    ...mapActions("user", ["LoginOut"]),
     totalCollapse() {
-      this.isCollapse = !this.isCollapse
-      this.isSider = !this.isCollapse
-      this.isShadowBg = !this.isCollapse
-      this.$bus.emit('totalCollapse')
+      this.isCollapse = !this.isCollapse;
+      this.isSider = !this.isCollapse;
+      this.isShadowBg = !this.isCollapse;
+      this.$bus.emit("collapse", this.isCollapse);
     },
     toPerson() {
-      this.$router.push({ name: 'person' })
+      this.$router.push({ name: "person" });
     },
     changeShadow() {
-      this.isShadowBg = !this.isShadowBg
-      this.isSider = !!this.isCollapse
-      this.totalCollapse()
+      this.isShadowBg = !this.isShadowBg;
+      this.isSider = !!this.isCollapse;
+      this.totalCollapse();
     },
     savePassword() {
       this.$refs.modifyPwdForm.validate(valid => {
@@ -163,57 +150,72 @@ export default {
             password: this.pwdModify.password,
             newPassword: this.pwdModify.newPassword
           }).then(() => {
-            this.$message.success('修改密码成功!')
-            this.showPassword = false
-          })
+            this.$message.success("修改密码成功!");
+            this.showPassword = false;
+          });
         } else {
-          return false
+          return false;
         }
-      })
+      });
     },
     clearPassword() {
       this.pwdModify = {
-        password: '',
-        newPassword: '',
-        confirmPassword: ''
-      }
-      this.$refs.modifyPwdForm.clearValidate()
+        password: "",
+        newPassword: "",
+        confirmPassword: ""
+      };
+      this.$refs.modifyPwdForm.clearValidate();
     }
   },
   computed: {
-    ...mapGetters('user', ['userInfo']),
-    ...mapGetters('history', ['historys','activeValue']),
+    ...mapGetters("user", ["userInfo"]),
+    ...mapGetters("history", ["historys", "activeValue"]),
     title() {
-      return this.$route.meta.title || '当前页面'
+      return this.$route.meta.title || "当前页面";
     },
     matched() {
-      return this.$route.matched
+      return this.$route.matched;
     }
   },
   mounted() {
+    let screenWidth = document.body.clientWidth;
+    if (screenWidth < 1000) {
+      this.isMobile = true;
+      this.isSider = false;
+      this.isCollapse = true;
+    } else if (screenWidth >= 1000 && screenWidth < 1200) {
+      this.isMobile = false;
+      this.isSider = false;
+      this.isCollapse = true;
+    } else {
+      this.isMobile = false;
+      this.isSider = true;
+      this.isCollapse = false;
+    }
+    this.$bus.emit("collapse", this.isCollapse);
+    this.$bus.emit("mobile", this.isMobile);
     window.onresize = () => {
       return (() => {
-        let screenWidth = document.body.clientWidth
-        if (!this.screenWidth && this.isSider) {
-          if (screenWidth < 1000) {
-            this.isMobile = true
-            this.isSider = false
-            this.isCollapse = true
-            this.$bus.emit('collapse', this.isCollapse)
-          }
+        let screenWidth = document.body.clientWidth;
+        if (screenWidth < 1000) {
+          this.isMobile = true;
+          this.isSider = false;
+          this.isCollapse = true;
+        } else if (screenWidth >= 1000 && screenWidth < 1200) {
+          this.isMobile = false;
+          this.isSider = false;
+          this.isCollapse = true;
         } else {
-          if (screenWidth < 1000) {
-            this.isMobile = true
-            this.isSider = false
-            this.isCollapse = true
-          } else {
-            this.isMobile = false
-          }
+          this.isMobile = false;
+          this.isSider = true;
+          this.isCollapse = false;
         }
-      })()
-    }
+        this.$bus.emit("collapse", this.isCollapse);
+        this.$bus.emit("mobile", this.isMobile);
+      })();
+    };
   }
-}
+};
 </script>
 
 <style lang="scss">
@@ -225,14 +227,14 @@ $mainHight: 100vh;
 .dropdown-group {
   min-width: 100px;
 }
-.topfix{
-  position:fixed;
-  top:0;
+.topfix {
+  position: fixed;
+  top: 0;
   box-sizing: border-box;
   z-index: 999;
 }
-.admin-box{
-  background-color: rgb(255,255,255);
+.admin-box {
+  background-color: rgb(255, 255, 255);
   margin-top: 100px;
 }
 .el-scrollbar__wrap {
@@ -269,10 +271,10 @@ $mainHight: 100vh;
       // padding: 6px;
       // border-bottom: 1px solid #eee;
     }
-    .router-history{
+    .router-history {
       background: #fff;
       padding: 0 6px;
-      border-top: 1px solid #DCDCDC;
+      border-top: 1px solid #dcdcdc;
     }
     &.el-main {
       overflow: auto;

+ 210 - 60
web/src/view/login/login.vue

@@ -1,57 +1,92 @@
 <template>
-  <el-container class="login-register-box">
-    <vue-particle-line></vue-particle-line>
-    <el-main class="login-box">
-      <h1 class="title-1">
-        <img
-          class="logo"
-          :src="require('@/assets/logo.png')"
-          alt=""
-          srcset=""
-        />
-      </h1>
-      <el-form :model="loginForm" :rules="rules" ref="loginForm" @keyup.enter.native="submitForm">
-        <el-form-item prop="username">
-          <el-input
-            placeholder="请输入用户名"
-            v-model="loginForm.username"
-          ></el-input>
-        </el-form-item>
-        <el-form-item prop="password">
-          <el-input
-            :type="lock === 'lock' ? 'password' : 'text'"
-            placeholder="请输入密码"
-            v-model="loginForm.password"
-          >
+  <div id="userLayout" class="user-layout-wrapper">
+    <div class="container">
+      <div class="top">
+        <div class="desc">
+          <img class="logo_login" src="@/assets/logo_login.png" alt="" />
+        </div>
+        <div class="header">
+          <a href="/">
+            <!-- <img src="~@/assets/logo.png" class="logo" alt="logo" /> -->
+            <span class="title">Gin-Vue-Admin</span>
+          </a>
+        </div>
+      </div>
+      <div class="main">
+        <el-form
+          :model="loginForm"
+          :rules="rules"
+          ref="loginForm"
+          @keyup.enter.native="submitForm"
+        >
+          <el-form-item prop="username">
+            <el-input
+              placeholder="请输入用户名"
+              v-model="loginForm.username"
+            >
             <i
-              :class="'el-input__icon el-icon-' + lock"
-              @click="changeLock"
-              slot="suffix"
-            ></i>
-          </el-input>
-        </el-form-item>
-        <el-form-item style="position:relative">
-          <el-input
-            v-model="loginForm.captcha"
-            name="logVerify"
-            placeholder="请输入验证码"
-            maxlength="10"
-          />
-          <img
-            v-if="picPath"
-            :src="path + picPath"
-            alt="请输入验证码"
-            @click="loginVefify()"
-            class="vPic"
-          />
-        </el-form-item>
-        <el-form-item>
-          <el-button @click="submitForm" style="width:100%">登 录</el-button>
-        </el-form-item>
-      </el-form>
-      <h3 class="title-3 fl-right">测试用户:admin 密码:123456</h3>
-    </el-main>
-  </el-container>
+                class="el-input__icon el-icon-user"
+                slot="suffix"
+              ></i></el-input>
+          </el-form-item>
+          <el-form-item prop="password">
+            <el-input
+              :type="lock === 'lock' ? 'password' : 'text'"
+              placeholder="请输入密码"
+              v-model="loginForm.password"
+            >
+              <i
+                :class="'el-input__icon el-icon-' + lock"
+                @click="changeLock"
+                slot="suffix"
+              ></i>
+            </el-input>
+          </el-form-item>
+          <el-form-item style="position:relative">
+            <el-input
+              v-model="loginForm.captcha"
+              name="logVerify"
+              placeholder="请输入验证码"
+              style="width:60%"
+            />
+            <div class="vPic">
+              <img
+                v-if="picPath"
+                :src="path + picPath"
+                alt="请输入验证码"
+                @click="loginVefify()"
+              />
+            </div>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="submitForm" style="width:100%"
+              >登 录</el-button
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div class="footer">
+        <div class="links">
+          <a href="http://doc.henrongyi.top/"
+            ><img src="@/assets/docs.png" class="link-icon"
+          /></a>
+          <a href="https://www.yuque.com/flipped-aurora/"
+            ><img src="@/assets/yuque.png" class="link-icon"
+          /></a>
+          <a href="https://github.com/flipped-aurora/gin-vue-admin"
+            ><img src="@/assets/github.png" class="link-icon"
+          /></a>
+          <a href="https://space.bilibili.com/322210472"
+            ><img src="@/assets/video.png" class="link-icon"
+          /></a>
+        </div>
+        <div class="copyright">
+          Copyright &copy; {{ curYear }} 💖flipped-aurora
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -75,12 +110,12 @@ export default {
         callback();
       }
     };
-
     return {
+      curYear: 0,
       lock: "lock",
       loginForm: {
-        username: "",
-        password: "",
+        username: "admin",
+        password: "123456",
         captcha: "",
         captchaId: "",
       },
@@ -95,6 +130,7 @@ export default {
   },
   created() {
     this.loginVefify();
+    this.curYear = new Date().getFullYear();
   },
   methods: {
     ...mapActions("user", ["LoginIn"]),
@@ -132,7 +168,6 @@ export default {
 
 <style scoped lang="scss">
 .login-register-box {
-  background: #fff;
   height: 100vh;
   .login-box {
     width: 40vw;
@@ -145,10 +180,125 @@ export default {
       width: 35vh;
     }
   }
-  .vPic {
-    position: absolute;
-    right: 10px;
-    bottom: 0px; // 适配ie
+}
+
+.link-icon {
+  width: 20px;
+  min-width: 20px;
+  height: 20px;
+  border-radius: 10px;
+}
+
+.vPic {
+  width: 33%;
+  height: 38px;
+  float: right !important;
+  background: #ccc;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+
+.logo_login {
+  width: 100px;
+}
+
+#userLayout.user-layout-wrapper {
+  height: 100%;
+  position: relative;
+  &.mobile {
+    .container {
+      .main {
+        max-width: 368px;
+        width: 98%;
+      }
+    }
+  }
+
+  .container {
+    position: relative;
+    overflow: auto;
+    width: 100%;
+    min-height: 100%;
+    background: #f0f2f5 url(~@/assets/background.svg) no-repeat 50%;
+    background-size: 100%;
+    padding: 110px 0 144px;
+    a {
+      text-decoration: none;
+    }
+
+    .top {
+      text-align: center;
+      margin-top: 20px;
+      .header {
+        height: 44px;
+        line-height: 44px;
+        margin-bottom: 30px;
+        .badge {
+          position: absolute;
+          display: inline-block;
+          line-height: 1;
+          vertical-align: middle;
+          margin-left: -12px;
+          margin-top: -10px;
+          opacity: 0.8;
+        }
+
+        .logo {
+          height: 44px;
+          vertical-align: top;
+          margin-right: 16px;
+          border-style: none;
+        }
+
+        .title {
+          font-size: 33px;
+          color: rgba(0, 0, 0, 0.85);
+          font-family: Avenir, "Helvetica Neue", Arial, Helvetica, sans-serif;
+          font-weight: 600;
+          position: relative;
+          top: 2px;
+        }
+      }
+      .desc {
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.45);
+        margin-top: 12px;
+      }
+    }
+
+    .main {
+      min-width: 260px;
+      width: 368px;
+      margin: 0 auto;
+    }
+
+    .footer {
+      position: relative;
+      width: 100%;
+      padding: 0 20px;
+      margin: 40px 0 10px;
+      text-align: center;
+      .links {
+        margin-bottom: 8px;
+        font-size: 14px;
+        width: 330px;
+        display: inline-flex;
+        flex-direction: row;
+        justify-content: space-between;
+        padding-right: 40px;
+        a {
+          color: rgba(0, 0, 0, 0.45);
+          transition: all 0.3s;
+        }
+      }
+      .copyright {
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 14px;
+        padding-right: 40px;
+      }
+    }
   }
 }
 </style>

+ 189 - 29
web/src/view/login/register.vue

@@ -1,24 +1,48 @@
 <template>
-  <el-container class="login-register-box">
-    <vue-particle-line></vue-particle-line>
-    <el-main class="login-box">
-      <h1 class="title-1">
-        <img class="logo" :src="require('@/assets/logo.png')">
-      </h1>
-      <el-form :model="registerForm" :rules="rules" ref="registerForm">
-        <el-form-item prop="username">
-          <el-input placeholder="请输入用户名" v-model="registerForm.username"></el-input>
-        </el-form-item>
-        <el-form-item prop="password">
-          <el-input
-            :type="lock==='lock'?'password':'text'"
-            placeholder="请输入密码"
-            v-model="registerForm.password"
-          >
-            <i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
-          </el-input>
-        </el-form-item>
-        <el-form-item prop="rePassword">
+  <div id="userLayout" class="user-layout-wrapper">
+    <div class="container">
+      <div class="top">
+        <div class="desc">
+          <img class="logo_login" src="@/assets/logo_login.png" alt="" />
+        </div>
+        <div class="header">
+          <a href="/">
+            <!-- <img src="~@/assets/logo.png" class="logo" alt="logo" /> -->
+            <span class="title">Gin-Vue-Admin</span>
+          </a>
+        </div>
+      </div>
+      <div class="main">
+        <el-form
+          :model="registerForm"
+          :rules="rules"
+          ref="registerForm"
+          @keyup.enter.native="submitForm"
+        >
+          <el-form-item prop="username">
+            <el-input
+              placeholder="请输入用户名"
+              v-model="registerForm.username"
+            >
+            <i
+                class="el-input__icon el-icon-user"
+                slot="suffix"
+              ></i></el-input>
+          </el-form-item>
+          <el-form-item prop="password">
+            <el-input
+              :type="lock === 'lock' ? 'password' : 'text'"
+              placeholder="请输入密码"
+              v-model="registerForm.password"
+            >
+              <i
+                :class="'el-input__icon el-icon-' + lock"
+                @click="changeLock"
+                slot="suffix"
+              ></i>
+            </el-input>
+          </el-form-item>
+          <el-form-item prop="rePassword" style="position:relative">
           <el-input
             :type="lock==='lock'?'password':'text'"
             placeholder="请再次输入密码"
@@ -27,12 +51,36 @@
             <i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
           </el-input>
         </el-form-item>
-        <el-form-item>
-          <el-button @click="submitForm" style="width:100%">注 册</el-button>
-        </el-form-item>
-      </el-form>
-    </el-main>
-  </el-container>
+        
+          <el-form-item>
+            <el-button type="primary" @click="submitForm" style="width:100%"
+              >注 册</el-button
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div class="footer">
+        <div class="links">
+          <a href="http://doc.henrongyi.top/"
+            ><img src="@/assets/docs.png" class="link-icon"
+          /></a>
+          <a href="https://www.yuque.com/flipped-aurora/"
+            ><img src="@/assets/yuque.png" class="link-icon"
+          /></a>
+          <a href="https://github.com/flipped-aurora/gin-vue-admin"
+            ><img src="@/assets/github.png" class="link-icon"
+          /></a>
+          <a href="https://space.bilibili.com/322210472"
+            ><img src="@/assets/video.png" class="link-icon"
+          /></a>
+        </div>
+        <div class="copyright">
+          Copyright &copy; 2020 💖flipped-aurora
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script>
@@ -110,18 +158,130 @@ export default {
 
 <style scoped lang="scss">
 .login-register-box {
-  background: #fff;
   height: 100vh;
   .login-box {
     width: 40vw;
     position: absolute;
     left: 50%;
     margin-left: -22vw;
-    top:5vh;
-    .logo{
+    top: 5vh;
+    .logo {
       height: 35vh;
       width: 35vh;
     }
   }
 }
+
+.link-icon {
+  width: 20px;
+  min-width: 20px;
+  height: 20px;
+  border-radius: 10px;
+}
+
+.vPic {
+  width: 33%;
+  height: 38px;
+  float: right !important;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+
+.logo_login {
+  width: 100px;
+}
+
+#userLayout.user-layout-wrapper {
+  height: 100%;
+  position: relative;
+  &.mobile {
+    .container {
+      .main {
+        max-width: 368px;
+        width: 98%;
+      }
+    }
+  }
+
+  .container {
+    width: 100%;
+    min-height: 100%;
+    background: #f0f2f5 url(~@/assets/background.svg) no-repeat 50%;
+    background-size: 100%;
+    padding: 110px 0 144px;
+    a {
+      text-decoration: none;
+    }
+
+    .top {
+      text-align: center;
+      margin-top: -50px;
+      .header {
+        height: 44px;
+        line-height: 44px;
+        margin-bottom: 30px;
+        .badge {
+          position: absolute;
+          display: inline-block;
+          line-height: 1;
+          vertical-align: middle;
+          margin-left: -12px;
+          margin-top: -10px;
+          opacity: 0.8;
+        }
+
+        .logo {
+          height: 44px;
+          vertical-align: top;
+          margin-right: 16px;
+          border-style: none;
+        }
+
+        .title {
+          font-size: 33px;
+          color: rgba(0, 0, 0, 0.85);
+          font-family: Avenir, "Helvetica Neue", Arial, Helvetica, sans-serif;
+          font-weight: 600;
+          position: relative;
+          top: 2px;
+        }
+      }
+      .desc {
+        font-size: 14px;
+        color: rgba(0, 0, 0, 0.45);
+        margin-top: 12px;
+      }
+    }
+
+    .main {
+      min-width: 260px;
+      width: 368px;
+      margin: 0 auto;
+    }
+
+    .footer {
+      position: relative;
+      width: 100%;
+      margin: 40px 0 0 0;
+      text-align: center;
+      .links {
+        margin-bottom: 8px;
+        font-size: 14px;
+        a {
+          color: rgba(0, 0, 0, 0.45);
+          transition: all 0.3s;
+          &:not(:last-child) {
+            margin-right: 80px;
+          }
+        }
+      }
+      .copyright {
+        color: rgba(0, 0, 0, 0.45);
+        font-size: 14px;
+      }
+    }
+  }
+}
 </style>

+ 13 - 4
web/src/view/superAdmin/authority/authority.vue

@@ -51,15 +51,15 @@
     </el-dialog>
 
     <el-drawer :visible.sync="drawer" :with-header="false" size="40%" title="角色配置" v-if="drawer">
-      <el-tabs class="role-box" type="border-card">
+      <el-tabs class="role-box" type="border-card" :before-leave="autoEnter">
         <el-tab-pane label="角色菜单">
-          <Menus :row="activeRow" />
+          <Menus :row="activeRow" ref="menus"/>
         </el-tab-pane>
         <el-tab-pane label="角色api">
-          <apis :row="activeRow" />
+          <apis :row="activeRow"  ref="apis"/>
         </el-tab-pane>
         <el-tab-pane label="资源权限">
-          <Datas :authority="tableData" :row="activeRow" />
+          <Datas :authority="tableData" :row="activeRow"  ref="datas"/>
         </el-tab-pane>
       </el-tabs>
     </el-drawer>
@@ -124,6 +124,15 @@ export default {
     Datas
   },
   methods: {
+    autoEnter(activeName, oldActiveName){
+      const paneArr = ["menus","apis","datas"]
+      if(oldActiveName){
+        if(this.$refs[paneArr[oldActiveName]].needConfirm){
+          this.$refs[paneArr[oldActiveName]].enterAndNext()
+          this.$refs[paneArr[oldActiveName]].needConfirm = false
+        }
+      }
+    },
     // 拷贝角色
     copyAuthority(row) {
       this.setOptions()

+ 10 - 1
web/src/view/superAdmin/authority/components/apis.vue

@@ -7,6 +7,7 @@
       :data="apiTreeData"
       :default-checked-keys="apiTreeIds"
       :props="apiDefaultProps"
+      @check="nodeChange"
       default-expand-all
       highlight-current
       node-key="onlyId"
@@ -32,6 +33,7 @@ export default {
     return {
       apiTreeData: [],
       apiTreeIds: [],
+      needConfirm:false,
       apiDefaultProps: {
         children: 'children',
         label: 'description'
@@ -39,6 +41,13 @@ export default {
     }
   },
   methods: {
+    nodeChange(){
+      this.needConfirm = true
+    },
+    // 暴露给外层使用的切换拦截统一方法
+    enterAndNext(){
+      this.authApiEnter()
+    },
     // 创建api树方法
     buildApiTree(apis) {
       const apiObj = new Object()
@@ -78,7 +87,7 @@ export default {
         casbinInfos
       })
       if (res.code == 0) {
-        this.$message({ type: 'success', message: res.msg })
+        this.$message({ type: 'success', message: "api设置成功" })
       }
     }
   },

+ 13 - 5
web/src/view/superAdmin/authority/components/datas.vue

@@ -3,8 +3,8 @@
       <div class="clearflex" style="margin:18px">
       <el-button @click="authDataEnter" class="fl-right" size="small" type="primary">确 定</el-button>
       <el-button @click="all" class="fl-left" size="small" type="primary">全选</el-button>
-      <el-button @click="self" class="fl-left" size="small" type="primary">本部门</el-button>
-      <el-button @click="selfAndChildren" class="fl-left" size="small" type="primary">部门及以下</el-button>
+      <el-button @click="self" class="fl-left" size="small" type="primary">本角色</el-button>
+      <el-button @click="selfAndChildren" class="fl-left" size="small" type="primary">本角色及子角色</el-button>
     </div>
      <el-checkbox-group v-model="dataAuthorityId" @change="selectAuthority">
         <el-checkbox v-for="(item,key) in authoritys" :label="item" :key="key">{{item.authorityName}}</el-checkbox>
@@ -18,7 +18,8 @@ export default {
   data() {
     return {
         authoritys:[],
-        dataAuthorityId:[]
+        dataAuthorityId:[],
+        needConfirm:false
     }
   },
   props: {
@@ -36,20 +37,26 @@ export default {
     }
   },
   methods:{
+    // 暴露给外层使用的切换拦截统一方法
+      enterAndNext(){
+        this.authDataEnter()
+      },
       all(){
          this.dataAuthorityId = [...this.authoritys]
          this.row.dataAuthorityId = this.dataAuthorityId
-
+         this.needConfirm = true
       },
       self(){
           this.dataAuthorityId = this.authoritys.filter(item=>item.authorityId===this.row.authorityId)
           this.row.dataAuthorityId = this.dataAuthorityId
+          this.needConfirm = true
       },
       selfAndChildren(){
          const arrBox = []
          this.getChildrenId(this.row,arrBox)
          this.dataAuthorityId = this.authoritys.filter(item=>arrBox.indexOf(item.authorityId)>-1)
          this.row.dataAuthorityId = this.dataAuthorityId
+         this.needConfirm = true
       },
       getChildrenId(row,arrBox){
           arrBox.push(row.authorityId)
@@ -61,7 +68,7 @@ export default {
       async authDataEnter(){
           const res = await setDataAuthority(this.row)
           if(res.code == 0){
-              this.$message({ type: 'success', message: res.msg })
+              this.$message({ type: 'success', message: "资源设置成功" })
           }
       },
     //   平铺角色
@@ -79,6 +86,7 @@ export default {
     //   选择
       selectAuthority(){
           this.row.dataAuthorityId = this.dataAuthorityId
+          this.needConfirm = true
       }
   },
   created() {

+ 10 - 1
web/src/view/superAdmin/authority/components/menus.vue

@@ -7,6 +7,7 @@
       :data="menuTreeData"
       :default-checked-keys="menuTreeIds"
       :props="menuDefaultProps"
+      @check="nodeChange"
       default-expand-all
       highlight-current
       node-key="ID"
@@ -32,6 +33,7 @@ export default {
     return {
       menuTreeData: [],
       menuTreeIds: [],
+      needConfirm:false,
       menuDefaultProps: {
         children: 'children',
         label: function(data){
@@ -41,6 +43,13 @@ export default {
     }
   },
   methods: {
+    nodeChange(){
+      this.needConfirm = true
+    },
+    // 暴露给外层使用的切换拦截统一方法
+    enterAndNext(){
+      this.relation()
+    },
     // 关联树 确认方法
     async relation() {
       const checkArr = this.$refs.menuTree.getCheckedNodes(false, true)
@@ -51,7 +60,7 @@ export default {
       if (res.code == 0) {
         this.$message({
           type: 'success',
-          message: '添加成功!'
+          message: '菜单设置成功!'
         })
       }
     }

+ 139 - 125
web/src/view/superAdmin/menu/menu.vue

@@ -36,41 +36,48 @@
     </el-table>
 
     <el-dialog :before-close="handleClose" :visible.sync="dialogFormVisible" :title="dialogTitle">
-      <el-form :inline="true" :model="form" :rules="rules" label-width="85px" ref="menuForm">
-        <el-form-item label="路由name" prop="path">
+      <el-form
+        :inline="true"
+        :model="form"
+        :rules="rules"
+        label-width="85px"
+        ref="menuForm"
+        label-position="top"
+      >
+        <el-form-item label="路由name" prop="path" style="width:30%">
           <el-input autocomplete="off" placeholder="唯一英文字符串" v-model="form.path"></el-input>
         </el-form-item>
-        <el-form-item label="是否隐藏">
+        <el-form-item label="是否隐藏" style="width:30%">
           <el-select placeholder="是否在列表隐藏" v-model="form.hidden">
             <el-option :value="false" label="否"></el-option>
             <el-option :value="true" label="是"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="父节点Id">
-           <el-cascader
-              :disabled="!this.isEdit"
-              v-model="form.parentId"
-              :options="menuOption"
-              :show-all-levels="false"
-              :props="{ checkStrictly: true,label:'title',value:'ID',disabled:'disabled',emitPath:false}"
-              filterable>
-              </el-cascader>
+        <el-form-item label="父节点Id" style="width:30%">
+          <el-cascader
+            :disabled="!this.isEdit"
+            v-model="form.parentId"
+            :options="menuOption"
+            :show-all-levels="false"
+            :props="{ checkStrictly: true,label:'title',value:'ID',disabled:'disabled',emitPath:false}"
+            filterable
+          ></el-cascader>
         </el-form-item>
-        <el-form-item label="文件路径" prop="component">
+        <el-form-item label="文件路径" prop="component" style="width:30%">
           <el-input autocomplete="off" v-model="form.component"></el-input>
         </el-form-item>
-        <el-form-item label="展示名称" prop="meta.title">
+        <el-form-item label="展示名称" prop="meta.title" style="width:30%">
           <el-input autocomplete="off" v-model="form.meta.title"></el-input>
         </el-form-item>
-        <el-form-item label="图标" prop="meta.icon">
+        <el-form-item label="图标" prop="meta.icon" style="width:30%">
           <el-input autocomplete="off" v-model="form.meta.icon">
             <template slot="prepend">el-icon-</template>
           </el-input>
         </el-form-item>
-        <el-form-item label="排序标记" prop="sort">
+        <el-form-item label="排序标记" prop="sort" style="width:30%">
           <el-input autocomplete="off" v-model.number="form.sort"></el-input>
         </el-form-item>
-        <el-form-item label="keepAlive" prop="meta.keepAlive">
+        <el-form-item label="keepAlive" prop="meta.keepAlive" style="width:30%">
           <el-select placeholder="是否keepAlive缓存页面" v-model="form.meta.keepAlive">
             <el-option :value="false" label="否"></el-option>
             <el-option :value="true" label="是"></el-option>
@@ -95,191 +102,198 @@ import {
   addBaseMenu,
   deleteBaseMenu,
   getBaseMenuById
-} from '@/api/menu'
-import infoList from '@/components/mixins/infoList'
+} from "@/api/menu";
+import infoList from "@/components/mixins/infoList";
 export default {
-  name: 'Menus',
+  name: "Menus",
   mixins: [infoList],
   data() {
     return {
       listApi: getMenuList,
       dialogFormVisible: false,
-      dialogTitle:"新增菜单",
-      menuOption:[
+      dialogTitle: "新增菜单",
+      menuOption: [
         {
-          ID:"0",
-          title:"根菜单"
+          ID: "0",
+          title: "根菜单"
         }
       ],
       form: {
         ID: 0,
-        path: '',
-        name: '',
-        hidden: '',
-        parentId: '',
-        component: '',
+        path: "",
+        name: "",
+        hidden: "",
+        parentId: "",
+        component: "",
         meta: {
-          title: '',
-          icon: '',
-          defaultMenu:false,
-          keepAlive:false
+          title: "",
+          icon: "",
+          defaultMenu: false,
+          keepAlive: false
         }
       },
       rules: {
-        path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
+        path: [{ required: true, message: "请输入菜单name", trigger: "blur" }],
         component: [
-          { required: true, message: '请输入文件路径', trigger: 'blur' }
+          { required: true, message: "请输入文件路径", trigger: "blur" }
         ],
-        'meta.title': [
-          { required: true, message: '请输入菜单展示名称', trigger: 'blur' }
+        "meta.title": [
+          { required: true, message: "请输入菜单展示名称", trigger: "blur" }
         ]
       },
       isEdit: false
-    }
+    };
   },
   methods: {
-    setOptions(){
-       this.menuOption = [{
-          ID:"0",
-          title:"根目录"
-        }]
-      this.setMenuOptions(this.tableData,this.menuOption,false)
-    },
-    setMenuOptions(menuData,optionsData,disabled){
-      menuData&&menuData.map(item=>{
-        if(item.children.length){
-          const option = {
-            title:item.meta.title,
-            ID:String(item.ID),
-            disabled:disabled||item.ID == this.form.ID,
-            children:[]
+    setOptions() {
+      this.menuOption = [
+        {
+          ID: "0",
+          title: "根目录"
         }
-          this.setMenuOptions(item.children,option.children,disabled||item.ID == this.form.ID)
-          optionsData.push(option)
-        }else{
-          const option = {
-              title:item.meta.title,
-              ID:String(item.ID),
-              disabled:disabled||item.ID == this.form.ID,
+      ];
+      this.setMenuOptions(this.tableData, this.menuOption, false);
+    },
+    setMenuOptions(menuData, optionsData, disabled) {
+      menuData &&
+        menuData.map(item => {
+          if (item.children.length) {
+            const option = {
+              title: item.meta.title,
+              ID: String(item.ID),
+              disabled: disabled || item.ID == this.form.ID,
+              children: []
+            };
+            this.setMenuOptions(
+              item.children,
+              option.children,
+              disabled || item.ID == this.form.ID
+            );
+            optionsData.push(option);
+          } else {
+            const option = {
+              title: item.meta.title,
+              ID: String(item.ID),
+              disabled: disabled || item.ID == this.form.ID
+            };
+            optionsData.push(option);
           }
-          optionsData.push(option)
-        }
-      })
+        });
     },
     handleClose(done) {
-      this.initForm()
-      done()
+      this.initForm();
+      done();
     },
     // 懒加载子菜单
     load(tree, treeNode, resolve) {
       resolve([
         {
           id: 31,
-          date: '2016-05-01',
-          name: '王小虎',
-          address: '上海市普陀区金沙江路 1519 弄'
+          date: "2016-05-01",
+          name: "王小虎",
+          address: "上海市普陀区金沙江路 1519 弄"
         },
         {
           id: 32,
-          date: '2016-05-01',
-          name: '王小虎',
-          address: '上海市普陀区金沙江路 1519 弄'
+          date: "2016-05-01",
+          name: "王小虎",
+          address: "上海市普陀区金沙江路 1519 弄"
         }
-      ])
+      ]);
     },
     // 删除菜单
     deleteMenu(ID) {
-      this.$confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
+      this.$confirm("此操作将永久删除所有角色下该菜单, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
       })
         .then(async () => {
-          const res = await deleteBaseMenu({ ID })
+          const res = await deleteBaseMenu({ ID });
           if (res.code == 0) {
             this.$message({
-              type: 'success',
-              message: '删除成功!'
-            })
-            this.getTableData()
+              type: "success",
+              message: "删除成功!"
+            });
+            this.getTableData();
           }
         })
         .catch(() => {
           this.$message({
-            type: 'info',
-            message: '已取消删除'
-          })
-        })
+            type: "info",
+            message: "已取消删除"
+          });
+        });
     },
     // 初始化弹窗内表格方法
     initForm() {
-      this.$refs.menuForm.resetFields()
+      this.$refs.menuForm.resetFields();
       this.form = {
         ID: 0,
-        path: '',
-        name: '',
-        hidden: '',
-        parentId: '',
-        component: '',
+        path: "",
+        name: "",
+        hidden: "",
+        parentId: "",
+        component: "",
         meta: {
-          title: '',
-          icon: '',
-          defaultMenu:false,
-          keepAlive:""
+          title: "",
+          icon: "",
+          defaultMenu: false,
+          keepAlive: ""
         }
-      }
+      };
     },
     // 关闭弹窗
     closeDialog() {
-      this.initForm()
-      this.dialogFormVisible = false
+      this.initForm();
+      this.dialogFormVisible = false;
     },
     // 添加menu
     async enterDialog() {
       this.$refs.menuForm.validate(async valid => {
         if (valid) {
-          let res
-          this.form.name = this.form.path
+          let res;
+          this.form.name = this.form.path;
           if (this.isEdit) {
-            res = await updateBaseMenu(this.form)
+            res = await updateBaseMenu(this.form);
           } else {
-            res = await addBaseMenu(this.form)
+            res = await addBaseMenu(this.form);
           }
           if (res.code == 0) {
             this.$message({
-              type: 'success',
-              message: this.isEdit?'编辑成功':'添加成功!'
-            })
-            this.getTableData()
+              type: "success",
+              message: this.isEdit ? "编辑成功" : "添加成功!"
+            });
+            this.getTableData();
           }
-          this.initForm()
-          this.dialogFormVisible = false
+          this.initForm();
+          this.dialogFormVisible = false;
         }
-      })
+      });
     },
     // 添加菜单方法,id为 0则为添加根菜单
     addMenu(id) {
-      this.dialogTitle = "新增菜单"
-      this.form.parentId = String(id)
-      this.isEdit = false
-      this.setOptions()
-      this.dialogFormVisible = true
+      this.dialogTitle = "新增菜单";
+      this.form.parentId = String(id);
+      this.isEdit = false;
+      this.setOptions();
+      this.dialogFormVisible = true;
     },
     // 修改菜单方法
     async editMenu(id) {
-      this.dialogTitle = "编辑菜单"
-      const res = await getBaseMenuById({ id })
-      this.form = res.data.menu
-      this.isEdit = true
-      this.setOptions()
-      this.dialogFormVisible = true
-    },
+      this.dialogTitle = "编辑菜单";
+      const res = await getBaseMenuById({ id });
+      this.form = res.data.menu;
+      this.isEdit = true;
+      this.setOptions();
+      this.dialogFormVisible = true;
+    }
   },
-   async created() {
-    this.pageSize = 999
-    await this.getTableData()
+  async created() {
+    this.pageSize = 999;
+    await this.getTableData();
   }
-}
+};
 </script>
 <style scoped lang="scss">
 .button-box {

+ 88 - 85
web/src/view/superAdmin/user/user.vue

@@ -18,27 +18,24 @@
         <template slot-scope="scope">
           <el-cascader
             @change="changeAuthority(scope.row)"
-              v-model="scope.row.authority.authorityId"
-              :options="authOptions"
-              :show-all-levels="false"
-              :props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
-              filterable>
-              </el-cascader>
+            v-model="scope.row.authority.authorityId"
+            :options="authOptions"
+            :show-all-levels="false"
+            :props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
+            filterable
+          ></el-cascader>
         </template>
       </el-table-column>
       <el-table-column label="操作" min-width="150">
         <template slot-scope="scope">
-          <el-popover
-          placement="top"
-          width="160"
-          v-model="scope.row.visible">
-          <p>确定要删除此用户吗</p>
-          <div style="text-align: right; margin: 0">
-            <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
-            <el-button type="primary" size="mini" @click="deleteUser(scope.row)">确定</el-button>
-          </div>
-           <el-button type="text" size="small" slot="reference">删除</el-button>
-        </el-popover>
+          <el-popover placement="top" width="160" v-model="scope.row.visible">
+            <p>确定要删除此用户吗</p>
+            <div style="text-align: right; margin: 0">
+              <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
+              <el-button type="primary" size="mini" @click="deleteUser(scope.row)">确定</el-button>
+            </div>
+            <el-button type="text" size="small" slot="reference">删除</el-button>
+          </el-popover>
         </template>
       </el-table-column>
     </el-table>
@@ -54,7 +51,7 @@
     ></el-pagination>
 
     <el-dialog :visible.sync="addUserDialog" custom-class="user-dialog" title="新增用户">
-      <el-form :rules="rules" ref="userForm" :model="userInfo" >
+      <el-form :rules="rules" ref="userForm" :model="userInfo">
         <el-form-item label="用户名" label-width="80px" prop="username">
           <el-input v-model="userInfo.username"></el-input>
         </el-form-item>
@@ -80,12 +77,12 @@
         <el-form-item label="用户角色" label-width="80px" prop="authorityId">
           <el-cascader
             @change="changeAuthority(scope.row)"
-              v-model="userInfo.authorityId"
-              :options="authOptions"
-              :show-all-levels="false"
-              :props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
-              filterable>
-              </el-cascader>
+            v-model="userInfo.authorityId"
+            :options="authOptions"
+            :show-all-levels="false"
+            :props="{ checkStrictly: true,label:'authorityName',value:'authorityId',disabled:'disabled',emitPath:false}"
+            filterable
+          ></el-cascader>
         </el-form-item>
       </el-form>
       <div class="dialog-footer" slot="footer">
@@ -99,115 +96,121 @@
 
 <script>
 // 获取列表内容封装在mixins内部  getTableData方法 初始化已封装完成
-const path = process.env.VUE_APP_BASE_API
-import { getUserList, setUserAuthority, register, deleteUser } from '@/api/user'
-import { getAuthorityList } from '@/api/authority'
-import infoList from '@/components/mixins/infoList'
-import { mapGetters } from 'vuex'
+const path = process.env.VUE_APP_BASE_API;
+import {
+  getUserList,
+  setUserAuthority,
+  register,
+  deleteUser
+} from "@/api/user";
+import { getAuthorityList } from "@/api/authority";
+import infoList from "@/components/mixins/infoList";
+import { mapGetters } from "vuex";
 export default {
-  name: 'Api',
+  name: "Api",
   mixins: [infoList],
   data() {
     return {
       listApi: getUserList,
-      path:path,
+      path: path,
       authOptions: [],
       addUserDialog: false,
       userInfo: {
-        username: '',
-        password: '',
-        nickName: '',
-        headerImg: '',
-        authorityId: ''
+        username: "",
+        password: "",
+        nickName: "",
+        headerImg: "",
+        authorityId: ""
       },
       rules: {
-        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+        username: [
+          { required: true, message: "请输入用户名", trigger: "blur" }
+        ],
         password: [
-          { required: true, message: '请输入用户密码', trigger: 'blur' }
+          { required: true, message: "请输入用户密码", trigger: "blur" }
         ],
         nickName: [
-          { required: true, message: '请输入用户昵称', trigger: 'blur' }
+          { required: true, message: "请输入用户昵称", trigger: "blur" }
         ],
         authorityId: [
-          { required: true, message: '请选择用户角色', trigger: 'blur' }
+          { required: true, message: "请选择用户角色", trigger: "blur" }
         ]
-      },
-    }
+      }
+    };
   },
   computed: {
-    ...mapGetters('user', ['token'])
+    ...mapGetters("user", ["token"])
   },
   methods: {
-     setOptions(authData){
-      this.authOptions = []
-      this.setAuthorityOptions(authData,this.authOptions)
+    setOptions(authData) {
+      this.authOptions = [];
+      this.setAuthorityOptions(authData, this.authOptions);
     },
-    setAuthorityOptions(AuthorityData,optionsData){
-      AuthorityData&&AuthorityData.map(item=>{
-        if(item.children.length){
-          const option = {
-            authorityId:item.authorityId,
-            authorityName:item.authorityName,
-            children:[]
-        }
-          this.setAuthorityOptions(item.children,option.children)
-          optionsData.push(option)
-        }else{
-          const option = {
-              authorityId:item.authorityId,
-              authorityName:item.authorityName,
+    setAuthorityOptions(AuthorityData, optionsData) {
+      AuthorityData &&
+        AuthorityData.map(item => {
+          if (item.children.length) {
+            const option = {
+              authorityId: item.authorityId,
+              authorityName: item.authorityName,
+              children: []
+            };
+            this.setAuthorityOptions(item.children, option.children);
+            optionsData.push(option);
+          } else {
+            const option = {
+              authorityId: item.authorityId,
+              authorityName: item.authorityName
+            };
+            optionsData.push(option);
           }
-          optionsData.push(option)
-        }
-      })
+        });
     },
-    async deleteUser(row){
-      const res = await deleteUser({id:row.ID})
-      if(res.code == 0){
-        this.getTableData()
-        row.visible = false
+    async deleteUser(row) {
+      const res = await deleteUser({ id: row.ID });
+      if (res.code == 0) {
+        this.getTableData();
+        row.visible = false;
       }
     },
     async enterAddUserDialog() {
       this.$refs.userForm.validate(async valid => {
         if (valid) {
-          const res = await register(this.userInfo)
+          const res = await register(this.userInfo);
           if (res.code == 0) {
-            this.$message({ type: 'success', message: '创建成功' })
+            this.$message({ type: "success", message: "创建成功" });
           }
-          await this.getTableData()
-          this.closeAddUserDialog()
+          await this.getTableData();
+          this.closeAddUserDialog();
         }
-      })
+      });
     },
     closeAddUserDialog() {
-      this.$refs.userForm.resetFields()
-      this.addUserDialog = false
+      this.$refs.userForm.resetFields();
+      this.addUserDialog = false;
     },
     handleAvatarSuccess(res) {
-      this.userInfo.headerImg = res.data.file.url
+      this.userInfo.headerImg = res.data.file.url;
     },
     addUser() {
-      this.addUserDialog = true
+      this.addUserDialog = true;
     },
     async changeAuthority(row) {
       const res = await setUserAuthority({
         uuid: row.uuid,
         authorityId: row.authority.authorityId
-      })
+      });
       if (res.code == 0) {
-        this.$message({ type: 'success', message: '角色设置成功' })
+        this.$message({ type: "success", message: "角色设置成功" });
       }
     }
   },
   async created() {
-    this.getTableData()
-    const res = await getAuthorityList({ page: 1, pageSize: 999 })
-    this.setOptions(res.data.list)
+    this.getTableData();
+    const res = await getAuthorityList({ page: 1, pageSize: 999 });
+    this.setOptions(res.data.list);
   }
-
-  
-}
+};
 </script>
 <style scoped lang="scss">
 .button-box {

+ 6 - 0
web/src/view/systemTools/autoCode/component/fieldDialog.vue

@@ -6,6 +6,11 @@
                 <el-input v-model="dialogMiddle.fieldName" autocomplete="off"></el-input>
                 </el-col>
             </el-form-item>
+            <el-form-item label="Field中文名" prop="fieldDesc">
+                <el-col :span="6">
+                <el-input v-model="dialogMiddle.fieldDesc" autocomplete="off"></el-input>
+                </el-col>
+            </el-form-item>
             <el-form-item label="FieldJSON" prop="fieldJson">
                 <el-col :span="6">
                 <el-input v-model="dialogMiddle.fieldJson" autocomplete="off"></el-input>
@@ -69,6 +74,7 @@ export default {
             ],
             rules:{
                 fieldName:[ { required: true, message: '请输入field英文名', trigger: 'blur' }],
+                fieldDesc:[ { required: true, message: '请输入field中文名', trigger: 'blur' }],
                 fieldJson:[ { required: true, message: '请输入field格式化json', trigger: 'blur' }],
                 fieldType:[ { required: true, message: '请选择field数据类型', trigger: 'blur' }]
             }

+ 11 - 1
web/src/view/systemTools/autoCode/index.vue

@@ -8,9 +8,12 @@
             <el-form-item label="Struct简称" prop="abbreviation">
                 <el-input v-model="form.abbreviation" placeholder="简称会作为入参对象名和路由group"></el-input>
             </el-form-item>
-            <el-form-item label="Package名称" prop="packageName">
+            <el-form-item label="文件名称" prop="packageName">
                 <el-input v-model="form.packageName"></el-input>
             </el-form-item>
+            <el-form-item label="自行创建api入库">
+                <el-checkbox v-model="form.autoCreateApiToSql">自动创建api</el-checkbox>
+            </el-form-item>
         </el-form>
         <!-- 组件列表 -->
         <div class="button-box clearflex">
@@ -28,6 +31,11 @@
                 prop="fieldName"
                 label="Field名"
                 width="280">
+            </el-table-column>
+             <el-table-column
+                prop="fieldDesc"
+                label="中文名"
+                width="280">
             </el-table-column>
             <el-table-column
                 prop="fieldJson"
@@ -74,6 +82,7 @@
 <script>
 const fieldTemplate={
             fieldName:"",
+            fieldDesc:"",
             fieldType:"",
             fieldJson:"",
             columnName:"",
@@ -91,6 +100,7 @@ export default {
                 structName:"",
                 packageName:"",
                 abbreviation:"",
+                autoCreateApiToSql:false,
                 fields:[]
             },
             rules:{

Some files were not shown because too many files changed in this diff