Browse Source

2024-5-22-展示

rui.jiang 1 year ago
parent
commit
d969d219de

File diff suppressed because it is too large
+ 14222 - 0
package-lock.json


+ 1 - 0
package.json

@@ -7,6 +7,7 @@
     "build": "vue-cli-service build"
   },
   "dependencies": {
+    "@riophae/vue-treeselect": "^0.4.0",
     "axios": "^1.6.8",
     "core-js": "^3.8.3",
     "echarts": "^5.5.0",

+ 4 - 4
public/config/config.js

@@ -1,8 +1,8 @@
 const config = {
-  API: '/api',
-  upload: 'http://xxx'
-}
-window._BASE_CONFIG = config
+  API: "/api",
+  // upload: "http://192.168.50.235:16200",
+};
+window._BASE_CONFIG = config;
 //冻结对象
 // if (Object.freeze) {
 //   Object.freeze(window._BASE_CONFIG)

+ 1 - 3
src/App.vue

@@ -11,9 +11,7 @@ import { login } from "@/api/login";
 import { testApi } from "@/api/test";
 import "@/assets/style/index.css";
 export default {
-  created() {
-    // this.test('2122')
-  },
+  created() {},
   components: { ThemePicker },
   metaInfo() {
     return {

+ 17 - 0
src/api/dict.js

@@ -0,0 +1,17 @@
+/*
+ * @Author: your name
+ * @Date: 2024-05-20 17:07:07
+ * @LastEditTime: 2024-05-20 17:07:53
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/api/dice.js
+ */
+import request from "@/utils/request";
+
+export function dictType(data) {
+  return request({
+    url: "/energy-manage-service/dict/getDictList",
+    method: "post",
+    data,
+  });
+}

+ 185 - 0
src/api/system.js

@@ -0,0 +1,185 @@
+/*
+ * @Author: your name
+ * @Date: 2024-05-20 09:36:55
+ * @LastEditTime: 2024-05-22 09:13:09
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/api/system.js
+ */
+import request from "@/utils/request";
+//用户退出登录
+
+export function userLogout(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/userLogout",
+    method: "post",
+    data,
+  });
+}
+export function getUserTableList(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/getUserByName",
+    method: "post",
+    data,
+  });
+}
+//用户启用
+export function enableUser(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/enableUser",
+    method: "post",
+    data,
+  });
+}
+//用户禁用
+export function disableUser(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/disableUser",
+    method: "post",
+    data,
+  });
+}
+//查看用户详情信息
+export function getUserInfoByUserId(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/getUserById",
+    method: "get",
+    params: data,
+  });
+}
+//修改用户密码
+export function updatePWD(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/updatePWD",
+    method: "post",
+    data,
+  });
+}
+//删除用户接口
+
+export function deleteUserInfo(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/deleteUser",
+    method: "post",
+    data,
+  });
+}
+//新增用户接口
+export function addUser(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/addUser",
+    method: "post",
+    data,
+  });
+}
+//编辑用户接口
+export function editUser(data) {
+  return request({
+    url: "/energy-manage-service/sysuserinfo/updateUser",
+    method: "post",
+    data,
+  });
+}
+//角色列表
+///energy-manage-service/sysrole
+export function getRoleTableList(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/通过角色名称查询角色列表",
+    method: "post",
+    data,
+  });
+}
+//删除角色
+
+export function deleteRoleInfo(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/deleteRole",
+    method: "post",
+    data,
+  });
+}
+//新增角色接口
+export function addRole(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/addRole",
+    method: "post",
+    data,
+  });
+}
+//编辑角色接口
+export function editRole(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/updateRole",
+    method: "post",
+    data,
+  });
+}
+//查看角色详情信息
+export function getRoleBId(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/getRoleBId",
+    method: "post",
+    data,
+  });
+}
+//更新角色状态
+
+export function updateRoleAvailable(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/updateRoleAvailable",
+    method: "post",
+    data,
+  });
+}
+
+//通过角色获取权限
+export function getDetailRoleAuth(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/getRolePermission",
+    method: "post",
+    data,
+  });
+}
+//更新角色菜单权限
+
+export function updateRolePermission(data) {
+  return request({
+    url: "/energy-manage-service/sysrole/updateRolePermission",
+    method: "post",
+    data,
+  });
+}
+
+//获取菜单列表
+export function getAllMenu(data) {
+  return request({
+    url: "/energy-manage-service/syspermission/getAll",
+    method: "post",
+    data,
+  });
+}
+//更新菜单权限
+export function updateMenuFn(data) {
+  return request({
+    url: "/energy-manage-service/syspermission/update",
+    method: "post",
+    data,
+  });
+}
+//删除菜单
+export function deleteMenuFn(data) {
+  return request({
+    url: "/energy-manage-service/syspermission/delete",
+    method: "post",
+    data,
+  });
+}
+
+//增加菜单
+export function addMenuFn(data) {
+  return request({
+    url: "/energy-manage-service/syspermission/add",
+    method: "post",
+    data,
+  });
+}

+ 10 - 1
src/components/HeaderCom.vue

@@ -15,7 +15,7 @@
         <img src="@/assets/portrait.png" slot="reference" />
         <div>
           <div class="cursor-pointer boxmini">
-            <p>账号:andmi</p>
+            <p>账号:admin</p>
           </div>
           <el-divider></el-divider>
           <div class="cursor-pointer boxmini">
@@ -44,6 +44,7 @@
 </template>
 
 <script>
+import { userLogout } from "@/api/system";
 import ThemePicker from "@/components/ThemePicker";
 export default {
   data() {
@@ -79,6 +80,14 @@ export default {
       // 设置当前时间数据
       this.currentDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
     },
+    skip() {
+      userLogout({
+        phone: this.$store.state.auth.userInfo.userInfo.userPhone,
+      }).then((res) => {
+        this.$store.commit("auth/RESET_USER_STATE");
+        this.$router.push("/login");
+      });
+    },
   },
 };
 </script>

+ 0 - 3
src/components/ThemePicker/index.vue

