소스 검색

添加登录页面
添加页面弹窗基础框架

DESKTOP-NE65RNK\Citrus_limon 1 년 전
부모
커밋
78fc860648

+ 111 - 4
package-lock.json

@@ -9,6 +9,8 @@
       "version": "0.0.0",
       "dependencies": {
         "@layui/layui-vue": "^2.13.0",
+        "axios": "^1.6.4",
+        "pinia": "^2.1.7",
         "vue": "^3.3.11",
         "vue-router": "^4.2.5"
       },
@@ -1357,6 +1359,21 @@
       "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
       "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
     },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+    },
+    "node_modules/axios": {
+      "version": "1.6.4",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.6.4.tgz",
+      "integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==",
+      "dependencies": {
+        "follow-redirects": "^1.15.4",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -1489,6 +1506,17 @@
       "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
       "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/commander": {
       "version": "2.20.3",
       "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
@@ -1529,6 +1557,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/dijkstrajs": {
       "version": "1.0.3",
       "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
@@ -1733,6 +1769,32 @@
         "node": ">=8"
       }
     },
+    "node_modules/follow-redirects": {
+      "version": "1.15.4",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.4.tgz",
+      "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/fsevents": {
       "version": "2.3.3",
       "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
@@ -1999,8 +2061,6 @@
       "version": "1.52.0",
       "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
       "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "dev": true,
-      "peer": true,
       "engines": {
         "node": ">= 0.6"
       }
@@ -2009,8 +2069,6 @@
       "version": "2.1.35",
       "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
       "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "dev": true,
-      "peer": true,
       "dependencies": {
         "mime-db": "1.52.0"
       },
@@ -2127,6 +2185,50 @@
         "node": ">=8.6"
       }
     },
+    "node_modules/pinia": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.1.7.tgz",
+      "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.5.0",
+        "vue-demi": ">=0.14.5"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.4.0",
+        "typescript": ">=4.4.4",
+        "vue": "^2.6.14 || ^3.3.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia/node_modules/vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/pngjs": {
       "version": "5.0.0",
       "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
@@ -2148,6 +2250,11 @@
         "node": "^10 || ^12 || >=14"
       }
     },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+    },
     "node_modules/punycode": {
       "version": "2.3.1",
       "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",

+ 2 - 0
package.json

@@ -10,6 +10,8 @@
   },
   "dependencies": {
     "@layui/layui-vue": "^2.13.0",
+    "axios": "^1.6.4",
+    "pinia": "^2.1.7",
     "vue": "^3.3.11",
     "vue-router": "^4.2.5"
   },

+ 6 - 1
src/assets/css/index.scss

