Răsfoiți Sursa

Merge branch 'main' of https://git.cloucl.top/baiyun/smart-reader-vue3

Bsheng123 6 luni în urmă
părinte
comite
1862339cf6

+ 8 - 0
package-lock.json

@@ -8,9 +8,11 @@
       "name": "vue3-admin-ui",
       "name": "vue3-admin-ui",
       "version": "0.0.0",
       "version": "0.0.0",
       "dependencies": {
       "dependencies": {
+        "@element-plus/icons-vue": "^2.3.1",
         "axios": "^1.10.0",
         "axios": "^1.10.0",
         "element-plus": "^2.10.2",
         "element-plus": "^2.10.2",
         "less": "^4.3.0",
         "less": "^4.3.0",
+        "normalize.css": "^8.0.1",
         "pinia": "^2.0.26",
         "pinia": "^2.0.26",
         "vue": "^3.2.45",
         "vue": "^3.2.45",
         "vue-router": "^4.1.6"
         "vue-router": "^4.1.6"
@@ -2275,6 +2277,12 @@
       "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
       "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
       "license": "BSD-3-Clause"
       "license": "BSD-3-Clause"
     },
     },
+    "node_modules/normalize.css": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmmirror.com/normalize.css/-/normalize.css-8.0.1.tgz",
+      "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==",
+      "license": "MIT"
+    },
     "node_modules/nth-check": {
     "node_modules/nth-check": {
       "version": "2.1.1",
       "version": "2.1.1",
       "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
       "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",

+ 2 - 0
package.json

@@ -9,9 +9,11 @@
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
   },
   },
   "dependencies": {
   "dependencies": {
+    "@element-plus/icons-vue": "^2.3.1",
     "axios": "^1.10.0",
     "axios": "^1.10.0",
     "element-plus": "^2.10.2",
     "element-plus": "^2.10.2",
     "less": "^4.3.0",
     "less": "^4.3.0",
+    "normalize.css": "^8.0.1",
     "pinia": "^2.0.26",
     "pinia": "^2.0.26",
     "vue": "^3.2.45",
     "vue": "^3.2.45",
     "vue-router": "^4.1.6"
     "vue-router": "^4.1.6"

+ 11 - 0
src/App.vue

@@ -0,0 +1,11 @@
+<script setup>
+import Layout from '@/layouts/index.vue'
+</script>
+
+<template>
+  <router-view></router-view>
+</template>
+
+<style lang="less" scoped>
+// 保持原有样式
+</style>

+ 44 - 1
src/api/system/user/index.js

@@ -43,4 +43,47 @@ export function getInfo(val) {
  method: 'get',
  method: 'get',
  params: {}
  params: {}
  })
  })