@@ -120,9 +120,6 @@ export default {
 
       this.$emit("change", val);
       const that = this;
-      // setTimeout(() => {
-
-      // }, 2000);
     },
 
     updateStyle(style, oldCluster, newCluster) {

+ 78 - 77
src/router/index.js

@@ -1,27 +1,40 @@
-// router/index.js
 import Vue from "vue";
 import VueRouter from "vue-router";
 import Home from "../views/home/Index.vue";
 
 Vue.use(VueRouter);
 
-const routes = [
-  {
-    path: "/",
-    redirect: "/login",
-  },
-  {
-    path: "/home",
-    redirect: "/home/cockpitManage",
-    name: "home",
-    component: Home,
-    children: [
-      // 驾驶舱
+const createRouter = () =>
+  new VueRouter({
+    mode: "history",
+    base: process.env.BASE_URL,
+    scrollBehavior: () => ({ y: 0 }),
+    routes: [
       {
-        path: "cockpitManage",
-        name: "cockpitManage",
-        component: () => import("../views/admin/cockpitManage/Index.vue"),
+        path: "/",
+        redirect: "/login",
+      },
+      {
+        path: "/home",
+        redirect: "/home/cockpitManage",
+        name: "home",
+        component: Home,
         children: [
+          // 驾驶舱
+          {
+            path: "cockpitManage",
+            name: "cockpitManage",
+            component: () => import("../views/admin/cockpitManage/Index.vue"),
+            children: [
+              // 电子地图
+              {
+                path: "electronic-map",
+                name: "electronicMap",
+                component: () =>
+                  import("../views/admin/cockpitManage/electronicMap.vue"),
+              },
+            ],
+          },
           // 电子地图
           {
             path: "electronic-map",
@@ -29,76 +42,64 @@ const routes = [
             component: () =>
               import("../views/admin/cockpitManage/electronicMap.vue"),
           },
+          // 数据操作
+          {
+            path: "dataAdministration",
+            name: "dataAdministration",
+            component: () => import("../views/dataAdministration/index.vue"),
+          },
+          // 企业信息
+          {
+            path: "enterprise",
+            name: "enterprise",
+            component: () => import("../views/ledger/enterprise.vue"),
+          },
+          // 风场信息
+          {
+            path: "windsite",
+            name: "windsite",
+            component: () => import("../views/ledger/windsite.vue"),
+          },
+          // 风机信息
+          {
+            path: "draught",
+            name: "draught",
+            component: () => import("../views/ledger/draught.vue"),
+          },
+          // 机型信息
+          {
+            path: "milltype",
+            name: "milltype",
+            component: () => import("../views/ledger/milltype.vue"),
+          },
+          // 测风塔信息
+          {
+            path: "anemometer",
+            name: "anemometer",
+            component: () => import("../views/ledger/anemometer.vue"),
+          },
         ],
       },
-      // 电子地图
-      {
-        path: 'electronic-map',
-        name: 'electronicMap',
-        component: () =>
-          import('../views/admin/cockpitManage/electronicMap.vue')
-      },
-      //数据操作
       {
-        path: 'dataAdministration',
-        name: 'dataAdministration',
-        component: () =>
-          import('../views/dataAdministration/index.vue')
+        path: "/login",
+        name: "login",
+        component: () => import("../views/login/Index.vue"),
       },
-      //企业信息
-      {
-        path: 'enterprise',
-        name: 'enterprise',
-        component: () =>
-          import('../views/ledger/enterprise.vue')
-      },
-      //风场信息
-      {
-        path: 'windsite',
-        name: 'windsite',
-        component: () =>
-          import('../views/ledger/windsite.vue')
-      },
-      // 风机信息
-      {
-        path: 'draught',
-        name: 'draught',
-        component: () =>
-          import('../views/ledger/draught.vue')
-      },
-      // 机型信息
-      {
-        path: 'milltype',
-        name: 'milltype',
-        component: () =>
-          import('../views/ledger/milltype.vue')
-      },
-        // 测风塔信息
-        {
-          path: 'anemometer',
-          name: 'anemometer',
-          component: () =>
-            import('../views/ledger/anemometer.vue')
-        },
-    ]
-  },
-  {
-    path: "/login",
-    name: "login",
-    component: () => import("../views/login/Index.vue"),
-  },
-];
+    ],
+  });
 
-const router = new VueRouter({
-  mode: "history",
-  base: process.env.BASE_URL,
-  scrollBehavior: () => ({ y: 0 }),
-  routes,
-});
+const router = createRouter();
 
 const originalPush = VueRouter.prototype.push;
 VueRouter.prototype.push = function push(location) {
   return originalPush.call(this, location).catch((err) => err);
 };
 
+// 重置路由
+export function resetRouter() {
+  const newRouter = createRouter();
+  router.matcher = newRouter.matcher; // reset router
+  console.log(router.getRoutes(), "重置后的路由");
+}
+
 export default router;

+ 19 - 11
src/store/auth.js

@@ -1,20 +1,21 @@
 import { login } from "../api/login";
 import { getAuthRouterFn } from "@/utils/getAuth";
+import { resetRouter } from "@/router/index";
 
 export default {
   namespaced: true, // 子模块一定要开启命名空间
   state: {
     userInfo: {},
-    // routes: [],
   },
   getters: {},
   mutations: {
     SET_USERINFO(state, payload) {
       state.userInfo = payload;
     },
-    // SET_ROUTES(state, routes) {
-    //   state.routes = routes;
-    // },
+    RESET_USER_STATE(state) {
+      state.userInfo = {};
+      resetRouter();
+    },
   },
   actions: {
     async goLogin({ commit, dispatch }, { loginForm, router }) {
@@ -30,8 +31,6 @@ export default {
       }
     },
     setAddRouter({ commit }, { resultRouter, router }) {
-      console.log("1111");
-      const { authRouterList } = getAuthRouterFn(resultRouter);
       // 获取home路由
       const homeRoute = router.options.routes.find(
         (route) => route.name === "home"
@@ -41,6 +40,13 @@ export default {
         if (!homeRoute.children) {
           homeRoute.children = [];
         }
+        // 过滤掉动态添加的路由,保留初始状态的路由
+        const originalChildren = homeRoute.children.filter(
+          (route) => route.meta && !route.meta.dynamic
+        );
+        // 清空原有的动态子路由
+        homeRoute.children = originalChildren;
+        const { authRouterList } = getAuthRouterFn(resultRouter);
         authRouterList.forEach((item) => {
           // 动态路由的父路径设置为home
           homeRoute.children.push(item);
@@ -55,12 +61,14 @@ export default {
         component: () => import("@/views/error/404.vue"),
         meta: { hidden: true },
       });
-      console.log("router", router.getRoutes());
-      // 持久化存储动态路由
-      // commit("SET_ROUTES", homeRoute.children);
-      // localStorage.setItem("authRoutes", JSON.stringify(homeRoute.children));
       // 确保导航到动态添加的路由
-      router.push("/home/system/userMag");
+      router.push("/home");
+    },
+    logout({ commit }) {
+      // 重置 Vuex 状态
+      commit("RESET_USER_STATE");
+      // 重置路由
+      resetRouter();
     },
   },
 };

+ 11 - 13
src/styles/base.css

@@ -45,8 +45,8 @@ td {
   margin: 0;
   padding: 0;
   border: 0;
-  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
-    "微软雅黑", Arial, sans-serif;
+  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
+    "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
 }
 
 header,
@@ -130,9 +130,7 @@ small {
 }
 
 input:-webkit-autofill {
-
   -webkit-box-shadow: 0 0 0 1000px white inset;
-
 }
 
 sub,
@@ -225,8 +223,9 @@ body {
   background: #ffffff;
   font-size: 22px;
   color: #333;
-  font-family: "HYQiHei", "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB",
-    "Heiti SC", "MicrosoftYaHei", "WenQuanYi Micro Hei", sans-serif;
+  font-family: "HYQiHei", "Helvetica Neue", Helvetica, Arial, "PingFang SC",
+    "Hiragino Sans GB", "Heiti SC", "MicrosoftYaHei", "WenQuanYi Micro Hei",
+    sans-serif;
 }
 
 .maxWidth {
@@ -255,7 +254,8 @@ body {
   margin: 20px;
   padding: 20px;
   background: #ffffff;
-  height: 89vh;
+  min-height: 89vh;
+  /* height: 89vh; */
 }
 
 /* 列表点击 */
@@ -276,7 +276,6 @@ body {
   margin-bottom: 20px;
 }
 
-
 .centeredH3 {
   text-align: center;
   font-size: 26px;
@@ -284,16 +283,15 @@ body {
   margin-bottom: 20px;
 }
 
-.el-date-editor .el-range-separator{
+.el-date-editor .el-range-separator {
   padding: 0;
 }
 
-
-.el-form-item--small.el-form-item{
+.el-form-item--small.el-form-item {
   margin-bottom: 0px;
   margin-top: 4px;
 }
 
-.el-dialog__body{
+.el-dialog__body {
   padding-top: 15px;
-}
+}

+ 7 - 3
src/styles/index.scss

@@ -1,7 +1,7 @@
 // @import 'minireset.css/minireset.sass';
-@import './element-ui.scss';
-@import './tailwind.css';
-@import './base.css';
+@import "./element-ui.scss";
+@import "./tailwind.css";
+@import "./base.css";
 
 body {
   background-color: #eef1f3;
@@ -11,3 +11,7 @@ img,
 svg {
   display: inline;
 }
+.views .dialog-footer {
+  display: flex !important;
+  justify-content: end !important;
+}

+ 54 - 0
src/utils/getMenu.js

@@ -0,0 +1,54 @@
+/*
+ * @Author: your name
+ * @Date: 2024-05-21 14:21:20
+ * @LastEditTime: 2024-05-21 17:36:17
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/utils/getMenu.js
+ */
+export const checkListFn = (data) => {
+  let list = [];
+  recursiveFind(data);
+  function recursiveFind(data) {
+    data.forEach((item) => {
+      //   if (item.permissionType === 1 && item.checked === 1) {
+      if (item.checked === 1) {
+        list.push(item.permissionId);
+      }
+      if (item.children && item.children.length > 0) {
+        recursiveFind(item.children); // 递归遍历子节点
+      }
+    });
+  }
+  return list;
+};
+
+// data 是一个树形数组结构数据,checkIdList是一个一维数组
+// 需求:递归循环data,data.permissionId在checkIdList这个数组中,父级节点和祖先节点的permissionId也需要push到新的一维数组,这个方法如何改?
+export const getcheckListFn = (checkIdList, data) => {
+  let list = [];
+  console.log(checkIdList, "checkIdList");
+  function recursiveFind(node, ancestors = []) {
+    if (checkIdList.includes(node.permissionId)) {
+      // 将当前节点的 permissionId 加入到列表中
+      list.push(node.permissionId);
+
+      // 将当前节点的祖先节点的 permissionId 加入到列表中
+      ancestors.forEach((ancestor) => {
+        list.push(ancestor.permissionId);
+      });
+    }
+    // 递归遍历子节点
+    if (node.children && node.children.length > 0) {
+      node.children.forEach((child) => {
+        recursiveFind(child, [...ancestors, node]);
+      });
+    }
+  }
+  // 从根节点开始递归遍历
+  data.forEach((root) => {
+    recursiveFind(root);
+  });
+
+  return list;
+};

+ 54 - 22
src/utils/request.js

@@ -1,17 +1,27 @@
 import axios from "axios";
 import { Message } from "element-ui";
-console.log(window?._BASE_CONFIG?.API, "window?._BASE_CONFIG?.API");
+
 const service = axios.create({
   baseURL: window?._BASE_CONFIG?.API || "/api",
   withCredentials: true,
+  timeout: 5000,
 });
 
+const writeList = ["/api/energy-manage-service/sysuserinfo/open/userLogin"];
+
 /**
  * 请求拦截器
  * 统一处理请求拦截,如:添加token等
  */
 service.interceptors.request.use(
   (config) => {
+    if (!writeList.includes(config.url)) {
+      const token = JSON.parse(sessionStorage.getItem("vuex"))?.auth?.userInfo
+        ?.token;
+      if (token) {
+        config.headers.token = token;
+      }
+    }
     return config;
   },
   (error) => {
@@ -28,7 +38,6 @@ service.interceptors.response.use(
   async (response) => {
     const { data } = response;
     if (data?.code) {
-      console.log(data?.code, "data?.code");
       if (data.code !== 200) {
         Message({
           message: data.msg || "Error",
@@ -43,8 +52,6 @@ service.interceptors.response.use(
       return response;
     } else if (data.type === "application/json") {
       const resData = JSON.parse(await data.text());
-      console.log(resData);
-      // 根据后端返回code码进行处理
       if (resData.code !== 200) {
         Message({
           message: resData.msg || "Error",
@@ -59,29 +66,54 @@ service.interceptors.response.use(
   },
   (error) => {
     const { response } = error;
-    if (response?.status === 401) {
-      window.location = response.data;
-      return;
+    if (response) {
+      if (response.status === 401) {
+        window.location = response.data;
+      } else {
+        Message({
+          message: response.data.message || error.message,
+          type: "error",
+          duration: 5 * 1000,
+        });
+      }
+    } else {
+      Message({
+        message: error.message,
+        type: "error",
+        duration: 5 * 1000,
+      });
     }
-    Message({
-      message: error.message,
-      type: "error",
-      duration: 5 * 1000,
-    });
     return Promise.reject(error);
   }
 );
 
-const request = (requestObj) => {
-  const { url, method, data = {}, timeout, params, responseType } = requestObj;
-  return service({
-    url,
-    method: method || "post",
-    data,
-    timeout: timeout || 300000,
-    params: params || (method && method.toLowerCase() === "get" ? data : {}),
-    responseType: responseType || "json",
-  });
+/**
+ * 统一处理请求
+ * @param {Object} requestObj 请求参数
+ */
+const request = async (requestObj) => {
+  try {
+    const {
+      url,
+      method,
+      data = {},
+      timeout,
+      params,
+      responseType,
+    } = requestObj;
+    const response = await service({
+      url,
+      method: method || "post",
+      data,
+      timeout: timeout || 300000,
+      params: params || (method && method.toLowerCase() === "get" ? data : {}),
+      responseType: responseType || "json",
+    });
+    return response;
+  } catch (error) {
+    // console.error("Request error:", error);
+    throw error;
+  }
 };
 
 export default request;

+ 4 - 4
src/views/admin/cockpitManage/electronicMap.vue

@@ -8,14 +8,14 @@
 
 <script>
 export default {
-  name: 'PerformanceTestIndex',
+  name: "PerformanceTestIndex",
 
   data() {
-    return {}
+    return {};
   },
 
   mounted() { },
 
-  methods: {}
-}
+  methods: {},
+};
 </script>

+ 345 - 294
src/views/ledger/anemometer.vue

@@ -1,335 +1,386 @@
 <template>
-    <div class="global-variable">
+  <div class="global-variable">
+    <div class="condition">
+      <el-form :inline="true" :model="formInline" class="demo-form-inline">
+        <el-form-item label="测风塔名称:">
+          <el-input
+            v-model="formInline.user"
+            placeholder="请输入批次编号"
+            size="small"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="选择日期:" size="small">
+          <el-date-picker
+            v-model="formInline.timeQuantum"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit" size="small"
+            >查询</el-button
+          >
+          <el-button @click="reset" size="small">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list-page">
+      <div class="newly">
+        <el-button type="primary" @click="newnuedialog" size="small"
+          >新增</el-button
+        >
+      </div>
+
+      <el-table
+        class="center-align-table"
+        :data="tableData"
+        border
+        :cell-style="rowStyle"
+      >
+        <el-table-column align="center" fixed prop="" label="测风塔名称">
+          <template slot-scope="scope">
+            <el-button @click="particulars(scope.row)" type="text" size="small"
+              >泗洪风场</el-button
+            >
+          </template>
+        </el-table-column>
+
+        <el-table-column align="center" label="测风塔编号"> </el-table-column>
+
+        <el-table-column prop="" align="center" label="机型类型">
+        </el-table-column>
+        <el-table-column prop="" align="center" label="经度" width="100">
+        </el-table-column>
+
+        <el-table-column prop="" align="center" label="纬度" width="100">
+        </el-table-column>
+        <el-table-column prop="" align="center" label="状态" width="100">
+        </el-table-column>
+        <el-table-column prop="" align="center" label="创建时间">
+        </el-table-column>
+        <el-table-column
+          prop="transition"
+          align="center"
+          fixed="right"
+          label="操作"
+          width="200"
+        >
+          <template slot-scope="scope">
+            <el-button @click="compile(scope.row)" type="text" size="small"
+              >编辑</el-button
+            >
+
+            <el-button
+              v-if="scope.row.transition == 1"
+              @click="start(scope.row)"
+              type="text"
+              size="small"
+              >启用</el-button
+            >
+            <el-button
+              v-else
+              style="color: #666"
+              @click="stop(scope.row)"
+              type="text"
+              size="small"
+              >停用</el-button
+            >
+            <el-button
+              style="color: #f00"
+              @click="deleted(scope.row)"
+              type="text"
+              size="small"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-container">
+        <el-pagination
+          :page-size="10"
+          :pager-count="11"
+          layout="total, prev, pager, next"
+          :total="35"
+        >
+        </el-pagination>
+      </div>
+    </div>
+
+    <!-- 弹出层 -->
+
+    <!-- 新增 -->
+    <el-dialog :title="title" :visible.sync="nuedialog" width="800px">
+      <div class="addition">
+        <span @click="addition">
+          <SvgIcon
+            name="jia"
+            class="jia"
+            width="20px"
+            height="22px"
+            color="#222"
+          ></SvgIcon>
+        </span>
+        <span @click="subtraction">
+          <SvgIcon
+            name="jian"
+            class="jian"
+            width="20px"
+            height="22px"
+            color="#222"
+          ></SvgIcon>
+        </span>
+      </div>
+      <div class="general">
         <div class="condition">
-            <el-form :inline="true" :model="formInline" class="demo-form-inline">
-                <el-form-item label="测风塔名称:">
-                    <el-input v-model="formInline.user" placeholder="请输入批次编号" size="small"></el-input>
-                </el-form-item>
-                <el-form-item label="选择日期:" size="small">
-                    <el-date-picker v-model="formInline.timeQuantum" type="daterange" range-separator="至"
-                        start-placeholder="开始日期" end-placeholder="结束日期">
-                    </el-date-picker>
-                </el-form-item>
-                <el-form-item>
-                    <el-button type="primary" @click="onSubmit" size="small">查询</el-button>
-                    <el-button @click="reset" size="small">重置</el-button>
-                </el-form-item>
-            </el-form>
+          <p>测风塔名称:</p>
+          <el-input v-model="windsiteName"></el-input>
         </div>
-        <div class="list-page">
-            <div class="newly">
-
-                <el-button type="primary" @click="newnuedialog" size="small">新增</el-button>
-            </div>
-
-            <el-table class="center-align-table" :data="tableData" border :cell-style="rowStyle">
-                <el-table-column align="center" fixed prop="" label="测风塔名称">
-                    <template slot-scope="scope">
-                        <el-button @click="particulars(scope.row)" type="text" size="small">泗洪风场</el-button>
-                    </template>
-                </el-table-column>
-
-                <el-table-column align="center" label="测风塔编号"> </el-table-column>
-
-                <el-table-column prop="" align="center" label="经度" width="100">
-                </el-table-column>
-
-                <el-table-column prop="" align="center" label="纬度" width="100">
-                </el-table-column>
-                <el-table-column prop="" align="center" label="状态" width="100">
-                </el-table-column>
-                <el-table-column prop="" align="center" label="创建时间">
-                </el-table-column>
-                <el-table-column prop="transition" align="center" fixed="right" label="操作" width="200">
-                    <template slot-scope="scope">
-                        <el-button @click="compile(scope.row)" type="text" size="small">编辑</el-button>
-
-                        <el-button v-if="scope.row.transition == 1" @click="start(scope.row)" type="text"
-                            size="small">启用</el-button>
-                        <el-button v-else style="color: #666" @click="stop(scope.row)" type="text"
-                            size="small">停用</el-button>
-                        <el-button style="color: #f00" @click="deleted(scope.row)" type="text"
-                            size="small">删除</el-button>
-                    </template>
-                </el-table-column>
-            </el-table>
-            <div class="pagination-container">
-                <el-pagination :page-size="10" :pager-count="11" layout="total, prev, pager, next" :total="35">
-                </el-pagination>
-            </div>
+        <div class="condition">
+          <p>经度:</p>
+          <el-input v-model="airdensity"></el-input>
         </div>
 
-        <!-- 弹出层 -->
-
-        <!-- 新增 -->
-        <el-dialog :title="title" :visible.sync="nuedialog" width="800px">
-            <div class="addition ">
-                <span @click="addition">
-                    <SvgIcon name="jia" class="jia" width="20px" height="22px" color="#222"></SvgIcon>
-                </span>
-                <span @click="subtraction">
-                    <SvgIcon name="jian" class="jian" width="20px" height="22px" color="#222"></SvgIcon>
-                </span>
-            </div>
-            <div class="general">
-
-                <div class="condition">
-                    <p>测风塔名称:</p>
-                    <el-input v-model="windsiteName"></el-input>
-                </div>
-                <div class="condition">
-                    <p>经度:</p>
-                    <el-input v-model="airdensity"></el-input>
-                </div>
-
-
-                <div class="condition">
-                    <p>纬度:</p>
-                    <el-input v-model="altitude"></el-input>
-                </div>
-
-
-                <div v-for="(input, index) in heightInputs" :key="index" class="condition">
-                    <p>测风塔高度:</p>
-                    <el-input v-model="input.value" placeholder="请输入测风塔高度"></el-input>
-                </div>
-
-
-            </div>
-
-            <span slot="footer" class="dialog-footer">
-                <el-button @click="nuedialog = false" size="small">取 消</el-button>
-                <el-button type="primary" @click="newly" size="small">确 定</el-button>
-            </span>
-        </el-dialog>
-
-        <!-- 风场详情 -->
-        <el-dialog title="详情" :visible.sync="unusualdialog" width="800px">
-
-        </el-dialog>
-
-
-
+        <div class="condition">
+          <p>纬度:</p>
+          <el-input v-model="altitude"></el-input>
+        </div>
 
-    </div>
+        <div
+          v-for="(input, index) in heightInputs"
+          :key="index"
+          class="condition"
+        >
+          <p>测风塔高度:</p>
+          <el-input
+            v-model="input.value"
+            placeholder="请输入测风塔高度"
+          ></el-input>
+        </div>
+      </div>
+
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="nuedialog = false" size="small">取 消</el-button>
+        <el-button type="primary" @click="newly" size="small">确 定</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 风场详情 -->
+    <el-dialog title="详情" :visible.sync="unusualdialog" width="800px">
+    </el-dialog>
+  </div>
 </template>
 
 <script>
 export default {
-    data() {
-        return {
-            // 新增信息
-            windsiteName: "",
-            airdensity: "",
-            superior: "",
-            superiorOptions: [],
-            altitude: "",
-            sheng: "",
-            shengOptions: [],
-            shi: "",
-            shiOptions: [],
-            longitude: "",
-            dimensionality: "",
-            anemometer: "",
-            anemometerOptions: [],
-
-            fileList: [
-                {
-                    name: "food.jpeg",
-                    url: "https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100",
-                },
-
-            ],
-            formInline: {
-                user: "",
-                region: "",
-                timeQuantum: "",
-            },
-            tableData: [
-                {
-                    id: 1,
-                    name: "王小虎",
-                    transition: "1",
-                },
-                {
-                    id: 3,
-                    name: "王小虎",
-                    abnormal: "1",
-                    transition: "0",
-                    children: [
-                        {
-                            id: 31,
-
-                            name: "王小虎",
-
-                            abnormal: "1",
-                        },
-                    ],
-                },
-            ],
-            nuedialog: false,
-            unusualdialog: false,
-
-
-
-
-            newform: {
-                unit: "",
-                province: "",
-                city: "",
-                descr: "",
-            },
-            title: "",
-            heightInputs: [{ value: '' }],
-        };
-    },
-    methods: {
-        rowStyle() {
-            return "text-align:center";
+  data() {
+    return {
+      // 新增信息
+      windsiteName: "",
+      airdensity: "",
+      superior: "",
+      superiorOptions: [],
+      altitude: "",
+      sheng: "",
+      shengOptions: [],
+      shi: "",
+      shiOptions: [],
+      longitude: "",
+      dimensionality: "",
+      anemometer: "",
+      anemometerOptions: [],
+
+      fileList: [
+        {
+          name: "food.jpeg",
+          url: "https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100",
         },
-
-        // 查询
-        onSubmit() {
-            console.log("submit!");
+      ],
+      formInline: {
+        user: "",
+        region: "",
+        timeQuantum: "",
+      },
+      tableData: [
+        {
+          id: 1,
+          name: "王小虎",
+          transition: "1",
         },
-        // 重置
-        reset() { },
-
-        // 新增
-        newly() {
-
-            this.heightInputs.forEach((value, index) => {
-                console.log(`测风塔高度 ${index + 1}:`, value);
-            });
-
-            this.nuedialog = false;
-            this.heightInputs = [{ value: '' }];
+        {
+          id: 3,
+          name: "王小虎",
+          abnormal: "1",
+          transition: "0",
+          children: [
+            {
+              id: 31,
+
+              name: "王小虎",
+
+              abnormal: "1",
+            },
+          ],
         },
+      ],
+      nuedialog: false,
+      unusualdialog: false,
+
+      newform: {
+        unit: "",
+        province: "",
+        city: "",
+        descr: "",
+      },
+      title: "",
+      heightInputs: [{ value: "" }],
+    };
+  },
+  methods: {
+    rowStyle() {
+      return "text-align:center";
+    },
 
-        //异常详情
-        particulars(row) {
-            this.unusualdialog = true;
-        },
+    // 查询
+    onSubmit() {
+      console.log("submit!");
+    },
+    // 重置
+    reset() {},
 
+    // 新增
+    newly() {
+      this.heightInputs.forEach((value, index) => {
+        console.log(`测风塔高度 ${index + 1}:`, value);
+      });
 
-        // 编辑
-        compile(row) {
-            this.nuedialog = true;
-            this.title = "编辑";
-        },
+      this.nuedialog = false;
+      this.heightInputs = [{ value: "" }];
+    },
 
+    //异常详情
+    particulars(row) {
+      this.unusualdialog = true;
+    },
 
-        // 启用
-        start(row) { },
-        // 停用
-        stop(row) { },
-        // 删除
-        deleted(row) {
-            this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
-                confirmButtonText: "确定",
-                cancelButtonText: "取消",
-                type: "warning",
-            })
-                .then(() => {
-                    this.$message({
-                        type: "success",
-                        message: "删除成功!",
-                    });
-                })
-                .catch(() => {
-                    this.$message({
-                        type: "info",
-                        message: "已取消删除",
-                    });
-                });
-        },
-        // 删除附件
-        deleteRow(row) {
-            this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
-                confirmButtonText: "确定",
-                cancelButtonText: "取消",
-                type: "warning",
-            })
-                .then(() => {
-                    this.$message({
-                        type: "success",
-                        message: "删除成功!",
-                    });
-                })
-                .catch(() => {
-                    this.$message({
-                        type: "info",
-                        message: "已取消删除",
-                    });
-                });
-        },
-        addition() {
-            this.heightInputs.push({ value: '' }); // Add a new object with an empty string property
-        },
+    // 编辑
+    compile(row) {
+      this.nuedialog = true;
+      this.title = "编辑";
+    },
 
-        // Method to remove the last input for "测风塔高度"
-        subtraction() {
-            if (this.heightInputs.length > 1) { // Ensure at least one input remains
-                this.heightInputs.pop();
-            }
-        },
+    // 启用
+    start(row) {},
+    // 停用
+    stop(row) {},
+    // 删除
+    deleted(row) {
+      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.$message({
+            type: "success",
+            message: "删除成功!",
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+    // 删除附件
+    deleteRow(row) {
+      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.$message({
+            type: "success",
+            message: "删除成功!",
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+    addition() {
+      this.heightInputs.push({ value: "" }); // Add a new object with an empty string property
+    },
 
-        // 新增
-        newnuedialog() {
-            this.nuedialog = true;
-            this.title = "新增";
-        },
+    // Method to remove the last input for "测风塔高度"
+    subtraction() {
+      if (this.heightInputs.length > 1) {
+        // Ensure at least one input remains
+        this.heightInputs.pop();
+      }
     },
+
+    // 新增
+    newnuedialog() {
+      this.nuedialog = true;
+      this.title = "新增";
+    },
+  },
 };
 </script>
 
 <style lang="scss" scoped>
 .general {
-    display: flex;
-    flex-wrap: wrap;
+  display: flex;
+  flex-wrap: wrap;
 
-    .condition {
-        width: 50%;
-        display: flex;
+  .condition {
+    width: 50%;
+    display: flex;
 
-        p {
-            width: 100px;
-            text-align: right;
-            line-height: 40px;
-        }
+    p {
+      width: 100px;
+      text-align: right;
+      line-height: 40px;
+    }
 
-        span {
-            line-height: 40px;
+    span {
+      line-height: 40px;
 
-            padding-left: 20px;
-        }
+      padding-left: 20px;
+    }
 
-        .el-select {
-            width: 100%;
-            margin-bottom: 20px;
-        }
+    .el-select {
+      width: 100%;
+      margin-bottom: 20px;
+    }
 
-        .el-input {
-            margin-bottom: 20px;
-        }
+    .el-input {
+      margin-bottom: 20px;
     }
+  }
 }
 
-
-
 .attachment {
-    display: flex;
-    padding-top: 10px;
+  display: flex;
+  padding-top: 10px;
 
-    p {
-        margin-right: 20px;
-        color: #409eff;
-    }
+  p {
+    margin-right: 20px;
+    color: #409eff;
+  }
 }
 
 .addition {
-    display: flex;
-    justify-content: flex-end;
-    margin-bottom: 10px;
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 10px;
 }
-</style>
+</style>

+ 2 - 1
src/views/login/Index.vue

@@ -43,6 +43,7 @@
 </template>
 
 <script>
+import { resetRouter } from "@/router/index.js";
 export default {
   data() {
     var validatePass = (rule, value, callback) => {
@@ -210,7 +211,7 @@ export default {
   }
 }
 
-.el-input{
+.el-input {
   width: 300px;
   margin-top: 20px;
 }

+ 229 - 0
src/views/system/menuMag/components/editDialog.vue

@@ -0,0 +1,229 @@
+<template>
+  <div>
+    <el-form
+      :model="menuForm"
+      :rules="addMenuRules"
+      ref="addUserForm"
+      label-width="100px"
+      class="demo-ruleForm"
+    >
+      <el-form-item label="上级目录:" prop="parentId" v-if="activeName !== '1'">
+        <treeselect
+          :normalizer="normalizer"
+          :noChildrenText="'没有子选项'"
+          :noOptionsText="'没有可选项'"
+          :noResultsText="'没有匹配的结果'"
+          :placeholder="'请选择'"
+          :searchable="true"
+          v-model="menuForm.parentId"
+          placeholder="请选择"
+          :options="menuOptions"
+        ></treeselect>
+      </el-form-item>
+      <el-form-item label="菜单名称:" prop="pname">
+        <el-input
+          v-model="menuForm.pname"
+          placeholder="请输入菜单名称"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="菜单标识:" prop="pcode">
+        <el-input
+          v-model="menuForm.pcode"
+          placeholder="请输入菜单标识"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="路由地址:" prop="purl" v-if="activeName !== '1'">
+        <el-input
+          v-model="menuForm.purl"
+          placeholder="请输入路由地址"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="是否显示:" prop="permissionShow">
+        <el-select
+          v-model="menuForm.permissionShow"
+          placeholder="请选择状态"
+          style="width: 100%"
+        >
+          <el-option label="显示" :value="1"></el-option>
+          <el-option label="不显示" :value="2"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="状态:" prop="pstat">
+        <el-select
+          v-model="menuForm.pstat"
+          placeholder="请选择状态"
+          style="width: 100%"
+        >
+          <el-option label="启用" :value="1"></el-option>
+          <el-option label="停用" :value="0"></el-option>
+        </el-select>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import Treeselect from "@riophae/vue-treeselect";
+import { addMenuFn, updateMenuFn } from "@/api/system";
+
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  components: {
+    Treeselect,
+  },
+  props: {
+    activeName: {
+      type: String,
+    },
+    tableData: {
+      type: Array,
+    },
+    checkId: {
+      type: Number,
+    },
+    title: {
+      type: String,
+    },
+    row: {
+      type: Object,
+    },
+  },
+  data() {
+    return {
+      menuForm: {
+        parentId: null,
+        pname: null,
+        purl: null,
+        pstat: null,
+        pcode: null,
+        permissionShow: null,
+      },
+      addMenuRules: {
+        permissionShow: {
+          required: true,
+          message: "请选择",
+          trigger: "change",
+        },
+        pcode: [
+          { required: true, message: "请填写菜单菜单标识", trigger: "blur" },
+        ],
+        pname: [{ required: true, message: "请填写菜单名称", trigger: "blur" }],
+        purl: [{ required: true, message: "请填写路由地址", trigger: "blur" }],
+        parentId: [
+          { required: true, message: "请选择上级目录", trigger: "change" },
+        ],
+        pstat: [{ required: true, message: "请选择状态", trigger: "change" }],
+      },
+      stateOPtions: [],
+      menuOptions: [
+        { permissionId: 0, permissionName: "主类目", children: [] },
+      ],
+    };
+  },
+  created() {
+    this.menuOptions[0].children.push(...this.tableData);
+    if (this.title === "编辑" && this.activeName === "2") {
+      this.menuForm = {
+        parentId: this.row.parentId,
+        pname: this.row.permissionName,
+        purl: this.row.permissionUrl,
+        pstat: this.row.permissionState,
+        pcode: this.row.permissionCode,
+        permissionShow: this.row.permissionShow,
+      };
+    } else if (this.title === "新增" && this.activeName === "2") {
+      this.menuForm.parentId = this.row.permissionId;
+    }
+  },
+  watch: {
+    checkId(newVale, oldVal) {
+      if (newVale) {
+        console.log(newVale, "newVale");
+        if (this.title === "编辑" && this.activeName === "2") {
+          this.menuForm = {
+            parentId: this.row.parentId,
+            pname: this.row.permissionName,
+            purl: this.row.permissionUrl,
+            pstat: this.row.permissionState,
+            pcode: this.row.permissionCode,
+            permissionShow: this.row.permissionShow,
+          };
+        } else if (this.title === "新增" && this.activeName === "2") {
+          this.menuForm.parentId = this.row.permissionId;
+        }
+      }
+    },
+  },
+  methods: {
+    /** 转换菜单数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.permissionId,
+        label: node.permissionName,
+        children: node.children,
+      };
+    },
+    submit() {
+      const that = this;
+      this.$refs["addUserForm"].validate((valid) => {
+        if (valid) {
+          if (this.title === "编辑") {
+            updateMenuFn({
+              ...this.menuForm,
+              permissionId: this.row.permissionId,
+            })
+              .then((res) => {
+                this.$message({
+                  type: "success",
+                  message: "编辑成功",
+                });
+                this.cancel();
+                that.$emit("updateList");
+              })
+              .catch((error) => {
+                this.$message({
+                  type: "error",
+                  message: "编辑失败",
+                });
+              });
+          } else if (this.title === "新增") {
+            addMenuFn({
+              ...this.menuForm,
+              purl:
+                this.menuForm.purl !== null ? this.menuForm.purl : undefined,
+              ptype: "1",
+              parentId:
+                this.activeName === "1" ? undefined : this.menuForm.parentId,
+            })
+              .then((res) => {
+                this.$message({
+                  type: "success",
+                  message: "新增成功",
+                });
+                this.cancel();
+                that.$emit("updateList");
+              })
+              .catch((error) => {
+                this.$message({
+                  type: "error",
+                  message: "新增失败",
+                });
+              });
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    cancel() {
+      this.$refs["addUserForm"].resetFields();
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss"></style>

+ 328 - 74
src/views/system/menuMag/index.vue

@@ -1,93 +1,347 @@
-<!--
- * @Author: your name
- * @Date: 2024-05-17 15:59:21
- * @LastEditTime: 2024-05-19 22:59:39
- * @LastEditors: bogon
- * @Description: In User Settings Edit
- * @FilePath: /dasheng/performance-test/src/views/system/menuMag/index.vue
--->
 <template>
-  <div>
-    <el-table :data="tableData" style="width: 100%">
-      <el-table-column label="日期" width="180">
-        <template slot-scope="scope">
-          <i class="el-icon-time"></i>
-          <span style="margin-left: 10px">{{ scope.row.date }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="姓名" width="180">
-        <template slot-scope="scope">
-          <el-popover trigger="hover" placement="top">
-            <p>姓名: {{ scope.row.name }}</p>
-            <p>住址: {{ scope.row.address }}</p>
-            <div slot="reference" class="name-wrapper">
-              <el-tag size="medium">{{ scope.row.name }}</el-tag>
-            </div>
-          </el-popover>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作">
-        <template slot-scope="scope">
-          <el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
-            >编辑</el-button
+  <div class="global-variable">
+    <div class="condition">
+      <el-form
+        :inline="true"
+        :model="formInline"
+        class="demo-form-inline"
+        ref="ruleForm"
+        :rules="rules"
+      >
+        <el-form-item label="菜单名称:" prop="permissionName">
+          <el-input
+            v-model="formInline.permissionName"
+            placeholder="请输入菜单名称"
+            size="small"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="状态:" prop="permissionState">
+          <el-select
+            v-model="formInline.permissionState"
+            placeholder="选择状态"
+            size="small "
           >
+            <el-option label="启用" value="1"></el-option>
+            <el-option label="停用" value="0"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit" size="small"
+            >查询</el-button
+          >
+          <el-button @click="reset('ruleForm')" size="small">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list-page">
+      <div class="newly">
+        <el-button type="primary" @click="newnuedialog" size="small"
+          >新增</el-button
+        >
+        <el-button type="primary" @click="toggleExpandAll" size="small">{{
+          defaultExpandAll ? "收起" : "展开"
+        }}</el-button>
+      </div>
+      <el-table
+        v-loading="loading"
+        class="center-align-table"
+        :data="tableData"
+        border
+        stripe
+        row-key="permissionId"
+        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+        ref="table"
+      >
+        <el-table-column prop="permissionName" label="菜单名称">
+        </el-table-column>
+        <el-table-column
+          prop="permissionType"
+          label="类型"
+          width="100"
+          align="center"
+        >
+          <template slot-scope="scope">
+            <span>{{ scope.row.permissionType == 1 ? "菜单" : "功能" }}</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          prop="permissionSort"
+          label="排序"
+          width="80"
+          align="center"
+        >
+        </el-table-column>
+
+        <el-table-column prop="permissionCode" label="权限标识" align="center">
+        </el-table-column>
+        <el-table-column prop="permissionUrl" label="路径" align="center">
+        </el-table-column>
+        <el-table-column
+          prop="permissionState"
+          label="状态"
+          align="center"
+          width="80"
+        >
+          <template slot-scope="scope">
+            <span>{{ scope.row.permissionState === 1 ? "启用" : "停用" }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column fixed="right" label="操作" align="center">
+          <template slot-scope="scope">
+            <el-button @click="compile(scope.row)" type="text" size="small"
+              >编辑</el-button
+            >
+            <el-button @click="newcomer(scope.row)" type="text" size="small"
+              >新增</el-button
+            >
+            <el-button
+              v-if="scope.row.permissionState === 0"
+              @click="updateState(scope.row, 1)"
+              type="text"
+              size="small"
+              >启用</el-button
+            >
+            <el-button
+              v-else
+              style="color: #666"
+              @click="updateState(scope.row, 0)"
+              type="text"
+              size="small"
+              >停用</el-button
+            >
+            <el-button
+              style="color: #f00"
+              @click="deleted(scope.row)"
+              type="text"
+              size="small"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 新增编辑弹出层 -->
+    <el-dialog :title="title" :visible.sync="unusualdialog" width="500px">
+      <div v-loading="loadingView" class="views">
+        <el-tabs type="border-card" class="tabs" v-model="activeName">
+          <el-tab-pane label="目录" name="1"
+            ><EditMenu
+              ref="addList"
+              :activeName="activeName"
+              :tableData="tableData"
+              :checkId="checkId"
+              :title="title"
+              @updateList="updateList"
+            />
+          </el-tab-pane>
+          <el-tab-pane label="菜单" name="2"
+            ><EditMenu
+              ref="addMenu"
+              :activeName="activeName"
+              :tableData="tableData"
+              :checkId="checkId"
+              :title="title"
+              @updateList="updateList"
+              :row="row"
+          /></el-tab-pane>
+        </el-tabs>
+        <span slot="footer" class="dialog-footer">
           <el-button
-            size="mini"
-            type="danger"
-            @click="handleDelete(scope.$index, scope.row)"
-            >删除</el-button
+            @click="
+              () => {
+                this.$refs.addMenu.cancel();
+                this.loadingView = false;
+                this.unusualdialog = false;
+                this.checkId = '';
+              }
+            "
+            size="small"
+            >取 消</el-button
+          >
+          <el-button type="primary" @click="editAuthMenu" size="small"
+            >确 定</el-button
           >
-        </template>
-      </el-table-column>
-    </el-table>
+        </span>
+      </div>
+    </el-dialog>
   </div>
 </template>
+
 <script>
+import {
+  addMenuFn,
+  deleteMenuFn,
+  updateMenuFn,
+  getAllMenu,
+} from "@/api/system";
+import EditMenu from "./components/editDialog.vue";
 export default {
+  components: {
+    EditMenu,
+  },
   data() {
     return {
-      tableData: [
-        {
-          date: "2016-05-02",
-          name: "王小虎",
-          address: "上海市普陀区金沙江路 1518 弄",
-        },
-        {
-          date: "2016-05-04",
-          name: "王小虎",
-          address: "上海市普陀区金沙江路 1517 弄",
-        },
-        {
-          date: "2016-05-01",
-          name: "王小虎",
-          address: "上海市普陀区金沙江路 1519 弄",
-        },
-        {
-          date: "2016-05-03",
-          name: "王小虎",
-          address: "上海市普陀区金沙江路 1516 弄",
-        },
-      ],
+      activeName: "1",
+      title: "",
+      loadingView: false,
+      defaultExpandAll: true,
+      row: {},
+      rules: {
+        roleId: { permissionName: "change" },
+        userName: { permissionState: "blur" },
+      },
+      loading: false,
+      formInline: {
+        permissionName: "",
+        permissionState: "",
+      },
+      tableData: [],
+      unusualdialog: false,
+      checkId: "",
     };
   },
+  created() {
+    this.getTableList();
+  },
+  watch: {
+    tableData: {
+      handler(newData) {
+        this.$nextTick(() => {
+          this.setExpandAll(this.defaultExpandAll);
+        });
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
   methods: {
-    handleEdit(index, row) {
-      console.log(index, row);
+    toggleExpandAll() {
+      this.defaultExpandAll = !this.defaultExpandAll;
+      this.$nextTick(() => {
+        this.setExpandAll(this.defaultExpandAll);
+      });
+    },
+    setExpandAll(expand) {
+      const table = this.$refs.table;
+      if (table) {
+        this.tableData.forEach((row) => {
+          table.toggleRowExpansion(row, expand);
+          if (row.children) {
+            row.children.forEach((child) => {
+              table.toggleRowExpansion(child, expand);
+            });
+          }
+        });
+      }
+    },
+    async getTableList() {
+      try {
+        this.loading = true;
+        const result = await getAllMenu({ ...this.formInline });
+        this.tableData = result.data;
+        this.loading = false;
+      } catch (error) {
+        this.$message({
+          type: "error",
+          message: "请检查是否连接网络",
+        });
+      }
+    },
+    //弹框确定按钮
+    editAuthMenu() {
+      if (this.activeName === "1") {
+        this.$refs.addList.submit();
+        this.checkId = "";
+        //目录
+      } else {
+        //菜单
+        this.$refs.addMenu.submit();
+        this.checkId = "";
+      }
+    },
+    updateList() {
+      console.log("updateList");
+      this.getTableList();
+      this.unusualdialog = false;
+    },
+    // 查询
+    onSubmit() {
+      this.getTableList();
+    },
+    // 重置
+    reset(formName) {
+      this.$refs[formName].resetFields();
+      this.getTableList();
+    },
+    // 编辑
+    compile(row) {
+      this.unusualdialog = true;
+      this.activeName = "2";
+      this.checkId = row.permissionId;
+      this.row = row;
+      this.title = "编辑";
+    },
+    // 新增子级
+    newcomer(row) {
+      this.unusualdialog = true;
+      this.checkId = row.permissionId;
+      this.activeName = "2";
+      this.title = "新增";
+    },
+    // 启用/停用
+    updateState(row, state) {
+      updateMenuFn({ permissionId: row.permissionId, pstat: state })
+        .then((res) => {
+          this.$message({
+            message: "状态更新成功",
+            type: "success",
+          });
+          this.getTableList();
+        })
+        .catch(() => {});
+    },
+
+    // 删除
+    deleted(row) {
+      this.$confirm("此操作将永久删除该文件,是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          // 执行删除操作
+          deleteMenuFn({ permissionId: row.permissionId })
+            .then(() => {
+              this.$message({
+                type: "success",
+                message: "删除成功!",
+              });
+              this.getTableList();
+            })
+            .catch(() => {});
+        })
+        .catch(() => {
+          // 取消删除
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
     },
-    handleDelete(index, row) {
-      console.log(index, row);
+    //新增菜单目录
+    newnuedialog() {
+      this.unusualdialog = true;
+      this.activeName = "1";
+      this.title = "新增";
     },
   },
 };
 </script>
-<!-- <style lang="scss">
-// .box {
-//   width: 100px;
-//   height: 100px;
-//   background-color: var(--color);
-// }
-.el-table th.el-table__cell {
-  background-color: var(--color);
-  color: aliceblue;
+
+<style lang="scss" scoped>
+.el-select {
+  width: 250px;
 }
-</style> -->
+</style>

+ 81 - 0
src/views/system/roleMag/components/menuTree.vue

@@ -0,0 +1,81 @@
+<template>
+  <div>
+    <el-tree
+      :data="menuList"
+      show-checkbox
+      default-expand-all
+      node-key="permissionId"
+      ref="tree"
+      highlight-current
+      :props="defaultProps"
+    >
+      <!-- :check-strictly="true"? -->
+    </el-tree>
+  </div>
+</template>
+
+<script>
+import { getAllMenu } from "@/api/system.js";
+import { checkListFn, getcheckListFn } from "@/utils/getMenu.js";
+
+export default {
+  props: {
+    treeObj: {
+      type: Object,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      menuList: [],
+      defaultProps: {
+        children: "children",
+        label: "permissionName",
+      },
+    };
+  },
+  watch: {
+    treeObj: {
+      handler(newVal) {
+        this.updateTreeCheckState(newVal.checkList);
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  created() {
+    this.getMenuList();
+  },
+  mounted() {
+    this.updateTreeCheckState(this.treeObj.checkList);
+  },
+  methods: {
+    getCheckedNodes() {
+      console.log(this.$refs.tree.getCheckedNodes());
+    },
+    getMenuList() {
+      getAllMenu().then((res) => {
+        this.menuList = res.data;
+      });
+    },
+    getCheckTreeKey() {
+      const result = getcheckListFn(
+        this.$refs.tree.getCheckedKeys(),
+        this.menuList
+      );
+      console.log(result, "reslut");
+      return {
+        permissionIds: [...new Set(result)].join(","),
+        roleId: this.treeObj.roleId,
+      };
+    },
+    updateTreeCheckState(checkList) {
+      if (this.$refs.tree) {
+        this.$refs.tree.setCheckedKeys(checkListFn(checkList));
+      }
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss"></style>

+ 597 - 11
src/views/system/roleMag/index.vue

@@ -1,13 +1,599 @@
-<!--
- * @Author: your name
- * @Date: 2024-05-17 15:58:57
- * @LastEditTime: 2024-05-17 15:59:09
- * @LastEditors: bogon
- * @Description: In User Settings Edit
- * @FilePath: /dasheng/performance-test/src/views/system/roleMag/index.vue
--->
 <template>
-  <div>角色管理</div>
+  <div class="global-variable">
+    <div class="condition">
+      <el-form
+        :inline="true"
+        ref="ruleForm"
+        :model="formInline"
+        class="demo-form-inline"
+        :rules="rules"
+      >
+        <el-form-item label="角色名称" prop="roleName">
+          <el-input
+            v-model="formInline.roleName"
+            placeholder="请输入角色名称"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="状态:" prop="roleAvailable">
+          <el-select
+            v-model="formInline.roleAvailable"
+            placeholder="请选择状态"
+          >
+            <el-option label="启用" value="1"></el-option>
+            <el-option label="停用" value="0"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit" size="small"
+            >查询</el-button
+          >
+          <el-button @click="reset('ruleForm')" size="small">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list-page">
+      <div class="newly">
+        <el-button type="primary" @click="newnuedialog" size="small"
+          >新增</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        class="center-align-table"
+        :data="tableData"
+        border
+        :cell-style="rowStyle"
+      >
+        <el-table-column
+          align="center"
+          fixed
+          prop="id"
+          label="角色ID"
+          width="100"
+        >
+        </el-table-column>
+
+        <el-table-column align="center" label="角色名称" prop="roleDescription">
+        </el-table-column>
+
+        <el-table-column prop="roleType" align="center" label="角色类型">
+          <template slot-scope="scope">
+            <span v-for="item in stateOPtions" :key="item.contentsValue">
+              {{
+                scope.row.roleType == item.contentsValue
+                  ? item.contentsName
+                  : ""
+              }}</span
+            >
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="source" label="角色来源">
+          <template slot-scope="scope">
+            <span>
+              {{
+                scope.row.source == 0
+                  ? "系统"
+                  : scope.row.source == 1
+                  ? "自定义"
+                  : "/"
+              }}</span
+            >
+          </template>
+        </el-table-column>
+
+        <el-table-column prop="roleCode" align="center" label="角色标识">
+        </el-table-column>
+        <el-table-column
+          prop="roleAvailable"
+          align="center"
+          label="状态"
+          width="100"
+        >
+          <template slot-scope="scope">
+            <span>
+              {{
+                scope.row.roleAvailable == 0
+                  ? "停用"
+                  : scope.row.roleAvailable == 1
+                  ? "启用"
+                  : "/"
+              }}</span
+            >
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" align="center" label="创建时间">
+        </el-table-column>
+        <el-table-column
+          prop="transition"
+          align="center"
+          fixed="right"
+          label="操作"
+          width="200"
+        >
+          <template slot-scope="scope">
+            <el-button @click="compile(scope.row)" type="text" size="small"
+              >编辑</el-button
+            >
+            <el-button
+              style="color: #f90"
+              @click="editAuth(scope.row)"
+              type="text"
+              size="small"
+              >权限设置</el-button
+            >
+            <el-button
+              v-if="scope.row.roleAvailable == 0"
+              @click="setState(1, scope.row.id)"
+              type="text"
+              size="small"
+              >启用</el-button
+            >
+            <el-button
+              v-else
+              style="color: #666"
+              @click="setState(0, scope.row.id)"
+              type="text"
+              size="small"
+              >停用</el-button
+            >
+
+            <el-button
+              style="color: #f00"
+              @click="deleted(scope.row)"
+              type="text"
+              size="small"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-container">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page.sync="formInline.pageNum"
+          layout="total, prev, pager, next"
+          :page-size="formInline.pageSize"
+          :total="formInline.totalSize"
+        >
+        </el-pagination>
+      </div>
+    </div>
+
+    <!-- 弹出层 -->
+    <!-- 新增 /编辑-->
+    <el-dialog :title="title" :visible.sync="nuedialog" width="500px">
+      <div v-loading="loadingView" class="views">
+        <el-form
+          :model="ruleForm"
+          :rules="addUserRules"
+          ref="addUserForm"
+          label-width="100px"
+          class="demo-ruleForm"
+        >
+          <el-form-item label="角色名称" prop="roleName">
+            <el-input
+              v-model="ruleForm.roleName"
+              placeholder="请输入角色名称"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="角色标识" prop="roleCode">
+            <el-input
+              v-model="ruleForm.roleCode"
+              placeholder="请输入角色标识"
+            ></el-input>
+          </el-form-item>
+
+          <el-form-item label="角色类型:" prop="roleType">
+            <el-select
+              v-model="ruleForm.roleType"
+              placeholder="请选择角色类型"
+              style="width: 100%"
+            >
+              <el-option
+                :label="item.contentsName"
+                v-for="item in stateOPtions"
+                :value="item.contentsValue"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </el-form>
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="cancel('addUserForm')" size="small"
+            >取 消</el-button
+          >
+          <el-button
+            type="primary"
+            @click="submitForm('addUserForm')"
+            size="small"
+            >确 定</el-button
+          >
+        </span>
+      </div>
+    </el-dialog>
+    <!-- 权限设置 -->
+    <el-dialog title="权限设置" :visible.sync="unusualdialog" width="500px">
+      <div v-loading="loadingView" class="views">
+        <el-form :model="editRoleAuth" ref="editRoleAuth" label-width="100px">
+          <el-form-item
+            label="角色名称"
+            prop="roleName"
+            :rules="[{ required: true, message: '角色名称不能为空' }]"
+          >
+            <el-input
+              disabled
+              v-model.number="editRoleAuth.roleName"
+              autocomplete="off"
+            ></el-input>
+          </el-form-item>
+          <el-form-item
+            label="角色标识"
+            prop="roleCode"
+            :rules="[{ required: true, message: '角色标识不能为空' }]"
+          >
+            <el-input
+              disabled
+              v-model.number="editRoleAuth.roleCode"
+              autocomplete="off"
+            ></el-input>
+          </el-form-item>
+        </el-form>
+        <el-tabs type="border-card" class="tabs">
+          <el-tab-pane label="功能权限"
+            ><MenuTree ref="menuTreeRef" :treeObj="treeObj"></MenuTree
+          ></el-tab-pane>
+          <el-tab-pane label="数据权限">数据权限</el-tab-pane>
+        </el-tabs>
+        <span slot="footer" class="dialog-footer">
+          <el-button
+            @click="
+              () => {
+                this.$refs['editRoleAuth'].resetFields();
+                this.unusualdialog = false;
+                this.loadingView = false;
+              }
+            "
+            size="small"
+            >取 消</el-button
+          >
+          <el-button
+            type="primary"
+            @click="editAuthMenu('editRoleAuth')"
+            size="small"
+            >确 定</el-button
+          >
+        </span>
+      </div>
+    </el-dialog>
+  </div>
 </template>
-<script></script>
-<style lang="scss"></style>
+
+<script>
+import MenuTree from "./components/menuTree.vue";
+import {
+  getRoleTableList,
+  updateRoleAvailable,
+  getRoleBId,
+  addRole,
+  editRole,
+  deleteRoleInfo,
+  updateRolePermission,
+  getDetailRoleAuth,
+} from "@/api/system.js";
+import { dictType } from "@/api/dict.js";
+export default {
+  components: {
+    MenuTree,
+  },
+  data() {
+    return {
+      treeObj: {
+        roleId: null,
+        checkList: [],
+      },
+      loadingView: false,
+      //角色类型
+      stateOPtions: [],
+      loading: false, //数据加载中
+      rules: {
+        roleAvailable: { trigger: "change" },
+        roleName: { trigger: "blur" },
+      },
+      roleList: [],
+      formInline: {
+        roleName: undefined,
+        roleAvailable: undefined,
+        pageNum: 1,
+        pageSize: 10,
+        totalSize: 0,
+      },
+      tableData: [],
+      // 新增编辑表单
+      ruleForm: {
+        roleType: null,
+        roleCode: null,
+        roleName: null,
+      },
+      addUserRules: {
+        roleName: [
+          { required: true, message: "请输入角色名称", trigger: "blur" },
+        ],
+        roleCode: {
+          required: true,
+          message: "请输入角色标识",
+          trigger: "blur",
+        },
+        roleType: {
+          required: true,
+          message: "请选择角色类型",
+          trigger: "change",
+        },
+      },
+      //修改权限
+      editRoleAuth: {
+        roleName: "",
+        roleCode: "",
+      },
+      nuedialog: false,
+      unusualdialog: false,
+      title: "",
+    };
+  },
+  created() {
+    dictType({ dictType: 2 })
+      .then((res) => {
+        this.stateOPtions = res.data;
+      })
+      .catch(() => {});
+    this.getTableList();
+  },
+  methods: {
+    //修改权限
+    editAuthMenu(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          const { permissionIds, roleId } =
+            this.$refs.menuTreeRef.getCheckTreeKey();
+          if (!permissionIds) {
+            this.$message({
+              message: "至少要选择一个菜单",
+              type: "warning",
+            });
+          } else {
+            this.loadingView = true;
+            updateRolePermission({ permissionIds, roleId })
+              .then((res) => {
+                this.$message({
+                  message: "权限修改成功",
+                  type: "success",
+                });
+                this.getTableList();
+                this.loadingView = false;
+                this.unusualdialog = false;
+              })
+              .catch(() => {});
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    //分页数据切换
+    handleCurrentChange(val) {
+      this.formInline.pageNum = val;
+      this.getTableList();
+    },
+    //修改状态
+    setState(state, roleId) {
+      //启用接口
+      updateRoleAvailable({ roleAvailable: state, roleId })
+        .then((res) => {
+          this.$message({
+            message: res.msg,
+            type: "success",
+          });
+          this.getTableList();
+        })
+        .catch((error) => {});
+    },
+    async getTableList() {
+      try {
+        this.loading = true;
+        const result = await getRoleTableList({
+          ...this.formInline,
+          roleAvailable: Number(this.formInline.roleAvailable),
+          totalSize: undefined,
+        });
+        this.tableData = result.data.list;
+        this.formInline.totalSize = result.data.totalSize;
+        this.loading = false;
+      } catch (error) {
+        this.$message({
+          type: "error",
+          message: "请检查是否连接网络",
+        });
+      }
+    },
+
+    rowStyle() {
+      return "text-align:center";
+    },
+    // 查询
+    onSubmit() {
+      this.getTableList();
+    },
+    // 重置
+    reset(formName) {
+      this.$refs[formName].resetFields();
+      this.getTableList();
+    },
+
+    // 新增,编辑确定
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.loadingView = true;
+          switch (this.title) {
+            case "新增":
+              addRole({ ...this.ruleForm, roleId: undefined })
+                .then((res) => {
+                  this.$message({
+                    type: "success",
+                    message: res.msg,
+                  });
+                  this.getTableList();
+                  this.nuedialog = false;
+                  this.loadingView = false;
+                })
+                .catch(() => {});
+              break;
+            case "编辑":
+              editRole({ ...this.ruleForm })
+                .then((res) => {
+                  this.$message({
+                    type: "success",
+                    message: res.msg,
+                  });
+                  this.getTableList();
+                  this.nuedialog = false;
+                  this.loadingView = false;
+                })
+                .catch(() => {});
+
+              break;
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    //点击取消
+    cancel(formName) {
+      this.$refs[formName] && this.$refs[formName].resetFields();
+      this.ruleForm = {
+        roleType: null,
+        roleCode: null,
+        roleName: null,
+        roleId: null,
+      };
+      this.nuedialog = false;
+      this.loadingView = false;
+    },
+    // 编辑 回显数据
+    async compile(row) {
+      try {
+        const result = await getRoleBId({ roleId: row.id });
+        const userInfo = result.data;
+
+        // 直接替换整个对象,以确保 Vue 的响应式系统能够检测到变化
+        this.ruleForm = {
+          roleType: userInfo.roleType,
+          roleCode: userInfo.roleCode,
+          roleName: userInfo.roleDescription,
+          roleId: userInfo.id.toString(),
+        };
+        this.nuedialog = true;
+        this.title = "编辑";
+      } catch (error) {
+        this.$message.error("获取用户信息失败");
+      }
+    },
+    // 删除
+    deleted(row) {
+      this.$confirm("此操作将永久删除该角色, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          deleteRoleInfo({ roleId: row.id })
+            .then((res) => {
+              this.$message({
+                type: "success",
+                message: "删除成功!",
+              });
+              this.getTableList();
+            })
+            .catch(() => {});
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+    //权限修改按钮
+    editAuth(row) {
+      this.editRoleAuth.roleCode = row.roleCode;
+      this.editRoleAuth.roleName = row.roleDescription;
+      getDetailRoleAuth({ roleId: row.id })
+        .then((res) => {
+          this.treeObj = {
+            roleId: row.id,
+            checkList: res.data,
+          };
+          this.unusualdialog = true;
+        })
+        .catch(() => {});
+    },
+    // 新增
+    newnuedialog() {
+      this.cancel("addUserForm");
+      this.nuedialog = true;
+      this.title = "新增";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.general {
+  display: flex;
+  flex-wrap: wrap;
+
+  .condition {
+    width: 50%;
+    display: flex;
+
+    p {
+      width: 100px;
+      text-align: right;
+      line-height: 40px;
+    }
+
+    span {
+      line-height: 40px;
+
+      padding-left: 20px;
+    }
+
+    .el-select {
+      width: 100%;
+      margin-bottom: 20px;
+    }
+
+    .el-input {
+      margin-bottom: 20px;
+    }
+  }
+}
+
+.attachment {
+  display: flex;
+  padding-top: 10px;
+
+  p {
+    margin-right: 20px;
+    color: #409eff;
+  }
+}
+
+.addition {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 10px;
+}
+.tabs {
+  margin-bottom: 50px;
+}
+</style>

+ 604 - 3
src/views/system/userMag/index.vue

@@ -1,5 +1,606 @@
 <template>
-  <div>用户管理</div>
+  <div class="global-variable">
+    <div class="condition">
+      <el-form
+        :inline="true"
+        ref="ruleForm"
+        :model="formInline"
+        class="demo-form-inline"
+        :rules="rules"
+      >
+        <el-form-item label="用户名称:" prop="userName">
+          <el-input
+            v-model="formInline.userName"
+            placeholder="请输入用户名称"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="角色名称:" prop="roleId">
+          <el-select v-model="formInline.roleId" placeholder="请选择角色">
+            <el-option
+              :label="item.roleDescription"
+              v-for="item in roleList"
+              :value="item.id + ''"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit" size="small"
+            >查询</el-button
+          >
+          <el-button @click="reset('ruleForm')" size="small">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list-page">
+      <div class="newly">
+        <el-button type="primary" @click="newnuedialog" size="small"
+          >新增</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        class="center-align-table"
+        :data="tableData"
+        border
+        :cell-style="rowStyle"
+      >
+        <el-table-column
+          align="center"
+          fixed
+          prop="userId"
+          label="员工ID"
+          width="100"
+        >
+        </el-table-column>
+
+        <el-table-column align="center" label="员工名称" prop="userName">
+        </el-table-column>
+
+        <el-table-column prop="loginName" align="center" label="登录账号">
+        </el-table-column>
+        <el-table-column align="center" prop="userPhone" label="手机号">
+        </el-table-column>
+
+        <el-table-column prop="roleName" align="center" label="角色">
+        </el-table-column>
+        <el-table-column prop="state" align="center" label="状态" width="100">
+          <template slot-scope="scope">
+            <span>
+              {{
+                scope.row.state == 0
+                  ? "未启用"
+                  : scope.row.state == 1
+                  ? "启用"
+                  : "禁用"
+              }}</span
+            >
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          prop="transition"
+          align="center"
+          fixed="right"
+          label="操作"
+          width="200"
+        >
+          <template slot-scope="scope">
+            <el-button @click="compile(scope.row)" type="text" size="small"
+              >编辑</el-button
+            >
+            <el-button
+              v-if="scope.row.state == 0 || scope.row.state == 2"
+              @click="setState(1, scope.row.userId)"
+              type="text"
+              size="small"
+              >启用</el-button
+            >
+            <el-button
+              v-else
+              style="color: #666"
+              @click="setState(2, scope.row.userId)"
+              type="text"
+              size="small"
+              >停用</el-button
+            >
+            <el-button
+              style="color: #f90"
+              @click="editPwd(scope.row)"
+              type="text"
+              size="small"
+              >修改密码</el-button
+            >
+            <el-button
+              style="color: #f00"
+              @click="deleted(scope.row)"
+              type="text"
+              size="small"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-container">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page.sync="formInline.pageNum"
+          layout="total, prev, pager, next"
+          :page-size="formInline.pageSize"
+          :total="formInline.totalSize"
+        >
+        </el-pagination>
+      </div>
+    </div>
+
+    <!-- 弹出层 -->
+    <!-- 新增 /编辑-->
+    <el-dialog :title="title" :visible.sync="nuedialog" width="500px">
+      <div v-loading="loadingView" class="views">
+        <el-form
+          :model="ruleForm"
+          :rules="addUserRules"
+          ref="addUserForm"
+          label-width="100px"
+          class="demo-ruleForm"
+        >
+          <el-form-item label="员工名称" prop="userName">
+            <el-input
+              v-model="ruleForm.userName"
+              placeholder="请输入员工名称"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="电话号码" prop="phone">
+            <el-input
+              v-model="ruleForm.phone"
+              placeholder="请输入电话号码"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="账号名称" prop="loginName">
+            <el-input
+              v-model="ruleForm.loginName"
+              placeholder="请输入账号名称"
+              autocomplete="off"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="密码" prop="pwd" v-if="title === '新增'">
+            <el-input
+              v-model="ruleForm.pwd"
+              autocomplete="new-password"
+              show-password
+              placeholder="请输入密码"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="角色名称:" prop="roleId">
+            <el-select
+              v-model="ruleForm.roleId"
+              placeholder="请选择角色"
+              style="width: 100%"
+            >
+              <el-option
+                :label="item.roleDescription"
+                v-for="item in roleList"
+                :value="item.id + ''"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </el-form>
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="cancel('addUserForm')" size="small"
+            >取 消</el-button
+          >
+          <el-button
+            type="primary"
+            @click="submitForm('addUserForm')"
+            size="small"
+            >确 定</el-button
+          >
+        </span>
+      </div>
+    </el-dialog>
+    <!-- 风场详情 -->
+    <el-dialog title="修改密码" :visible.sync="unusualdialog" width="500px">
+      <div v-loading="loadingView" class="views">
+        <el-form
+          :model="editUserPassword"
+          ref="editUserPassword"
+          label-width="100px"
+        >
+          <el-form-item
+            label="旧密码"
+            prop="oldPWD"
+            :rules="[{ required: true, message: '旧密码不能为空' }]"
+          >
+            <el-input
+              v-model.number="editUserPassword.oldPWD"
+              autocomplete="off"
+              show-password
+            ></el-input>
+          </el-form-item>
+          <el-form-item
+            label="新密码"
+            prop="newPWD"
+            :rules="[{ required: true, message: '新密码不能为空' }]"
+          >
+            <el-input
+              v-model.number="editUserPassword.newPWD"
+              autocomplete="off"
+              show-password
+            ></el-input>
+          </el-form-item>
+        </el-form>
+        <span slot="footer" class="dialog-footer">
+          <el-button
+            @click="
+              () => {
+                this.$refs['editUserPassword'].resetFields();
+                this.unusualdialog = false;
+                this.loadingView = false;
+              }
+            "
+            size="small"
+            >取 消</el-button
+          >
+          <el-button
+            type="primary"
+            @click="editUserPwd('editUserPassword')"
+            size="small"
+            >确 定</el-button
+          >
+        </span>
+      </div>
+    </el-dialog>
+  </div>
 </template>
-<script></script>
-<style lang="scss"></style>
+
+<script>
+import {
+  getUserTableList,
+  getRoleTableList,
+  enableUser,
+  disableUser,
+  getUserInfoByUserId,
+  addUser,
+  editUser,
+  deleteUserInfo,
+  updatePWD,
+} from "@/api/system.js";
+export default {
+  data() {
+    const validatePhone = (rule, value, callback) => {
+      const phoneRegex = /^[1][3-9][0-9]{9}$/;
+      if (!value) {
+        return callback(new Error("手机号不能为空"));
+      }
+      if (!phoneRegex.test(value)) {
+        return callback(new Error("请输入正确的手机号"));
+      }
+      callback();
+    };
+    return {
+      loadingView: false,
+      loading: false, //数据加载中
+      rules: {
+        roleId: { trigger: "change" },
+        userName: { trigger: "blur" },
+      },
+      roleList: [],
+      formInline: {
+        userName: undefined,
+        roleId: undefined,
+        pageNum: 1,
+        pageSize: 10,
+        // sort: "desc",
+        totalSize: 0,
+      },
+      tableData: [],
+      // 新增编辑表单
+      ruleForm: {
+        phone: null,
+        pwd: null,
+        roleId: null,
+        userName: null,
+        loginName: null,
+      },
+      addUserRules: {
+        phone: [
+          { required: true, message: "请输入手机号", trigger: "blur" },
+          { validator: validatePhone, trigger: "blur" },
+        ],
+        loginName: { required: true, message: "请输入", trigger: "blur" },
+        pwd: { required: true, message: "请输入密码", trigger: "blur" },
+        roleId: { required: true, message: "请选择角色", trigger: "change" },
+        userName: { required: true, message: "请输入账号", trigger: "blur" },
+      },
+      //修改密码
+      editUserPassword: {
+        oldPWD: "",
+        newPWD: "",
+        userId: "",
+      },
+      nuedialog: false,
+      unusualdialog: false,
+      title: "",
+    };
+  },
+  created() {
+    this.getTableList();
+    this.getRoleList();
+  },
+
+  methods: {
+    //修改密码
+    editUserPwd(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.loadingView = true;
+          updatePWD({ ...this.editUserPassword })
+            .then((res) => {
+              this.$message({
+                message: "密码修改成功",
+                type: "success",
+              });
+              this.getTableList();
+              this.unusualdialog = false;
+              this.loadingView = false;
+            })
+            .catch(() => {
+              this.loadingView = false;
+            });
+        } else {
+          return false;
+        }
+      });
+    },
+    //分页数据切换
+    handleCurrentChange(val) {
+      this.formInline.pageNum = val;
+      this.getTableList();
+    },
+    //修改状态
+    setState(state, userId) {
+      switch (state) {
+        case 1:
+          //启用接口
+          enableUser({ userId })
+            .then((res) => {
+              this.$message({
+                message: res.msg,
+                type: "success",
+              });
+              this.getTableList();
+            })
+            .catch((error) => {});
+          break;
+        case 2:
+          //禁用接口
+          disableUser({ userId })
+            .then((res) => {
+              this.$message({
+                message: res.msg,
+                type: "success",
+              });
+              this.getTableList();
+            })
+            .catch((error) => {});
+          break;
+        default:
+          return;
+      }
+    },
+    async getTableList() {
+      try {
+        this.loading = true;
+        const result = await getUserTableList({
+          ...this.formInline,
+          totalSize: undefined,
+        });
+        this.tableData = result.data.list;
+        this.formInline.totalSize = result.data.totalSize;
+        this.loading = false;
+      } catch (error) {
+        this.$message({
+          type: "error",
+          message: "请检查是否连接网络",
+        });
+      }
+    },
+    async getRoleList() {
+      try {
+        const result = await getRoleTableList({ pageNum: 1, pageSize: 100000 });
+        this.roleList = result.data.list;
+      } catch (error) {
+        this.$message({
+          type: "error",
+          message: "请检查是否连接网络",
+        });
+      }
+    },
+    rowStyle() {
+      return "text-align:center";
+    },
+    // 查询
+    onSubmit() {
+      this.getTableList();
+    },
+    // 重置
+    reset(formName) {
+      this.$refs[formName].resetFields();
+      this.getTableList();
+    },
+
+    // 新增,编辑确定
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.loadingView = true;
+          switch (this.title) {
+            case "新增":
+              addUser({ ...this.ruleForm, userId: undefined })
+                .then((res) => {
+                  this.$message({
+                    type: "success",
+                    message: res.msg,
+                  });
+                  this.getTableList();
+                  this.nuedialog = false;
+                  this.loadingView = false;
+                })
+                .catch(() => {
+                  this.loadingView = false;
+                });
+
+              break;
+            case "编辑":
+              editUser({ ...this.ruleForm })
+                .then((res) => {
+                  this.$message({
+                    type: "success",
+                    message: res.msg,
+                  });
+                  this.getTableList();
+                  this.nuedialog = false;
+                  this.loadingView = false;
+                })
+                .catch(() => {
+                  this.loadingView = false;
+                });
+
+              break;
+          }
+          // this.nuedialog = false;
+        } else {
+          return false;
+        }
+      });
+    },
+    //点击取消
+    cancel(formName) {
+      this.$refs[formName] && this.$refs[formName].resetFields();
+      this.ruleForm = {
+        phone: null,
+        pwd: null,
+        roleId: null,
+        userName: null,
+        userId: null,
+        loginName: null,
+      };
+      this.nuedialog = false;
+      this.loadingView = false;
+    },
+    //异常详情
+    particulars(row) {
+      this.unusualdialog = true;
+    },
+    // 编辑 回显数据
+    async compile(row) {
+      try {
+        const result = await getUserInfoByUserId({ userId: row.userId });
+        const userInfo = result.data;
+
+        // 直接替换整个对象,以确保 Vue 的响应式系统能够检测到变化
+        this.ruleForm = {
+          phone: userInfo.userPhone,
+          pwd: undefined, // 如果需要重置密码字段
+          roleId: userInfo.roleId.toString(),
+          userName: userInfo.userName,
+          userId: userInfo.userId, // 如果需要用户ID
+          loginName: userInfo.loginName,
+        };
+        this.nuedialog = true;
+        this.title = "编辑";
+      } catch (error) {
+        this.$message.error("获取用户信息失败");
+      }
+    },
+    // 删除
+    deleted(row) {
+      this.$confirm("此操作将永久删除该用户, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          deleteUserInfo({ userId: row.userId })
+            .then((res) => {
+              this.$message({
+                type: "success",
+                message: "删除成功!",
+              });
+              this.getTableList();
+            })
+            .catch(() => {});
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+    editPwd(row) {
+      this.editUserPassword.userId = row.userId;
+      this.unusualdialog = true;
+    },
+    // 新增
+    newnuedialog() {
+      this.cancel("addUserForm");
+      this.ruleForm = {
+        loginName: "",
+        pwd: "",
+        userName: "",
+      };
+      this.nuedialog = true;
+      this.title = "新增";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.general {
+  display: flex;
+  flex-wrap: wrap;
+
+  .condition {
+    width: 50%;
+    display: flex;
+
+    p {
+      width: 100px;
+      text-align: right;
+      line-height: 40px;
+    }
+
+    span {
+      line-height: 40px;
+
+      padding-left: 20px;
+    }
+
+    .el-select {
+      width: 100%;
+      margin-bottom: 20px;
+    }
+
+    .el-input {
+      margin-bottom: 20px;
+    }
+  }
+}
+
+.attachment {
+  display: flex;
+  padding-top: 10px;
+
+  p {
+    margin-right: 20px;
+    color: #409eff;
+  }
+}
+
+.addition {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 10px;
+}
+</style>

+ 2 - 1
vue.config.js

@@ -33,7 +33,8 @@ module.exports = {
   devServer: {
     proxy: {
       "/api": {
-        target: "http://192.168.50.235:16200", //内网
+        // target: "http://192.168.5.4:16200", //内网
+        target: "http://192.168.50.235:16200",
         // target: "http://106.120.102.238:16600",//外网
         changeOrigin: true,
         pathRewrite: {

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