@@ -1,5 +1,10 @@
-:root{
+:root {
   --color-theme: rgb(28, 175, 131);
+  --button-primary-color: rgb(28, 175, 131);
+  --button-normal-color: #1e9fff;
+  --button-warm-color: #ffb800;
+  --button-danger-color: #ff5722;
+  --button-checked-color: #16b777;
 }
 
 * {

+ 17 - 0
src/assets/images/bg.svg

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="1457px" height="651px" viewBox="0 0 1457 651" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 54 (76480) - https://sketchapp.com -->
+    <title>bg</title>
+    <desc>Created with Sketch.</desc>
+    <g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="body">
+            <rect id="矩形" fill="#E0E3F5" transform="translate(1111.405592, 620.405592) rotate(45.000000) translate(-1111.405592, -620.405592) " x="1089.90559" y="598.905592" width="43" height="43"></rect>
+            <rect id="矩形" fill="#DEEFF6" transform="translate(127.254834, 230.254834) rotate(40.000000) translate(-127.254834, -230.254834) " x="95.254834" y="198.254834" width="64" height="64"></rect>
+            <circle id="Oval-7" fill="#C9CFED" fill-rule="nonzero" opacity="0.45" cx="1286.5" cy="27.5" r="23.5"></circle>
+            <circle id="Oval-7" fill="#E7E6E6" fill-rule="nonzero" opacity="0.45" cx="191" cy="51" r="18"></circle>
+            <circle id="Oval-7" fill="#EFEFEF" fill-rule="nonzero" opacity="0.45" cx="888" cy="499" r="18"></circle>
+            <ellipse id="Oval-7" stroke="#E4E4F2" stroke-width="10" fill-opacity="0" fill="#FFFFFF" fill-rule="nonzero" opacity="0.45" cx="1373.5" cy="331.5" rx="78.5" ry="79.5"></ellipse>
+            <ellipse id="Oval-7" stroke="#CEECF8" stroke-width="10" fill-opacity="0" fill="#FFFFFF" fill-rule="nonzero" opacity="0.45" cx="235" cy="481.5" rx="44" ry="44.5"></ellipse>
+        </g>
+    </g>
+</svg>

+ 3 - 1
src/components/PageLayout/Layout.vue

@@ -10,7 +10,9 @@
       <lay-body class="layout-body">
         <Tag />
         <div class="layout-main">
-          <router-view class="layout-content" />
+          <div class="layout-content">
+            <router-view />
+          </div>
         </div>
       </lay-body>
     </lay-layout>

+ 34 - 0
src/components/TableButton.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="table-button" :class="props.type">{{ props.text }}</div>
+</template>
+<script lang="ts" setup>
+import { defineProps } from "vue";
+const props = defineProps({
+  type: {
+    type: String,
+    default: "primary",
+  },
+  text: {
+    type: String,
+    default: "按钮",
+  },
+});
+</script>
+<style lang="scss" scoped>
+.table-button{
+    cursor: pointer;
+    display: inline-block;
+}
+.primary {
+  color: var(--button-primary-color);
+}
+.normal {
+  color: var(--button-normal-color);
+}
+.warm {
+  color: var(--button-warm-color);
+}
+.danger {
+  color: var(--button-danger-color);
+}
+</style>

+ 103 - 2
src/views/login/index.vue

@@ -1,5 +1,106 @@
 <template>
-  <div></div>
+  <div class="login-page-wp">
+    <div class="login-wp">
+      <div class="login-title">
+        <div class="title">两江资本</div>
+        <div class="sub-title">今天你当量化韭菜了吗?</div>
+      </div>
+      <div class="login-form-wp">
+        <lay-form :model="loginParams" ref="layFormRef" :useCN="true" :rules="rules">
+          <lay-form-item prop="account" required>
+            <lay-input v-model="loginParams.account" prefix-icon="layui-icon-username" />
+          </lay-form-item>
+          <lay-form-item prop="password" required>
+            <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>
+      </div>
+    </div>
+    <div class="footer-wp">
+      <div class="footer">
+        <lay-space> <span>© 2021</span><span>两江资本</span> </lay-space>
+      </div>
+      <div class="sub-footer">
+        <lay-space> <span>韭菜</span><span>被割</span><span>嘎嘎割</span> </lay-space>
+      </div>
+    </div>
+  </div>
 </template>
 
-<script lang="ts" setup></script>
+<script lang="ts" setup>
+import { ref, reactive } from "vue";
+
+const layFormRef = ref();
+const rules = ref({
+  account: {
+    type: "string",
+    min: 1,
+    max: 16,
+  },
+  password: {
+    type: "string",
+    min: 1,
+    max: 16,
+  },
+});
+
+interface LoginParams {
+  account?: string;
+  password?: string;
+}
+const loginParams: LoginParams = reactive({});
+
+const handleLogin = () => {
+  layFormRef.value.validate((isValidate: boolean) => {
+    if (isValidate) {
+      console.log(loginParams);
+    }
+  });
+};
+</script>
+<style lang="scss" scoped>
+.login-page-wp {
+  min-width: 650px;
+  min-height: 540px;
+  box-sizing: border-box;
+  padding: 100px 0;
+  position: relative;
+  width: 100%;
+  height: 100%;
+  background: url("../../assets/images/bg.svg") no-repeat;
+  background-size: 100% auto;
+  background-position: center;
+  background-color: #f5f7f9;
+  .login-wp {
+    width: 375px;
+    position: absolute;
+    top: 40%;
+    left: 50%;
+    transform: translate(-50%, -40%);
+    .login-title {
+      padding: 20px;
+      text-align: center;
+      .title {
+        font-size: 30px;
+        margin-bottom: 10px;
+      }
+      .sub-title {
+        color: #999;
+      }
+    }
+  }
+  .footer-wp {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    padding: 40px 20px;
+    box-sizing: border-box;
+    text-align: center;
+    .footer {
+      box-sizing: border-box;
+      padding: 10px;
+    }
+  }
+}
+</style>

+ 51 - 0
src/views/system/organization/components/Update.vue

@@ -0,0 +1,51 @@
+<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-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="desc">
+          <lay-textarea placeholder="请输入备注" v-model="modelParams.desc" />
+        </lay-form-item>
+      </lay-form>
+    </div>
+  </lay-layer>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, defineExpose } from "vue";
+interface ModelInfo {
+  title: string;
+  visible: boolean;
+  isUpdate: boolean;
+}
+interface ModelParams {
+  name?: string;
+  account?: string;
+  organization?: string;
+  desc?: string;
+}
+let modelParams: ModelParams = reactive({});
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
+
+const show = (params?: ModelParams) => {
+  modelInfo.visible = true;
+  modelInfo.isUpdate = !!params;
+  modelInfo.title = modelInfo.isUpdate ? "编辑组织" : "添加组织";
+};
+const operator = ref([
+  {
+    text: "确认",
+    callback: () => {},
+  },
+  {
+    text: "取消",
+    callback: () => {},
+  },
+]);
+defineExpose({ show });
+</script>

+ 10 - 1
src/views/system/organization/index.vue

@@ -4,7 +4,7 @@
       <span class="card-title">组织管理</span>
     </template>
     <template v-slot:extra>
-      <lay-button class="card-button">添加组织</lay-button>
+      <lay-button class="card-button" @click="handleUpdate()">添加组织</lay-button>
     </template>
 
     <template v-slot:body>
@@ -23,10 +23,15 @@
       </div>
     </template>
   </lay-card>
+  <Update ref="updateRef" />
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive } from "vue";
+import Update from "./components/Update.vue";
+
+const updateRef = ref();
+
 interface FormItem {
   username?: String;
 }