-}
+}
+  return service.request({
+    url: "/api/v1/system/userInfo/queryInfo",
+    method: "get",
+    params,
+  });
+export function add(data) {
+  return service.request({
+    url: "/api/v1/system/userInfo/add",
+    method: "post",
+    data,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}
+export function edit(data) {
+  return service.request({
+    url: "/api/v1/system/userInfo/update",
+    method: "put",
+    data,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}
+export function del(params) {
+  return service.request({
+    url: "/api/v1/system/userInfo/delete/" + params,
+    method: "delete",
+    params: {},
+  });
+}
+export function batchDelete(params) {
+  return service.request({
+    url: "/api/v1/system/userInfo/batchDelete",
+    method: "delete",
+    data: params,
+    headers: { "Content-Type": "application/json;charset=UTF-8" },
+  });
+}
+export function getInfo(val) {
+  return service.request({
+    url: "/api/v1/system/userInfo/detail?userInfoId=" + val,
+    method: "get",
+    params: {},
+  });
+}

+ 0 - 147
src/index.vue

@@ -1,147 +0,0 @@
-<script setup>
-import { Setting } from "@element-plus/icons-vue";
-const handleOpen = (key, keyPath) => {
-  console.log(key, keyPath);
-};
-const handleClose = (key, keyPath) => {
-  console.log(key, keyPath);
-};
-</script>
-<template>
-  <el-container class="app-layout">
-    <el-aside width="200px" class="app-side">
-      <div class="logo">
-        <span>ADMIN UI</span>
-      </div>
-      <el-menu default-active="/home" class="side-menu" @open="handleOpen" @close="handleClose" router>
-        <el-menu-item index="/home">
-          <el-icon>
-            <HomeFilled />
-          </el-icon>
-          <span>⾸⻚</span>
-        </el-menu-item>
-        <el-sub-menu index="/system">
-          <template #title>
-            <el-icon>
-              <setting />
-            </el-icon>
-            <span>系统管理</span>
-          </template>
-          <el-menu-item index="/system/user">
-            <el-icon>
-              <Menu />
-            </el-icon>
-            <span>⽤户管理</span>
-          </el-menu-item>
-          <el-menu-item index="/system/role">
-            <el-icon>
-              <Menu />
-            </el-icon>
-            <span>⻆⾊管理</span>
-          </el-menu-item>
-          <el-menu-item index="/system/permission">
-            <el-icon>
-              <Menu />
-            </el-icon>
-            <span>权限管理</span>
-          </el-menu-item>
-        </el-sub-menu>
-      </el-menu>
-    </el-aside>
-    <el-container class="app-cent-container">
-      <el-header class="app-header">Header</el-header>
-      <el-main class="app-content">
-        <div class="content-wrapper">
-          <router-view></router-view>
-        </div>
-      </el-main>
-    </el-container>
-  </el-container>
-</template>
-<style lang="less" scoped>
-.app-layout {
-  height: 100vh;
-  background-color: #f0f2f5;
-
-  .app-side {
-    background-color: #fff;
-    box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
-    position: relative;
-    z-index: 10;
-
-    .logo {
-      height: 64px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      padding: 0 24px;
-      overflow: hidden;
-
-      span {
-        color: #0c0c0c;
-        font-size: 18px;
-        font-weight: 600;
-        white-space: nowrap;
-      }
-    }
-
-    .side-menu {
-      border-right: none;
-    }
-  }
-
-  .app-cent-container {
-    position: fixed;
-    top: 0;
-    left: 200px;
-    right: 0;
-    bottom: 0;
-    background-color: #f9f9f9;
-
-    .app-header {
-      display: flex;
-      flex-direction: row;
-      justify-content: space-between;
-      height: 64px;
-      background: #fff;
-      padding-left: 16px;
-      padding-right: 16px;
-      line-height: 64px;
-      align-items: center;
-      border-bottom: 1px solid #d8dce5;
-    }
-
-    .app-content {
-      display: flex;
-      flex-direction: column;
-      position: absolute;
-      top: 104px;
-      right: 20px;
-      bottom: 20px;
-      left: 20px;
-      background-color: #fff;
-    }
-  }
-
-  .app-footer {
-    text-align: center;
-    padding: 16px 24px;
-    color: rgba(0, 0, 0, 0.45);
-    font-size: 14px;
-    background: #fff;
-
-    .footer-links {
-      margin-bottom: 8px;
-
-      a {
-        color: rgba(0, 0, 0, 0.45);
-        margin: 0 8px;
-
-        &:hover {
-          color: rgba(0, 0, 0, 0.65);
-        }
-      }
-    }
-  }
-}
-</style>

+ 147 - 0
src/layouts/index.vue

@@ -0,0 +1,147 @@
+<script setup>
+import { Setting } from "@element-plus/icons-vue";
+const handleOpen = (key, keyPath) => {
+  console.log(key, keyPath);
+};
+const handleClose = (key, keyPath) => {
+  console.log(key, keyPath);
+};
+</script>
+<template>
+  <el-container class="app-layout">
+    <el-aside width="200px" class="app-side">
+      <div class="logo">
+        <span>ADMIN UI</span>
+      </div>
+      <el-menu default-active="/home" class="side-menu" @open="handleOpen" @close="handleClose" router>
+        <el-menu-item index="/home">
+          <el-icon>
+            <HomeFilled />
+          </el-icon>
+          <span>⾸⻚</span>
+        </el-menu-item>
+        <el-sub-menu index="/system">
+          <template #title>
+            <el-icon>
+              <setting />
+            </el-icon>
+            <span>系统管理</span>
+          </template>
+          <el-menu-item index="/system/user">
+            <el-icon>
+              <Menu />
+            </el-icon>
+            <span>⽤户管理</span>
+          </el-menu-item>
+          <el-menu-item index="/system/role">
+            <el-icon>
+              <Menu />
+            </el-icon>
+            <span>⻆⾊管理</span>
+          </el-menu-item>
+          <el-menu-item index="/system/permission">
+            <el-icon>
+              <Menu />
+            </el-icon>
+            <span>权限管理</span>
+          </el-menu-item>
+        </el-sub-menu>
+      </el-menu>
+    </el-aside>
+    <el-container class="app-cent-container">
+      <el-header class="app-header">Header</el-header>
+      <el-main class="app-content">
+        <div class="content-wrapper">
+          <router-view></router-view>
+        </div>
+      </el-main>
+    </el-container>
+  </el-container>
+</template>
+<style lang="less" scoped>
+.app-layout {
+  height: 100vh;
+  background-color: #f0f2f5;
+
+  .app-side {
+    background-color: #fff;
+    box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
+    position: relative;
+    z-index: 10;
+
+    .logo {
+      height: 64px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      padding: 0 24px;
+      overflow: hidden;
+
+      span {
+        color: #0c0c0c;
+        font-size: 18px;
+        font-weight: 600;
+        white-space: nowrap;
+      }
+    }
+
+    .side-menu {
+      border-right: none;
+    }
+  }
+
+  .app-cent-container {
+    position: fixed;
+    top: 0;
+    left: 200px;
+    right: 0;
+    bottom: 0;
+    background-color: #f9f9f9;
+
+    .app-header {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      height: 64px;
+      background: #fff;
+      padding-left: 16px;
+      padding-right: 16px;
+      line-height: 64px;
+      align-items: center;
+      border-bottom: 1px solid #d8dce5;
+    }
+
+    .app-content {
+      display: flex;
+      flex-direction: column;
+      position: absolute;
+      top: 104px;
+      right: 20px;
+      bottom: 20px;
+      left: 20px;
+      background-color: #fff;
+    }
+  }
+
+  .app-footer {
+    text-align: center;
+    padding: 16px 24px;
+    color: rgba(0, 0, 0, 0.45);
+    font-size: 14px;
+    background: #fff;
+
+    .footer-links {
+      margin-bottom: 8px;
+
+      a {
+        color: rgba(0, 0, 0, 0.45);
+        margin: 0 8px;
+
+        &:hover {
+          color: rgba(0, 0, 0, 0.65);
+        }
+      }
+    }
+  }
+}
+</style>

+ 6 - 3
src/main.js

@@ -1,17 +1,20 @@
 import { createApp } from 'vue'
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'
 import { createPinia } from 'pinia'
 
 
-import App from './Index.vue'
+import App from './App.vue'
 import router from './router'
 import router from './router'
 
 
 import ElementPlus from 'element-plus'
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
 import 'element-plus/dist/index.css'
-
+import 'normalize.css'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 
 
 const app = createApp(App)
 const app = createApp(App)
 
 
 app.use(createPinia())
 app.use(createPinia())
 app.use(router)
 app.use(router)
 app.use(ElementPlus)
 app.use(ElementPlus)
-
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+ app.component(key, component)
+}
 app.mount('#app')
 app.mount('#app')

+ 37 - 5
src/router/index.js

@@ -1,14 +1,46 @@
 import { createRouter, createWebHistory } from 'vue-router'
 import { createRouter, createWebHistory } from 'vue-router'
-import HomeView from '../views/HomeView.vue'
 
 
 const router = createRouter({
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: [
   routes: [
     {
     {
-      path: '/home',
-      name: 'home',
-      component: HomeView
-    }
+      path: '/',
+      name: 'layout',
+      component: () => import('../layouts/index.vue'),
+      redirect: '/home',
+      children: [
+        {
+          path: '/home',
+          name: 'home',
+          component: () => import('../views/home/index.vue')
+        },
+        {
+          path: '/system',
+          name: 'system',
+          component: () => import('../views/system/index.vue'),
+          redirect: '/system/user',
+          children: [
+            {
+              path: 'user',
+              name: 'user',
+              component: () => import('../views/system/user/index.vue')
+            },
+            {
+              path: 'role',
+              name: 'srole',
+              component: () => import('../views/system/role/index.vue')
+            },
+            {
+              path: 'permission',
+              name: 'permission',
+              component: () => import('../views/system/permission/index.vue')
+            },
+          ]
+        },
+      ]
+    },
+    
+
   ]
   ]
 })
 })
 
 

+ 0 - 12
src/stores/counter.js

@@ -1,12 +0,0 @@
-import { ref, computed } from 'vue'
-import { defineStore } from 'pinia'
-
-export const useCounterStore = defineStore('counter', () => {
-  const count = ref(0)
-  const doubleCount = computed(() => count.value * 2)
-  function increment() {
-    count.value++
-  }
-
-  return { count, doubleCount, increment }
-})

+ 0 - 0
src/stores/system/index.js


+ 78 - 77
src/stores/system/user/index.js

@@ -1,82 +1,83 @@
 import { defineStore } from "pinia";
 import { defineStore } from "pinia";
 import { queryInfo, add, edit, del, batchDelete } from "@/api/system/user/index";
 import { queryInfo, add, edit, del, batchDelete } from "@/api/system/user/index";
 import { ElMessage } from 'element-plus';
 import { ElMessage } from 'element-plus';
+
 export const useUserStore = defineStore("user", {
 export const useUserStore = defineStore("user", {
- state: () => ({
- tableData: [],
- total: 0,
- pageNum: 1,
- pageSize: 10,
- loading: false,
- dialogFormVisible: false,
- }),
- actions: {
- async queryData(params) {
- this.loading = true;
- try {
- const { data } = await queryInfo(params);
- this.tableData = data.list;
- this.total = data.total;
- } finally {
- this.loading = false;
- }
- },
- addUser(data) {
- return new Promise((resolve, reject) => {
- add(data)
- .then(({ code }) => {
- if (code === 200) {
- ElMessage.success('⽤户添加成功');
- this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
- resolve();
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- },
- editUser(data) {
- return new Promise((resolve, reject) => {
- edit(data)
- .then(() => {
- this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
-resolve();
- })
- .catch(error => {
- reject(error);
- });
- });
- },
- deleteUser(params) {
- return new Promise((resolve, reject) => {
- del(params)
- .then(({ code }) => {
- if (code==200){
- ElMessage.success('批量删除成功');
- this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
- }
- resolve();
- })
- .catch(error => {
- reject(error);
- });
- });
- },
- batchDeleteUser(params) {
- return new Promise((resolve, reject) => {
- batchDelete(params)
- .then(({ code }) => {
- if (code==200){
- ElMessage.success('批量删除成功');
- this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
- }
- resolve();
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- },
+  state: () => ({
+    tableData: [],
+    total: 0,
+    pageNum: 1,
+    pageSize: 10,
+    loading: false,
+    dialogFormVisible: false,
+  }),
+  actions: {
+    async queryData(params) {
+      this.loading = true;
+      try {
+        const { data } = await queryInfo(params);
+        this.tableData = data.list;
+        this.total = data.total;
+      } finally {
+        this.loading = false;
+      }
+    },
+    addUser(data) {
+      return new Promise((resolve, reject) => {
+        add(data)
+          .then(({ code }) => {
+            if (code === 200) {
+              ElMessage.success("用户添加成功");
+              this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
+              resolve();
+            }
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    editUser(data) {
+      return new Promise((resolve, reject) => {
+        edit(data)
+          .then(() => {
+            this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    deleteUser(params) {
+      return new Promise((resolve, reject) => {
+        del(params)
+          .then(({ code }) => {
+            if (code == 200) {
+              ElMessage.success("批量删除成功");
+              this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
+            }
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+    batchDeleteUser(params) {
+      return new Promise((resolve, reject) => {
+        batchDelete(params)
+          .then(({ code }) => {
+            if (code == 200) {
+              ElMessage.success("批量删除成功");
+              this.queryData({ pageNum: this.pageNum, pageSize: this.pageSize });
+            }
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+  },
 });
 });

+ 0 - 20
src/views/HomeView.vue

@@ -1,20 +0,0 @@
-<template>
-  <div class="home">
-    <h1>欢迎使用管理系统</h1>
-    <p>这是您的首页内容区域</p>
-  </div>
-</template>
-
-<script setup>
-// 这里可以添加首页需要的业务逻辑
-</script>
-
-<style scoped>
-.home {
-  padding: 20px;
-  font-size: 16px;
-}
-h1 {
-  color: #1890ff;
-}
-</style>

+ 5 - 5
src/views/home/index.vue

@@ -14,11 +14,11 @@ const handleClose = (key, keyPath) => {
         <span>ADMIN UI</span>
         <span>ADMIN UI</span>
       </div>
       </div>
       <el-menu
       <el-menu
-          default-active="/home"
-          class="side-menu"
-          @open="handleOpen"
-          @close="handleClose"
-          router
+        default-active="/home"
+        class="side-menu"
+        @open="handleOpen"
+        @close="handleClose"
+        router
       >
       >
         <el-menu-item index="/home">
         <el-menu-item index="/home">
           <el-icon><HomeFilled /></el-icon>
           <el-icon><HomeFilled /></el-icon>

+ 31 - 38
src/views/system/index.vue

@@ -1,45 +1,43 @@
 <script setup>
 <script setup>
-import { onMounted, ref } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import { useUserStore } from "@/stores/system/user";
-import { storeToRefs } from "pinia";
-
+import { onMounted, ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useUserStore } from '@/stores/system/user';
+import { storeToRefs } from 'pinia';
 const userStore = useUserStore();
 const userStore = useUserStore();
 const { tableData, total, pageNum, pageSize } = storeToRefs(userStore);
 const { tableData, total, pageNum, pageSize } = storeToRefs(userStore);
 // 选中的⽤户ID数组
 // 选中的⽤户ID数组
 const selectedUserIds = ref([]);
 const selectedUserIds = ref([]);
-const queryFunction = function() {
-  userStore.queryData({
-    pageNum: pageNum.value, pageSize: pageSize.value
+const queryFunction = function () {
+  userStore.queryData({ pageNum: pageNum.value, pageSize: pageSize.value
   });
   });
-};
+}
 const userAddFrom = ref({
 const userAddFrom = ref({
-  userName: "",
-  password: "",
-  fullName: "",
-  phoneNumber: "",
-  avatarAddress: ""
+  userName: '',
+  password: '',
+  fullName: '',
+  phoneNumber: '',
+  avatarAddress: ''
 });
 });
 const userAddFromRules = {
 const userAddFromRules = {
-  userName: [{ required: true, message: "请输⼊⽤户名", trigger: "blur" }],
-  password: [{ required: true, message: "请输⼊密码", trigger: "blur" }],
-  fullName: [{ required: true, message: "请输⼊姓名", trigger: "blur" }]
+  userName: [{ required: true, message: '请输⼊⽤户名', trigger: 'blur' }],
+  password: [{ required: true, message: '请输⼊密码', trigger: 'blur' }],
+  fullName: [{ required: true, message: '请输⼊姓名', trigger: 'blur' }]
 };
 };
 // 创建表单引⽤
 // 创建表单引⽤
 const userAddFromRef = ref();
 const userAddFromRef = ref();
 onMounted(() => {
 onMounted(() => {
   queryFunction();
   queryFunction();
-});
-const handleSizeChange = function(val) {
+})
+const handleSizeChange = function (val) {
   userStore.pageSize = val;
   userStore.pageSize = val;
   queryFunction();
   queryFunction();
-};
-const handleCurrentChange = function(val) {
+}
+const handleCurrentChange = function (val) {
   userStore.pageNum = val;
   userStore.pageNum = val;
   queryFunction();
   queryFunction();
-};
+}
 const handleAdd = async () => {
 const handleAdd = async () => {
-  if (!userAddFromRef.value) return;
+  if (!userAddFromRef.value) return
   try {
   try {
     // 这⾥可以打开添加⽤户对话框,并传递userAddFrom数据
     // 这⾥可以打开添加⽤户对话框,并传递userAddFrom数据
     const valid = await userAddFromRef.value.validate();
     const valid = await userAddFromRef.value.validate();
@@ -50,7 +48,7 @@ const handleAdd = async () => {
   } catch (error) {
   } catch (error) {
     // console.error('添加⽤户失败:', error);
     // console.error('添加⽤户失败:', error);
     // 可以显示错误提示给⽤户,例如使⽤ElMessage
     // 可以显示错误提示给⽤户,例如使⽤ElMessage
-    ElMessage.error("添加⽤户失败,请重试");
+    ElMessage.error('添加⽤户失败,请重试');
   }
   }
 };
 };
 const handleEdit = (row) => {
 const handleEdit = (row) => {
@@ -64,10 +62,10 @@ const handleSelectionChange = (rows) => {
 };
 };
 const handleDelete = (row) => {
 const handleDelete = (row) => {
   // 使⽤Element Plus的MessageBox组件实现确认对话框
   // 使⽤Element Plus的MessageBox组件实现确认对话框
-  ElMessageBox.confirm("确定要删除这个⽤户吗?", "提示", {
-    confirmButtonText: "确定",
-    cancelButtonText: "取消",
-    type: "warning"
+  ElMessageBox.confirm('确定要删除这个⽤户吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
   }).then(() => {
   }).then(() => {
     userStore.deleteUser(row.id);
     userStore.deleteUser(row.id);
   }).catch(() => {
   }).catch(() => {
@@ -77,13 +75,13 @@ const handleDelete = (row) => {
 // 批量删除选中的⽤户
 // 批量删除选中的⽤户
 const handleBatchDelete = () => {
 const handleBatchDelete = () => {
   if (selectedUserIds.value.length === 0) {
   if (selectedUserIds.value.length === 0) {
-    ElMessage.warning("请⾄少选择⼀条记录进⾏删除");
+    ElMessage.warning('请⾄少选择⼀条记录进⾏删除');
     return;
     return;
   }
   }
-  ElMessageBox.confirm("确定要批量删除选中的⽤户吗?", "提示", {
-    confirmButtonText: "确定",
-    cancelButtonText: "取消",
-    type: "warning"
+  ElMessageBox.confirm('确定要批量删除选中的⽤户吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
   }).then(() => {
   }).then(() => {
     userStore.batchDeleteUser(selectedUserIds.value);
     userStore.batchDeleteUser(selectedUserIds.value);
   }).catch(() => {
   }).catch(() => {
@@ -208,27 +206,22 @@ dit(row)">
   flex-direction: column;
   flex-direction: column;
   flex: 1;
   flex: 1;
   overflow: hidden;
   overflow: hidden;
-
   .search-from {
   .search-from {
     padding-top: 20px;
     padding-top: 20px;
   }
   }
-
   .operate-buttons {
   .operate-buttons {
     height: 54px;
     height: 54px;
     line-height: 54px;
     line-height: 54px;
   }
   }
-
   .data-table {
   .data-table {
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
     flex: 1;
     flex: 1;
     overflow: hidden;
     overflow: hidden;
-
     .table-container {
     .table-container {
       flex: 1;
       flex: 1;
       overflow: hidden;
       overflow: hidden;
     }
     }
-
     .pagination-container {
     .pagination-container {
       height: 70px;
       height: 70px;
       display: flex;
       display: flex;

+ 20 - 0
src/views/system/permission/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div class="home">
+    <h1>欢迎使用管理系统</h1>
+    <p>这是您的首页内容区域</p>
+  </div>
+</template>
+
+<script setup>
+// 这里可以添加首页需要的业务逻辑
+</script>
+
+<style scoped>
+.home {
+  padding: 20px;
+  font-size: 16px;
+}
+h1 {
+  color: #1890ff;
+}
+</style>

+ 20 - 0
src/views/system/role/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div class="home">
+    <h1>欢迎使用管理系统</h1>
+    <p>这是您的首页内容区域</p>
+  </div>
+</template>
+
+<script setup>
+// 这里可以添加首页需要的业务逻辑
+</script>
+
+<style scoped>
+.home {
+  padding: 20px;
+  font-size: 16px;
+}
+h1 {
+  color: #1890ff;
+}
+</style>

+ 209 - 0
src/views/system/user/index.vue

@@ -0,0 +1,209 @@
+<script setup>
+import { onMounted, ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useUserStore } from '@/stores/system/user';
+import { storeToRefs } from 'pinia';
+const userStore = useUserStore();
+const { tableData, total, pageNum, pageSize } = storeToRefs(userStore);
+// 选中的⽤户ID数组
+const selectedUserIds = ref([]);
+const queryFunction = function () {
+  userStore.queryData({
+    pageNum: pageNum.value, pageSize: pageSize.value
+  });
+}
+const userAddFrom = ref({
+  userName: '',
+  password: '',
+  fullName: '',
+  phoneNumber: '',
+  avatarAddress: ''
+});
+const userAddFromRules = {
+  userName: [{ required: true, message: '请输⼊⽤户名', trigger: 'blur' }],
+  password: [{ required: true, message: '请输⼊密码', trigger: 'blur' }],
+  fullName: [{ required: true, message: '请输⼊姓名', trigger: 'blur' }]
+};
+// 创建表单引⽤
+const userAddFromRef = ref();
+onMounted(() => {
+  queryFunction();
+})
+const handleSizeChange = function (val) {
+  userStore.pageSize = val;
+  queryFunction();
+}
+const handleCurrentChange = function (val) {
+  userStore.pageNum = val;
+  queryFunction();
+}
+const handleAdd = async () => {
+  if (!userAddFromRef.value) return
+  try {
+    // 这⾥可以打开添加⽤户对话框,并传递userAddFrom数据
+    const valid = await userAddFromRef.value.validate();
+    if (valid) {
+      userStore.addUser(userAddFrom.value);
+      userStore.dialogFormVisible = false;
+    }
+  } catch (error) {
+    // console.error('添加⽤户失败:', error);
+    // 可以显示错误提示给⽤户,例如使⽤ElMessage
+    ElMessage.error('添加⽤户失败,请重试');
+  }
+};
+const handleEdit = (row) => {
+  // 这⾥可以打开编辑⽤户对话框,并传递row数据
+  userStore.editUser(row);
+};
+// 当前选中的⾏
+const handleSelectionChange = (rows) => {
+  // 获取选中⾏的ID
+  selectedUserIds.value = rows.map(row => row.id);
+};
+const handleDelete = (row) => {
+  // 使⽤Element Plus的MessageBox组件实现确认对话框
+  ElMessageBox.confirm('确定要删除这个⽤户吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    userStore.deleteUser(row.id);
+  }).catch(() => {
+    // ⽤户点击取消时的处理
+  });
+};
+// 批量删除选中的⽤户
+const handleBatchDelete = () => {
+  if (selectedUserIds.value.length === 0) {
+    ElMessage.warning('请⾄少选择⼀条记录进⾏删除');
+    return;
+  }
+  ElMessageBox.confirm('确定要批量删除选中的⽤户吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    userStore.batchDeleteUser(selectedUserIds.value);
+  }).catch(() => {
+    // ⽤户点击取消时的处理
+  });
+};
+</script>
+<template>
+  <div class="data-table-container">
+    <div class="search-from">
+      <!-- 搜索表单 -->
+    </div>
+    <div class="operate-buttons">
+      <el-button size="default" type="primary" @click="userStore.dialogFo
+      rmVisible = true">
+        <i class="el-icon-plus el-icon--left"></i>新增
+      </el-button>
+      <el-button size="default" type="danger" @click="handleBatchDelete">
+        <i class="el-icon-delete el-icon--left"></i>批量删除
+      </el-button>
+    </div>
+    <div class="data-table">
+      <div class="table-container">
+        <el-table height="600" border fit stripe :data="tableData" style="width: 100%" max-height="600"
+          v-loading="userStore.loading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading"
+          element-loading-background="rgba(0, 0, 0, 0.1)" @selection-change="handleSelectionChange">
+          <el-table-column type="selection" width="55" />
+          <el-table-column type="index" label="序号" width="55" />
+          <el-table-column prop="userName" label="⽤户名" />
+          <el-table-column prop="fullName" label="姓名" />
+          <el-table-column prop="phoneNumber" label="⼿机号" />
+          <el-table-column label="头像" width="88">
+            <template #default="{ row }">
+              <el-image style="width: 40px; height: 40px" :src="row.avatarAddress" :zoom-rate="1.2" :max-scale="7"
+                :min-scale="0.2" show-progress :initial-index="4" fit="cover" />
+            </template>
+          </el-table-column>
+          <el-table-column prop="createTime" label="创建时间" />
+          <el-table-column fixed="right" label="操作" min-width="80">
+            <template #default="{ row }">
+              <el-button link type="primary" size="small" @click="handleD
+              elete(row)">
+                删除
+              </el-button>
+              <el-button link type="primary" size="small" @click="handleE
+              dit(row)">
+                修改
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pagination-container">
+        <el-pagination :currentPage="pageNum" :page-sizes="[10, 20, 50, 100]" :page-size="pageSize"
+          layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
+          @current-change="handleCurrentChange" />
+      </div>
+    </div>
+  </div>
+  <el-dialog v-model="userStore.dialogFormVisible" title="新增⽤户" width="600" center>
+    <el-form ref="userAddFromRef" :model="userAddFrom" :rules="userAddFromRules">
+      <el-form-item prop="userName">
+        <el-input v-model="userAddFrom.userName" autocomplete="off" place holder="请输⼊⽤户名" />
+      </el-form-item>
+      <el-form-item prop="password">
+        <el-input v-model="userAddFrom.password" type="password" autocomp lete="off" placeholder="请输⼊⽤户名" />
+      </el-form-item>
+      <el-form-item prop="fullName">
+        <el-input v-model="userAddFrom.fullName" autocomplete="off" place holder="请输⼊姓名" />
+      </el-form-item>
+      <el-form-item>
+        <el-input v-model="userAddFrom.phoneNumber" autocomplete="off" pl aceholder="请输⼊⼿机号" />
+      </el-form-item>
+      <el-form-item>
+        <el-input v-model="userAddFrom.avatarAddress" autocomplete="off" placeholder="请上传头像" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="userStore.dialogFormVisible = false">取消</el-button>
+        <el-button type="primary" @click="handleAdd">
+          确定
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+<style scoped lang="less">
+.data-table-container {
+  display: flex;
+  flex-direction: column;
+  flex: 1;
+  overflow: hidden;
+
+  .search-from {
+    padding-top: 20px;
+  }
+
+  .operate-buttons {
+    height: 54px;
+    line-height: 54px;
+  }
+
+  .data-table {
+    display: flex;
+    flex-direction: column;
+    flex: 1;
+    overflow: hidden;
+
+    .table-container {
+      flex: 1;
+      overflow: hidden;
+    }
+
+    .pagination-container {
+      height: 70px;
+      display: flex;
+      justify-content: flex-end;
+      align-items: center;
+      margin-right: 24px;
+    }
+  }
+}
+</style>