Browse Source

添加环境配置文件
封装请求方法

DESKTOP-NE65RNK\Citrus_limon 1 year ago
parent
commit
783d4a407a

+ 1 - 0
.env

@@ -0,0 +1 @@
+VITE_API_BASE_URL = ""

+ 1 - 0
.env.development

@@ -0,0 +1 @@
+VITE_API_BASE_URL = "http://192.168.1.6:8848"

+ 1 - 0
.env.production

@@ -0,0 +1 @@
+VITE_API_BASE_URL = ""

+ 1 - 0
.env.test

@@ -0,0 +1 @@
+VITE_API_BASE_URL = ""

+ 6 - 0
package-lock.json

@@ -10,6 +10,7 @@
       "dependencies": {
         "@layui/layui-vue": "^2.13.0",
         "axios": "^1.6.4",
+        "js-md5": "^0.8.3",
         "pinia": "^2.1.7",
         "vue": "^3.3.11",
         "vue-router": "^4.2.5"
@@ -1932,6 +1933,11 @@
         "node": ">= 10.13.0"
       }
     },
+    "node_modules/js-md5": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
+      "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ=="
+    },
     "node_modules/jsbarcode": {
       "version": "3.11.5",
       "resolved": "https://registry.npmmirror.com/jsbarcode/-/jsbarcode-3.11.5.tgz",

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
   "dependencies": {
     "@layui/layui-vue": "^2.13.0",
     "axios": "^1.6.4",
+    "js-md5": "^0.8.3",
     "pinia": "^2.1.7",
     "vue": "^3.3.11",
     "vue-router": "^4.2.5"

+ 113 - 0
src/api/index.ts

@@ -0,0 +1,113 @@
+import http from "@/utils/request";
+
+export const clientLogin = (params: any, callback: any) => {
+  return http.request("/client/login", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+
+export const clientLogout = (params: any, callback: any) => {
+  return http.request("/client/logout", "get", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+
+export const getClientInfo = (params: any, callback: any) => {
+  return http.request("/client/info", "get", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+
+// 系统管理
+// 用户管理-用户列表
+export const get_user_list = (params: any, callback: any) => {
+  return http.request("/user/getPage", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 用户管理-添加用户
+export const add_user = (params: any, callback: any) => {
+  return http.request("/user/save", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 用户管理-编辑用户
+export const update_user = (params: any, callback: any) => {
+  return http.request("/user/update", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 用户管理-设置用户状态
+export const set_user_status = (params: any, callback: any) => {
+  return http.request("/user/setStatus", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 用户管理-删除用户
+export const delete_user = (params: any, callback: any) => {
+  return http.request("/user/delete", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 用户管理-用户重置密码
+export const reset_user_password = (params: any, callback: any) => {
+  return http.request("/user/resetPassword", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+
+// 组织管理-组织列表
+export const get_group_list = (params: any, callback: any) => {
+  return http.request("/group/getPage", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 组织管理-添加组织
+export const add_group = (params: any, callback: any) => {
+  return http.request("/group/save", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 组织管理-编辑组织
+export const update_group = (params: any, callback: any) => {
+  return http.request("/group/update", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 组织管理-删除组织
+export const delete_group = (params: any, callback: any) => {
+  return http.request("/group/delete", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 组织管理-设置组织状态
+export const set_group_status = (params: any, callback: any) => {
+  return http.request("/group/setStatus", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+
+// 页面管理-页面列表
+export const get_menu_list = (params: any, callback: any) => {
+  return http.request("/menu/getPage", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 页面管理-添加页面
+export const add_menu = (params: any, callback: any) => {
+  return http.request("/menu/save", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 页面管理-编辑页面
+export const update_menu = (params: any, callback: any) => {
+  return http.request("/menu/update", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
+// 页面管理-删除页面
+export const delete_menu = (params: any, callback: any) => {
+  return http.request("/menu/delete", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};

+ 32 - 1
src/main.ts

@@ -1,10 +1,41 @@
 import { createApp } from "vue";
-import Layui from "@layui/layui-vue";
+import Layui, { layer } from "@layui/layui-vue";
 import "@layui/layui-vue/lib/index.css";
 import { router } from "./router";
 import App from "./App.vue";
 
 const app = createApp(App);
+app.config.globalProperties.$waitingConfirm = (
+  msg: string,
+  title = "提示",
+  type = {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+  }
+) => {
+  return new Promise((resolve) => {
+    layer.confirm(msg, {
+      title: title,
+      btn: [
+        {
+          text: type.confirmButtonText,
+          callback: (id: any) => {
+            resolve(true);
+            layer.close(id);
+          },
+        },
+        {
+          text: type.cancelButtonText,
+          callback: (id: any) => {
+            resolve(false);
+            layer.close(id);
+          },
+        },
+      ],
+    });
+  });
+};
+
 app.use(Layui);
 app.use(router);
 app.mount("#app");

+ 74 - 0
src/utils/request.ts

@@ -0,0 +1,74 @@
+import axios, { AxiosInstance } from "axios";
+const BASEURL = import.meta.env.VITE_API_BASE_URL;
+const checkStatus = (response: any) => {
+  if (response.status >= 200 && response.status < 300) {
+    if (response.data.code === 200 || !response.data.code) {
+      return response.data;
+    } else {
+      return response.data;
+    }
+  }
+};
+class HttpRequest {
+  // 请求拦截
+  interceptors(instance: AxiosInstance, url: string | number | undefined) {
+    instance.interceptors.request.use(
+      (config) => {
+        console.log(config);
+        // 添加全局的loading..
+        // 请求头携带token
+        return config;
+      },
+      (error: any) => {
+        return Promise.reject(error);
+      }
+    );
+
+    //响应拦截
+    instance.interceptors.response.use(
+      (res) => {
+        //返回数据
+        const { data } = res;
+        console.log("返回数据处理", res);
+        return data;
+      },
+      (error: any) => {
+        console.log("error==>", error);
+        return Promise.reject(error);
+      }
+    );
+  }
+
+  request(url: string, method: string, data: any, responseType?: any) {
+    const token = window.sessionStorage.getItem("_4l_token") || "";
+    switch (method) {
+      case "get":
+        data = { params: data };
+        break;
+      default:
+        data = { data };
+    }
+    const instance = axios.create({
+      headers: {
+        Accept: "application/json",
+        "Content-Type": "application/json;charset=UTF-8",
+        auth: "4L",
+        Token: token,
+      },
+      timeout: 50000,
+      baseURL: BASEURL,
+      responseType: responseType,
+    });
+
+    return instance({ url: `${url}`, method, ...data })
+      .then(checkStatus)
+      .then((data) => data)
+      .catch((err) => {
+        console.log(err);
+      });
+  }
+}
+
+const http = new HttpRequest();
+
+export default http;

+ 25 - 3
src/views/login/index.vue

@@ -14,7 +14,7 @@
             <lay-input v-model="loginParams.password" type="password" password prefix-icon="layui-icon-password" />
           </lay-form-item>
         </lay-form>
-        <lay-button type="primary" fluid @click="handleLogin()">登录</lay-button>
+        <lay-button type="primary" fluid @click="handleLogin()" :loading="pageInfo.loading">登录</lay-button>
       </div>
     </div>
     <div class="footer-wp">
@@ -29,7 +29,12 @@
 </template>
 
 <script lang="ts" setup>
+import { md5 } from "js-md5";
 import { ref, reactive } from "vue";
+import { useRouter } from "vue-router";
+import { clientLogin } from "@/api/index";
+
+const router = useRouter();
 
 const layFormRef = ref();
 const rules = ref({
@@ -41,10 +46,16 @@ const rules = ref({
   password: {
     type: "string",
     min: 1,
-    max: 16,
+    max: 20,
   },
 });
 
+interface PageInfo {
+  loading: boolean;
+}
+let pageInfo: PageInfo = reactive({
+  loading: false,
+});
 interface LoginParams {
   account?: string;
   password?: string;
@@ -54,7 +65,18 @@ const loginParams: LoginParams = reactive({});
 const handleLogin = () => {
   layFormRef.value.validate((isValidate: boolean) => {
     if (isValidate) {
-      console.log(loginParams);
+      let params: LoginParams = {
+        account: loginParams.account,
+        password: md5(`${loginParams.password}4L`),
+      };
+      pageInfo.loading = true;
+      clientLogin(params, (data: any) => {
+        pageInfo.loading = false;
+        if (data.code == 200) {
+          window.sessionStorage.setItem("_4l_token", data.data);
+          router.push({ path: "/" });
+        }
+      });
     }
   });
 };

+ 49 - 14
src/views/system/organization/components/Update.vue

@@ -2,14 +2,14 @@
   <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['500px', '450px']" :btn="operator">
     <div style="padding: 20px">
       <lay-form :model="modelParams" ref="layFormRef11" required>
-        <lay-form-item label="组织名称" prop="name">
-          <lay-input v-model="modelParams.name" />
+        <lay-form-item label="组织名称" prop="groupName">
+          <lay-input v-model="modelParams.groupName" />
         </lay-form-item>
-        <lay-form-item label="组织编码" prop="account">
-          <lay-input v-model="modelParams.account" />
+        <lay-form-item label="组织编码" prop="code">
+          <lay-input v-model="modelParams.code" />
         </lay-form-item>
-        <lay-form-item label="备注" prop="desc">
-          <lay-textarea placeholder="请输入备注" v-model="modelParams.desc" />
+        <lay-form-item label="描述" prop="describe">
+          <lay-textarea placeholder="请输入描述" v-model="modelParams.describe" />
         </lay-form-item>
       </lay-form>
     </div>
@@ -18,33 +18,68 @@
 
 <script lang="ts" setup>
 import { ref, reactive, defineExpose } from "vue";
+import { add_group, update_group } from "@/api";
 interface ModelInfo {
   title: string;
   visible: boolean;
   isUpdate: boolean;
+  loading: boolean;
 }
 interface ModelParams {
-  name?: string;
-  account?: string;
-  organization?: string;
-  desc?: string;
+  groupId?: String;
+  groupName?: string;
+  code?: string;
+  describe?: string;
 }
 let modelParams: ModelParams = reactive({});
-let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false, loading: false });
+
+interface HandleResult {
+  resolve?: any;
+  reject?: any;
+}
+const handleResult: HandleResult = reactive({});
 
 const show = (params?: ModelParams) => {
   modelInfo.visible = true;
   modelInfo.isUpdate = !!params;
-  modelInfo.title = modelInfo.isUpdate ? "编辑组织" : "添加组织";
+  modelInfo.title = modelInfo.isUpdate ? "编辑用户" : "添加用户";
+  modelParams = modelInfo.isUpdate ? reactive(params!) : {};
+  return new Promise(async (resolve, reject) => {
+    handleResult.resolve = resolve;
+    handleResult.reject = reject;
+  });
 };
 const operator = ref([
   {
     text: "确认",
-    callback: () => {},
+    callback: () => {
+      modelInfo.loading = true;
+      if (modelInfo.isUpdate) {
+        const params = { ...modelParams, status: 1, groupId: modelParams.groupId };
+        update_group(params, (data: any) => {
+          modelInfo.loading = false;
+          console.log(data);
+          handleResult.resolve(true);
+          modelInfo.visible = false;
+        });
+      } else {
+        const params = { ...modelParams, status: 1 };
+        add_group(params, (data: any) => {
+          modelInfo.loading = false;
+          console.log(data);
+          handleResult.resolve(true);
+          modelInfo.visible = false;
+        });
+      }
+    },
   },
   {
     text: "取消",
-    callback: () => {},
+    callback: () => {
+      handleResult.resolve(false);
+      modelInfo.visible = false;
+    },
   },
 ]);
 defineExpose({ show });

+ 82 - 13
src/views/system/organization/index.vue

@@ -9,17 +9,26 @@
 
     <template v-slot:body>
       <div class="form-layout-wp">
-        <lay-form class="form-wp" :model="params" mode="inline">
-          <lay-form-item label="组织名称" prop="username">
-            <lay-input v-model="params.username"></lay-input>
+        <lay-form class="form-wp" :model="pageParams" mode="inline">
+          <lay-form-item label="组织名称" prop="keyword">
+            <lay-input v-model="pageParams.params.keyword"></lay-input>
           </lay-form-item>
           <div class="form-button-wp">
-            <lay-button>搜索</lay-button>
+            <lay-button @click="getPageInfo()">搜索</lay-button>
           </div>
         </lay-form>
       </div>
       <div>
-        <lay-table :columns="columns"> </lay-table>
+        <lay-table :columns="columns" :data-source="dataSource" :loading="pageInfo.loading">
+          <template v-slot:operator="{ row }">
+            <lay-space>
+              <TableButton :text="row.status == 0 ? '启用' : '禁用'" @click="handleStatus(row)" />
+              <TableButton text="编辑" @click="handleUpdate(row)" />
+              <TableButton text="设置权限" @click="handleUpdate(row)" />
+              <TableButton type="danger" text="删除" @click="handleDelete(row)" />
+            </lay-space>
+          </template>
+        </lay-table>
       </div>
     </template>
   </lay-card>
@@ -27,21 +36,36 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive } from "vue";
+import { ref, reactive, getCurrentInstance } from "vue";
 import Update from "./components/Update.vue";
+import TableButton from "@/components/TableButton.vue";
+import { get_group_list, delete_group, set_group_status } from "@/api";
 
+const { proxy }: any = getCurrentInstance();
 const updateRef = ref();
 
+interface PageInfo {
+  loading: boolean;
+}
+
+let pageInfo: PageInfo = reactive({
+  loading: false,
+});
+
 interface FormItem {
-  username?: String;
+  pageNum?: Number;
+  pageSize?: Number;
+  params: {
+    keyword?: String;
+  };
 }
-const params: FormItem = reactive({});
+const pageParams: FormItem = reactive({ pageNum: 1, pageSize: 10, params: {} });
 
 const columns = ref([
-  { title: "组织名称", width: "80px", key: "username", sort: "desc" },
-  { title: "组织编码", width: "80px", key: "organization", sort: "desc" },
+  { title: "组织名称", width: "80px", key: "groupName", sort: "desc" },
+  { title: "组织编码", width: "80px", key: "code", sort: "desc" },
   { title: "状态", width: "80px", key: "status", sort: "desc" },
-  { title: "备注", width: "80px", key: "remake" },
+  { title: "说明", width: "80px", key: "describe", ellipsisTooltip: true },
   {
     title: "操作",
     width: "150px",
@@ -51,9 +75,54 @@ const columns = ref([
     ignoreExport: true,
   },
 ]);
+let dataSource = ref([]);
+
+const getPageInfo = () => {
+  // 请求组织列表
+  pageInfo.loading = true;
+  get_group_list(pageParams, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      dataSource.value = data.data.list;
+    }
+  });
+};
+getPageInfo();
 
-const handleUpdate = (value?: any) => {
-  updateRef.value.show(value);
+const handleUpdate = async (value?: any) => {
+  const result = await updateRef.value.show(value);
+  if (result) getPageInfo();
+};
+// 删除组织
+const handleDelete = async (value: any) => {
+  let result = await proxy.$waitingConfirm("是否确认删除该组织?");
+  if (!result) return;
+  let params = [value.groupId];
+  pageInfo.loading = true;
+  delete_group(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("删除成功");
+      getPageInfo();
+    }
+  });
+};
+// 修改组织状态
+const handleStatus = async (value: any) => {
+  let result = await proxy.$waitingConfirm(`是否确认${value.status == 0 ? "启用" : "禁用"}该组织?`);
+  if (!result) return;
+  let params = {
+    ids: [value.groupId],
+    status: value.status == 0 ? 1 : 0,
+  };
+  pageInfo.loading = true;
+  set_group_status(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("修改成功");
+      getPageInfo();
+    }
+  });
 };
 </script>
 

+ 48 - 13
src/views/system/user/components/Update.vue

@@ -1,18 +1,18 @@
 <template>
   <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['500px', '450px']" :btn="operator">
     <div style="padding: 20px">
-      <lay-form :model="modelParams" ref="layFormRef11" required>
+      <lay-form :model="modelParams" ref="modelParams" required>
         <lay-form-item label="昵称" prop="name">
           <lay-input v-model="modelParams.name" />
         </lay-form-item>
         <lay-form-item label="账号" prop="account">
           <lay-input v-model="modelParams.account" />
         </lay-form-item>
-        <lay-form-item label="组织" prop="organization">
-          <lay-input v-model="modelParams.organization" />
+        <lay-form-item label="组织" prop="groupIds">
+          <lay-input v-model="modelParams.groupIds" />
         </lay-form-item>
-        <lay-form-item label="备注" prop="desc">
-          <lay-textarea placeholder="请输入备注" v-model="modelParams.desc" />
+        <lay-form-item label="备注" prop="remark">
+          <lay-textarea placeholder="请输入备注" v-model="modelParams.remark" />
         </lay-form-item>
       </lay-form>
     </div>
@@ -20,35 +20,70 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, defineExpose } from "vue";
+import { reactive, defineExpose } from "vue";
+import { add_user, update_user } from "@/api";
 interface ModelInfo {
   title: string;
   visible: boolean;
   isUpdate: boolean;
+  loading: boolean;
 }
 interface ModelParams {
   name?: string;
   account?: string;
-  organization?: string;
-  desc?: string;
+  groupIds?: Array<String>;
+  status?: number;
+  remark?: string;
 }
 let modelParams: ModelParams = reactive({});
-let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false, loading: false });
+
+interface HandleResult {
+  resolve?: any;
+  reject?: any;
+}
+const handleResult: HandleResult = reactive({});
 
 const show = (params?: ModelParams) => {
   modelInfo.visible = true;
   modelInfo.isUpdate = !!params;
   modelInfo.title = modelInfo.isUpdate ? "编辑用户" : "添加用户";
-  modelParams = modelInfo.isUpdate ? JSON.parse(JSON.stringify(params)) : {};
+  modelParams = modelInfo.isUpdate ? reactive(params!) : {};
+  return new Promise(async (resolve, reject) => {
+    handleResult.resolve = resolve;
+    handleResult.reject = reject;
+  });
 };
-const operator = ref([
+const operator = reactive([
   {
     text: "确认",
-    callback: () => {},
+    callback: () => {
+      modelInfo.loading = true;
+      if (modelInfo.isUpdate) {
+        const params = { ...modelParams, status: 1, groupIds: [1] };
+        update_user(params, (data: any) => {
+          modelInfo.loading = false;
+          console.log(data);
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+        });
+      } else {
+        const params = { ...modelParams, status: 1, groupIds: [1] };
+        add_user(params, (data: any) => {
+          modelInfo.loading = false;
+          console.log(data);
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+        });
+      }
+    },
   },
   {
     text: "取消",
-    callback: () => {},
+    callback: () => {
+      modelInfo.visible = false;
+      handleResult.resolve(false);
+    },
   },
 ]);
 defineExpose({ show });

+ 90 - 40
src/views/system/user/index.vue

@@ -9,27 +9,24 @@
 
     <template v-slot:body>
       <div class="form-layout-wp">
-        <lay-form class="form-wp" :model="params" mode="inline">
-          <lay-form-item label="用户名" prop="name">
-            <lay-input v-model="params.name" />
-          </lay-form-item>
-          <lay-form-item label="账号" prop="account">
-            <lay-input v-model="params.account" />
+        <lay-form class="form-wp" :model="pageParams" mode="inline">
+          <lay-form-item label="昵称" prop="name">
+            <lay-input v-model="pageParams.params.name" />
           </lay-form-item>
           <div class="form-button-wp">
-            <lay-button>搜索</lay-button>
+            <lay-button @click="getPageInfo()">搜索</lay-button>
           </div>
         </lay-form>
       </div>
       <div>
-        <lay-table :columns="columns" :data-source="dataSource">
+        <lay-table :columns="columns" :data-source="dataSource" :loading="pageInfo.loading">
           <template v-slot:operator="{ row }">
             <lay-space>
-              <TableButton text="禁用" />
+              <TableButton :text="row.status == 0 ? '启用' : '禁用'" @click="handleStatus(row)" />
               <TableButton text="编辑" @click="handleUpdate(row)" />
-              <TableButton type="danger" text="删除" />
-              <TableButton type="danger" text="重置密码"
-            /></lay-space>
+              <TableButton type="danger" text="删除" @click="handleDelete(row)" />
+              <TableButton type="danger" text="重置密码" @click="handleResetPassword(row)" />
+            </lay-space>
           </template>
         </lay-table>
       </div>
@@ -39,56 +36,109 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive } from "vue";
+import { ref, reactive, getCurrentInstance } from "vue";
 import Update from "./components/Update.vue";
 import TableButton from "@/components/TableButton.vue";
+import { get_user_list, delete_user, set_user_status, reset_user_password } from "@/api";
 
-const requestData = {
-  data: {
-    list: [
-      {
-        userId: "123",
-        name: "admin",
-        status: 1,
-        account: "admin",
-        groupNames: "第一组,第二组",
-        groupIds: "1,2",
-      },
-    ],
-    total: 11,
-    pageNum: 1,
-    pageSize: 10,
-    pages: [1, 2],
-  },
-};
-
+const { proxy }: any = getCurrentInstance();
 const updateRef = ref();
 
+interface PageInfo {
+  loading: boolean;
+}
+
+let pageInfo: PageInfo = reactive({
+  loading: false,
+});
+
 interface FormItem {
-  name?: String;
-  account?: String;
+  pageNum?: Number;
+  pageSize?: Number;
+  params: {
+    name?: String;
+  };
 }
-const params: FormItem = reactive({});
+const pageParams: FormItem = reactive({ pageNum: 1, pageSize: 10, params: {} });
 
 const columns = ref([
   { title: "昵称", width: "80px", key: "name", sort: "desc" },
   { title: "账号", width: "80px", key: "account", sort: "desc" },
   { title: "组织", width: "80px", key: "groupNames", sort: "desc" },
   { title: "状态", width: "80px", key: "status" },
-  { title: "备注", width: "80px", key: "remake" },
+  { title: "备注", width: "80px", key: "remark", ellipsisTooltip: true},
   {
     title: "操作",
     width: "150px",
     customSlot: "operator",
     key: "operator",
-    fixed: "right",
     ignoreExport: true,
   },
 ]);
-const dataSource = ref(requestData.data.list);
+let dataSource = ref([]);
+
+const getPageInfo = () => {
+  // 请求用户列表
+  pageInfo.loading = true;
+  get_user_list(pageParams, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      dataSource.value = data.data.list;
+    }
+  });
+};
+getPageInfo();
 
-const handleUpdate = (value?: any) => {
-  updateRef.value.show(value);
+const handleUpdate = async (value?: any) => {
+  const result = await updateRef.value.show(value);
+  if (result) getPageInfo();
+};
+// 删除用户
+const handleDelete = async (value: any) => {
+  let result = await proxy.$waitingConfirm("是否确认删除该用户?");
+  if (!result) return;
+  let params = [value.userId];
+  pageInfo.loading = true;
+  delete_user(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("删除成功");
+      getPageInfo();
+    }
+  });
+};
+// 修改用户状态
+const handleStatus = async (value: any) => {
+  let result = await proxy.$waitingConfirm(`是否确认${value.status == 0 ? "启用" : "禁用"}该用户?`);
+  if (!result) return;
+  let params = {
+    ids: [value.userId],
+    status: value.status == 0 ? 1 : 0,
+  };
+  pageInfo.loading = true;
+  set_user_status(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("修改成功");
+      getPageInfo();
+    }
+  });
+};
+// 重置密码
+const handleResetPassword = async (value: any) => {
+  let result = await proxy.$waitingConfirm(`是否确认重置该用户密码?`);
+  if (!result) return;
+  let params = {
+    id: value.userId,
+  };
+  pageInfo.loading = true;
+  reset_user_password(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("重置成功");
+      getPageInfo();
+    }
+  });
 };
 </script>
 

+ 103 - 0
src/views/system/webpage/components/Operator.vue

@@ -0,0 +1,103 @@
+<template>
+  <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['1200px', '600px']">
+    <div>
+      <lay-button>添加</lay-button>
+    </div>
+    <div style="padding: 20px">
+      <lay-table :columns="columns" :data-source="dataSource" :loading="modelInfo.loading">
+        <template v-slot:menuType="{ row }">
+          {{ row.menuType == 1 ? "目录" : row.menuType == 2 ? "页面" : "操作" }}
+        </template>
+        <template v-slot:operator="{ row }">
+          <lay-space>
+            <TableButton text="编辑" @click="handleUpdate(row)" />
+            <TableButton type="danger" text="删除" @click="handleDelete(row)" />
+          </lay-space>
+        </template>
+      </lay-table>
+    </div>
+  </lay-layer>
+  <UpdateOperator ref="updateOperatorRef" />
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, defineExpose, getCurrentInstance } from "vue";
+import UpdateOperator from "./UpdateOperator.vue";
+import TableButton from "@/components/TableButton.vue";
+import { get_menu_list, delete_menu } from "@/api";
+
+const { proxy }: any = getCurrentInstance();
+const updateOperatorRef = ref();
+
+interface ModelInfo {
+  title: string;
+  visible: boolean;
+  isUpdate: boolean;
+  loading: boolean;
+}
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false, loading: false });
+
+interface FormItem {
+  pageNum?: Number;
+  pageSize?: Number;
+  params: {
+    name?: String;
+    account?: String;
+  };
+}
+const pageParams: FormItem = reactive({ pageNum: 1, pageSize: 10, params: {} });
+
+const columns = ref([
+  { title: "页面名称", key: "name", sort: "desc" },
+  { title: "类型", key: "menuType", customSlot: "menuType", sort: "desc" },
+  {
+    title: "操作",
+    width: "300px",
+    customSlot: "operator",
+    key: "operator",
+    fixed: "right",
+    ignoreExport: true,
+  },
+]);
+let dataSource = ref([]);
+
+const show = () => {
+  modelInfo.visible = true;
+  modelInfo.title = "操作管理";
+  getPageInfo();
+};
+
+// 请求操作列表
+const getPageInfo = () => {
+  modelInfo.loading = true;
+  get_menu_list(pageParams, (data: any) => {
+    modelInfo.loading = false;
+    if (data.code == 200) {
+      dataSource.value = data.data.list;
+    }
+  });
+};
+
+// 添加/编辑操作
+const handleUpdate = async (value?: any) => {
+  const result = await updateOperatorRef.value.show(value);
+  if (result) getPageInfo();
+};
+
+// 删除操作
+const handleDelete = async (value: any) => {
+  let result = await proxy.$waitingConfirm("是否确认删除该操作?");
+  if (!result) return;
+  let params = [value.menuId];
+  modelInfo.loading = true;
+  delete_menu(params, (data: any) => {
+    modelInfo.loading = false;
+    if (data.code == 200) {
+      console.log("删除成功");
+      getPageInfo();
+    }
+  });
+};
+
+defineExpose({ show });
+</script>

+ 66 - 18
src/views/system/webpage/components/Update.vue

@@ -1,19 +1,19 @@
 <template>
   <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['500px', '450px']" :btn="operator">
     <div style="padding: 20px">
-      <lay-form :model="modelParams" ref="layFormRef11" required>
+      <lay-form :model="modelParams" ref="modelParams" required>
         <lay-form-item label="页面名称" prop="name">
           <lay-input v-model="modelParams.name" />
         </lay-form-item>
-        <lay-form-item label="URL" prop="account">
-          <lay-input v-model="modelParams.account" />
+        <lay-form-item label="URL" prop="filePath">
+          <lay-input v-model="modelParams.filePath" />
         </lay-form-item>
-        <lay-form-item label="排序" prop="organization">
-          <lay-input v-model="modelParams.organization" />
+        <lay-form-item label="排序" prop="sequence">
+          <lay-input v-model="modelParams.sequence" />
         </lay-form-item>
-        <lay-form-item label="页面类型" prop="type">
-          <lay-radio v-model="modelParams.type" name="pageType" value="1">目录</lay-radio>
-          <lay-radio v-model="modelParams.type" name="pageType" value="2">页面</lay-radio>
+        <lay-form-item label="页面类型" prop="menuType">
+          <lay-radio v-model="modelParams.menuType" name="menuType" value="1">目录</lay-radio>
+          <lay-radio v-model="modelParams.menuType" name="menuType" value="2">页面</lay-radio>
         </lay-form-item>
       </lay-form>
     </div>
@@ -21,34 +21,82 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, defineExpose } from "vue";
+import { reactive, defineExpose } from "vue";
+import { add_menu, update_menu } from "@/api";
 interface ModelInfo {
   title: string;
   visible: boolean;
   isUpdate: boolean;
+  loading: boolean;
 }
 interface ModelParams {
+  parentId?: string;
+  menuId?: string;
   name?: string;
-  account?: string;
-  organization?: string;
-  desc?: string;
+  filePath?: string;
+  menuType?: string;
+  sequence?: string;
+  status?: number;
 }
 let modelParams: ModelParams = reactive({});
-let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false, loading: false });
 
-const show = (params?: ModelParams) => {
+interface HandleResult {
+  resolve?: any;
+  reject?: any;
+}
+const handleResult: HandleResult = reactive({});
+
+const show = (type: number, params?: ModelParams) => {
   modelInfo.visible = true;
   modelInfo.isUpdate = !!params;
-  modelInfo.title = modelInfo.isUpdate ? "编辑页面" : "添加页面";
+  switch (type) {
+    case 1:
+      modelInfo.title = "添加页面";
+      break;
+    case 2:
+      modelInfo.title = "添加子页面";
+      break;
+    case 3:
+      modelInfo.title = "编辑页面";
+      break;
+  }
+  modelParams = modelInfo.isUpdate ? reactive(params!) : {};
+  return new Promise(async (resolve, reject) => {
+    handleResult.resolve = resolve;
+    handleResult.reject = reject;
+  });
 };
-const operator = ref([
+const operator = reactive([
   {
     text: "确认",
-    callback: () => {},
+    callback: () => {
+      modelInfo.loading = true;
+      if (modelInfo.isUpdate) {
+        const params = { ...modelParams, status: 1 };
+        update_menu(params, (data: any) => {
+          modelInfo.loading = false;
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+          console.log(data);
+        });
+      } else {
+        const params = { ...modelParams, status: 1, parentId: 0 };
+        add_menu(params, (data: any) => {
+          modelInfo.loading = false;
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+          console.log(data);
+        });
+      }
+    },
   },
   {
     text: "取消",
-    callback: () => {},
+    callback: () => {
+      modelInfo.visible = false;
+      handleResult.resolve(false);
+    },
   },
 ]);
 defineExpose({ show });

+ 93 - 0
src/views/system/webpage/components/UpdateOperator.vue

@@ -0,0 +1,93 @@
+<template>
+  <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['500px', '450px']" :btn="operator">
+    <div style="padding: 20px">
+      <lay-form :model="modelParams" ref="modelParams" required>
+        <lay-form-item label="页面名称" prop="name">
+          <lay-input v-model="modelParams.name" />
+        </lay-form-item>
+        <lay-form-item label="URL" prop="filePath">
+          <lay-input v-model="modelParams.filePath" />
+        </lay-form-item>
+        <lay-form-item label="排序" prop="sequence">
+          <lay-input v-model="modelParams.sequence" />
+        </lay-form-item>
+        <lay-form-item label="页面类型" prop="menuType">
+          <lay-radio v-model="modelParams.menuType" name="menuType" value="1">目录</lay-radio>
+          <lay-radio v-model="modelParams.menuType" name="menuType" value="2">页面</lay-radio>
+        </lay-form-item>
+      </lay-form>
+    </div>
+  </lay-layer>
+</template>
+
+<script lang="ts" setup>
+import { reactive, defineExpose } from "vue";
+import { add_menu, update_menu } from "@/api";
+interface ModelInfo {
+  title: string;
+  visible: boolean;
+  isUpdate: boolean;
+  loading: boolean;
+}
+interface ModelParams {
+  parentId?: string;
+  menuId?: string;
+  name?: string;
+  filePath?: string;
+  menuType?: string;
+  sequence?: string;
+  status?: number;
+}
+let modelParams: ModelParams = reactive({});
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false, loading: false });
+
+interface HandleResult {
+  resolve?: any;
+  reject?: any;
+}
+const handleResult: HandleResult = reactive({});
+
+const show = (params?: ModelParams) => {
+  modelInfo.visible = true;
+  modelInfo.isUpdate = !!params;
+  modelInfo.title = modelInfo.isUpdate ? "编辑操作" : "添加操作";
+  modelParams = modelInfo.isUpdate ? reactive(params!) : {};
+  return new Promise(async (resolve, reject) => {
+    handleResult.resolve = resolve;
+    handleResult.reject = reject;
+  });
+};
+const operator = reactive([
+  {
+    text: "确认",
+    callback: () => {
+      modelInfo.loading = true;
+      if (modelInfo.isUpdate) {
+        const params = { ...modelParams, status: 1 };
+        update_menu(params, (data: any) => {
+          modelInfo.loading = false;
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+          console.log(data);
+        });
+      } else {
+        const params = { ...modelParams, status: 1, parentId: 0 };
+        add_menu(params, (data: any) => {
+          modelInfo.loading = false;
+          modelInfo.visible = false;
+          handleResult.resolve(true);
+          console.log(data);
+        });
+      }
+    },
+  },
+  {
+    text: "取消",
+    callback: () => {
+      modelInfo.visible = false;
+      handleResult.resolve(false);
+    },
+  },
+]);
+defineExpose({ show });
+</script>

+ 77 - 7
src/views/system/webpage/index.vue

@@ -4,38 +4,108 @@
       <span class="card-title">页面管理</span>
     </template>
     <template v-slot:extra>
-      <lay-button class="card-button" @click="handleUpdate()">添加页面</lay-button>
+      <lay-button class="card-button" @click="handleUpdate(1)">添加页面</lay-button>
     </template>
 
     <template v-slot:body>
       <div>
-        <lay-table :columns="columns"> </lay-table>
+        <lay-table :columns="columns" :data-source="dataSource" :loading="pageInfo.loading">
+          <template v-slot:menuType="{ row }">
+            {{ row.menuType == 1 ? "目录" : row.menuType == 2 ? "页面" : "操作" }}
+          </template>
+          <template v-slot:operator="{ row }">
+            <lay-space>
+              <TableButton v-if="row.menuType == 1" text="添加子页面" @click="handleUpdate(2, row)" />
+              <TableButton text="编辑" @click="handleUpdate(3, row)" />
+              <TableButton text="操作管理" @click="handleOperator(row)" />
+              <TableButton type="danger" text="删除" @click="handleDelete(row)" />
+            </lay-space>
+          </template>
+        </lay-table>
       </div>
     </template>
   </lay-card>
   <Update ref="updateRef" />
+  <Operator ref="operatorRef" />
 </template>
 
 <script lang="ts" setup>
-import { ref } from "vue";
+import { ref, reactive, getCurrentInstance } from "vue";
 import Update from "./components/Update.vue";
+import Operator from "./components/Operator.vue";
+import TableButton from "@/components/TableButton.vue";
+import { get_menu_list, delete_menu } from "@/api";
 
+const { proxy }: any = getCurrentInstance();
 const updateRef = ref();
+const operatorRef = ref();
+
+interface PageInfo {
+  loading: boolean;
+}
+
+let pageInfo: PageInfo = reactive({
+  loading: false,
+});
+
+interface FormItem {
+  pageNum?: Number;
+  pageSize?: Number;
+  params: {
+    name?: String;
+    account?: String;
+  };
+}
+const pageParams: FormItem = reactive({ pageNum: 1, pageSize: 10, params: {} });
 
 const columns = ref([
-  { title: "页面名称", key: "username", sort: "desc" },
+  { title: "页面名称", key: "name", sort: "desc" },
+  { title: "类型", key: "menuType", customSlot: "menuType", sort: "desc" },
   {
     title: "操作",
-    width: "150px",
+    width: "300px",
     customSlot: "operator",
     key: "operator",
     fixed: "right",
     ignoreExport: true,
   },
 ]);
+let dataSource = ref([]);
 
-const handleUpdate = (value?: any) => {
-  updateRef.value.show(value);
+// 请求页面列表
+const getPageInfo = () => {
+  pageInfo.loading = true;
+  get_menu_list(pageParams, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      dataSource.value = data.data.list;
+    }
+  });
+};
+getPageInfo();
+
+// 添加/编辑页面
+const handleUpdate = async (type: number, value?: any) => {
+  const result = await updateRef.value.show(type, value);
+  if (result) getPageInfo();
+};
+// 操作管理
+const handleOperator = (value: any) => {
+  operatorRef.value.show(value);
+};
+// 删除页面
+const handleDelete = async (value: any) => {
+  let result = await proxy.$waitingConfirm("是否确认删除该页面?");
+  if (!result) return;
+  let params = [value.menuId];
+  pageInfo.loading = true;
+  delete_menu(params, (data: any) => {
+    pageInfo.loading = false;
+    if (data.code == 200) {
+      console.log("删除成功");
+      getPageInfo();
+    }
+  });
 };
 </script>
 

+ 2 - 1
tsconfig.json

@@ -17,12 +17,13 @@
     "paths": {
       "@/*": ["src/*"]
     },
+    "types": ["vite/client"],
 
     /* Linting */
     "strict": true,
     "noUnusedLocals": true,
     "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
+    "noFallthroughCasesInSwitch": true,
   },
   "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
   "references": [{ "path": "./tsconfig.node.json" }]