@@ -46,6 +51,10 @@ const columns = ref([
     ignoreExport: true,
   },
 ]);
+
+const handleUpdate = (value?: any) => {
+  updateRef.value.show(value);
+};
 </script>
 
 <style lang="scss" scoped>

+ 20 - 12
src/views/system/user/components/Update.vue

@@ -1,15 +1,18 @@
 <template>
-  <lay-layer v-model="visible" :shade="false" :area="['500px', '450px']" :btn="operator">
+  <lay-layer :title="modelInfo.title" v-model="modelInfo.visible" :area="['500px', '450px']" :btn="operator">
     <div style="padding: 20px">
-      <lay-form :model="params" ref="layFormRef11" required>
-        <lay-form-item label="用户名" prop="username">
-          <lay-input v-model="params.username" />
+      <lay-form :model="modelParams" ref="layFormRef11" 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="params.organization" type="password" />
+          <lay-input v-model="modelParams.organization" />
         </lay-form-item>
         <lay-form-item label="备注" prop="desc">
-          <lay-textarea placeholder="请输入备注" v-model="params.desc" />
+          <lay-textarea placeholder="请输入备注" v-model="modelParams.desc" />
         </lay-form-item>
       </lay-form>
     </div>
@@ -17,21 +20,26 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive } from "vue";
+import { ref, reactive, defineExpose } from "vue";
 interface ModelInfo {
+  title: string;
   visible: boolean;
   isUpdate: boolean;
 }
 interface ModelParams {
-  username?: string;
+  name?: string;
+  account?: string;
   organization?: string;
   desc?: string;
 }
-const modelParams: ModelParams = reactive({});
-const modeInfo: ModelInfo = ref({ visible: false, isUpdate: false });
+let modelParams: ModelParams = reactive({});
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
 
-const show = (params: ModelParams) => {
-  modeInfo.visible = true;
+const show = (params?: ModelParams) => {
+  modelInfo.visible = true;
+  modelInfo.isUpdate = !!params;
+  modelInfo.title = modelInfo.isUpdate ? "编辑用户" : "添加用户";
+  modelParams = modelInfo.isUpdate ? JSON.parse(JSON.stringify(params)) : {};
 };
 const operator = ref([
   {

+ 46 - 14
src/views/system/user/index.vue

@@ -4,17 +4,17 @@
       <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()">添加用户</lay-button>
     </template>
 
     <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-item label="用户名" prop="name">
+            <lay-input v-model="params.name" />
           </lay-form-item>
-          <lay-form-item label="用户名" prop="username">
-            <lay-input v-model="params.username"></lay-input>
+          <lay-form-item label="账号" prop="account">
+            <lay-input v-model="params.account" />
           </lay-form-item>
           <div class="form-button-wp">
             <lay-button>搜索</lay-button>
@@ -22,28 +22,59 @@
         </lay-form>
       </div>
       <div>
-        <lay-table :columns="columns"> </lay-table>
+        <lay-table :columns="columns" :data-source="dataSource">
+          <template v-slot:operator="{ row }">
+            <lay-space>
+              <TableButton text="禁用" />
+              <TableButton text="编辑" @click="handleUpdate(row)" />
+              <TableButton type="danger" text="删除" />
+              <TableButton type="danger" text="重置密码"
+            /></lay-space>
+          </template>
+        </lay-table>
       </div>
     </template>
-    <Update ref="updateRef" />
   </lay-card>
+  <Update ref="updateRef" />
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive } from "vue";
 import Update from "./components/Update.vue";
+import TableButton from "@/components/TableButton.vue";
 
-let updateRef = ref();
+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 updateRef = ref();
 
 interface FormItem {
-  username?: String;
+  name?: String;
+  account?: String;
 }
 const params: FormItem = reactive({});
 
 const columns = ref([
-  { title: "用户名", width: "80px", key: "username", sort: "desc" },
-  { title: "组织", width: "80px", key: "organization", sort: "desc" },
-  { title: "状态", width: "80px", key: "status", sort: "desc" },
+  { 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: "操作",
@@ -54,9 +85,10 @@ const columns = ref([
     ignoreExport: true,
   },
 ]);
+const dataSource = ref(requestData.data.list);
 
-const handleUpdate = () => {
-  updateRef.value.show();
+const handleUpdate = (value?: any) => {
+  updateRef.value.show(value);
 };
 </script>
 

+ 55 - 0
src/views/system/webpage/components/Update.vue

@@ -0,0 +1,55 @@
+<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-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>
+        <lay-form-item label="排序" prop="organization">
+          <lay-input v-model="modelParams.organization" />
+        </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>
+      </lay-form>
+    </div>
+  </lay-layer>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, defineExpose } from "vue";
+interface ModelInfo {
+  title: string;
+  visible: boolean;
+  isUpdate: boolean;
+}
+interface ModelParams {
+  name?: string;
+  account?: string;
+  organization?: string;
+  desc?: string;
+}
+let modelParams: ModelParams = reactive({});
+let modelInfo: ModelInfo = reactive({ title: "", visible: false, isUpdate: false });
+
+const show = (params?: ModelParams) => {
+  modelInfo.visible = true;
+  modelInfo.isUpdate = !!params;
+  modelInfo.title = modelInfo.isUpdate ? "编辑页面" : "添加页面";
+};
+const operator = ref([
+  {
+    text: "确认",
+    callback: () => {},
+  },
+  {
+    text: "取消",
+    callback: () => {},
+  },
+]);
+defineExpose({ show });
+</script>

+ 9 - 1
src/views/system/webpage/index.vue

@@ -4,7 +4,7 @@
       <span class="card-title">页面管理</span>
     </template>
     <template v-slot:extra>
-      <lay-button class="card-button">添加页面</lay-button>
+      <lay-button class="card-button" @click="handleUpdate()">添加页面</lay-button>
     </template>
 
     <template v-slot:body>
@@ -13,10 +13,14 @@
       </div>
     </template>
   </lay-card>
+  <Update ref="updateRef" />
 </template>
 
 <script lang="ts" setup>
 import { ref } from "vue";
+import Update from "./components/Update.vue";
+
+const updateRef = ref();
 
 const columns = ref([
   { title: "页面名称", key: "username", sort: "desc" },
@@ -29,6 +33,10 @@ const columns = ref([
     ignoreExport: true,
   },
 ]);
+
+const handleUpdate = (value?: any) => {
+  updateRef.value.show(value);
+};
 </script>
 
 <style lang="scss" scoped>