Quellcode durchsuchen

feat(成员管理): 新增成员管理页

fxs vor 5 Tagen
Ursprung
Commit
412e8eafd8

+ 4 - 4
.env

@@ -1,10 +1,10 @@
 # 开发
-VITE_API_URL_DEV="http://192.168.1.139:8000"
+#VITE_API_URL_DEV="http://192.168.1.139:8000"
 #VITE_API_URL_DEV='http://server.ichunhao.cn'
-#VITE_API_URL_DEV="http://service.ichunhao.cn"
+VITE_API_URL_DEV="http://service.ichunhao.cn"
 # 测试服和本地开发
 #VITE_API_URL_TEST='http://server.ichunhao.cn'
-VITE_API_URL_TEST="http://192.168.1.139:8000"
-#VITE_API_URL_TEST="http://service.ichunhao.cn"
+#VITE_API_URL_TEST="http://192.168.1.139:8000"
+VITE_API_URL_TEST="http://service.ichunhao.cn"
 # 线上
 VITE_API_URL_PRODUCT='http://service.ichunhao.cn'

+ 7 - 1
src/hooks/useRequest.ts

@@ -79,7 +79,13 @@ export function useRequest() {
     fileUploadToServer: `/upload`, // 上传到服务器
     fileUploadToTencent: `/file/localFileToService`, // 上传到腾讯云
     fileManageDeleteFile: `/file/fileDelete`, // 删除文件
-    makeDir: `/file/createDir` // 新建文件夹
+    makeDir: `/file/createDir`, // 新建文件夹
+
+    // 成员管理
+    memberList: `/admin/adminList`, // 成员列表
+    addMember: `/admin/setAdmin`, // 新增成员
+    updateMember: `/admin/updateAdmin`, // 修改成员信息
+    deleteMember: `/admin/deleteAdmin` // 删除成员
   }
 
   /**

+ 3 - 2
src/router/index.ts

@@ -8,12 +8,13 @@
  */
 import { createRouter, createWebHashHistory } from 'vue-router'
 
-import { authLogin } from '@/utils/axios/auth'
+import { authLogin } from '@/utils/auth/auth.ts'
 
 import HomeRoutes from './home'
 import LoginRoutes from './login'
 import AppManage from './appManage'
 import FileManage from './fileManage.ts'
+import MemberManage from './memberManage'
 
 const routes = [
   ...LoginRoutes,
@@ -22,7 +23,7 @@ const routes = [
     name: 'Index',
     redirect: '/home/overView',
     component: () => import('@/views/IndexView.vue'),
-    children: [...HomeRoutes, ...AppManage, ...FileManage]
+    children: [...HomeRoutes, ...AppManage, ...FileManage, ...MemberManage]
   },
   {
     path: '/',

+ 20 - 0
src/router/memberManage.ts

@@ -0,0 +1,20 @@
+export default [
+  {
+    path: '/memberManage',
+    redirect: '/memberManage/memberTable',
+    name: 'MemberManage',
+    children: [
+      {
+        path: 'memberTable',
+        name: 'MemberTable',
+        icon: 'PieChart',
+        cnName: '成员列表',
+        component: () => import('@/views/MemberManage/MemberTable.vue'),
+        meta: {
+          activeMenu: 'memberTable',
+          needKeepAlive: true
+        }
+      }
+    ]
+  }
+]

+ 3 - 3
src/utils/axios/auth.ts → src/utils/auth/auth.ts

@@ -8,9 +8,9 @@
  *
  */
 
-import {ElMessage} from 'element-plus'
-import {MessageType} from '@/types/res'
-import {getLoginState} from '../localStorage/localStorage'
+import { ElMessage } from 'element-plus'
+import { MessageType } from '@/types/res.ts'
+import { getLoginState } from '../localStorage/localStorage.ts'
 
 export const authLogin = (): boolean => {
   const state = getLoginState()

+ 4 - 0
src/utils/auth/permissionAuth.ts

@@ -0,0 +1,4 @@
+// // 根据传入的用户信息,判断用户是否有对应权限
+// export function checkUserPermission(userInfo: any, permission: string): boolean {
+//   return permissionAuth(userInfo, permission)
+// }

+ 65 - 6
src/views/FileManage/FileList.vue

@@ -470,6 +470,7 @@ onMounted(async () => {
           @close="handleClose"
           class="make-dir-dialog"
           :close-on-click-modal="false"
+          :style="{ width: '400px' }"
         >
           <el-form
             :model="makeDirDialogConfig.formData"
@@ -478,21 +479,21 @@ onMounted(async () => {
             label-position="left"
             class="make-dir-form-row"
             ref="makeDirForm"
+            :style="{ padding: '20px' }"
           >
             <el-form-item label="文件夹名称" prop="name" class="make-dir-form-item">
               <el-input
                 v-model="makeDirDialogConfig.formData.name"
                 placeholder="请输入文件夹名称"
                 class="make-dir-input"
+                :style="{ width: '240px' }"
               />
             </el-form-item>
           </el-form>
 
           <template #footer>
-            <div class="make-dir-footer">
-              <el-button class="make-dir-btn confirm" type="primary" @click="handleCreate"
-                >确定</el-button
-              >
+            <div class="make-dir-footer" :style="{ textAlign: 'right', padding: '10px 20px' }">
+              <el-button class="make-dir-btn confirm" type="primary" @click="handleCreate">确定</el-button>
               <el-button class="make-dir-btn cancel" @click="handleClose">取消</el-button>
             </div>
           </template>
@@ -534,7 +535,6 @@ onMounted(async () => {
   min-width: 80px;
   height: 28px;
   margin-right: 16px;
-  /*border: 1px solid #197afb;*/
   border-radius: 3px;
   font-size: 12px;
   font-weight: 500;
@@ -604,7 +604,66 @@ onMounted(async () => {
 }
 
 /* 创建文件夹表单 */
+.make-dir-dialog {
+  border-radius: 12px; /* 增加圆角边框 */
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); /* 增强阴影效果 */
+}
+
+.make-dir-dialog .el-dialog__header {
+  padding: 20px 24px; /* 增加头部内边距 */
+  border-bottom: 1px solid #ebeef5; /* 添加底部边框 */
+  background-color: #f8f9fa; /* 添加背景色 */
+}
+
+.make-dir-dialog .el-dialog__title {
+  font-size: 18px; /* 增加字体大小 */
+  font-weight: bold; /* 加粗标题 */
+  color: #303133; /* 调整标题颜色 */
+}
+
+.make-dir-form-row {
+  padding: 24px; /* 增加表单内边距 */
+}
+
+.make-dir-form-item {
+  margin-bottom: 20px; /* 增加表单项之间的间距 */
+}
+
+.make-dir-input {
+  border: 1px solid #dcdfe6; /* 输入框默认边框颜色 */
+  border-radius: 6px; /* 增加圆角边框 */
+  transition: border-color 0.3s; /* 边框颜色过渡效果 */
+}
+
+.make-dir-input:focus {
+  border-color: #409eff; /* 聚焦时边框颜色 */
+}
+
+.make-dir-footer {
+  padding: 16px 24px; /* 增加底部内边距 */
+  background-color: #f8f9fa; /* 添加背景色 */
+  border-top: 1px solid #ebeef5; /* 添加顶部边框 */
+}
+
 .make-dir-btn {
-  margin-right: 10px;
+  min-width: 100px; /* 增加按钮最小宽度 */
+  height: 40px; /* 增加按钮高度 */
+  margin-right: 12px; /* 增加按钮间距 */
+  border-radius: 6px; /* 增加圆角按钮 */
+  font-size: 14px; /* 增加字体大小 */
+}
+
+.make-dir-btn.confirm {
+  background-color: #409eff; /* 确认按钮背景色 */
+  color: white; /* 确认按钮文字颜色 */
+}
+
+.make-dir-btn.cancel {
+  background-color: #f5f7fa; /* 取消按钮背景色 */
+  color: #909399; /* 取消按钮文字颜色 */
+}
+
+.make-dir-btn:hover {
+  opacity: 0.9; /* 按钮悬停时的透明度 */
 }
 </style>

+ 5 - 1
src/views/IndexView.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:06:49
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-12-07
+ * @LastEditTime: 2025-06-03
  * @Description: 
  * 
 -->
@@ -52,6 +52,10 @@ const navBarMenuList = [
   {
     name: 'FileManage',
     title: '文件管理'
+  },
+  {
+    name: 'MemberManage',
+    title: '成员管理'
   }
 ]
 

+ 312 - 0
src/views/MemberManage/MemberTable.vue

@@ -0,0 +1,312 @@
+<script setup lang="ts">
+import { useRequest } from '@/hooks/useRequest.ts'
+import { useTableStore } from '@/stores/useTable.ts'
+
+import type { ReqConfig } from '@/types/dataAnalysis.ts'
+import {
+  FilterType,
+  type QueryInfo,
+  type TableFieldInfo,
+  type TablePaginationSetting,
+  type TableToolsConfig
+} from '@/types/table.ts'
+import { FieldSpecialEffectType, TextType } from '@/types/tableText.ts'
+import axiosInstance from '@/utils/axios/axiosInstance.ts'
+import { onMounted, ref } from 'vue'
+import { ElMessageBox, ElMessage } from 'element-plus'
+
+// 定义表格配置接口
+interface TableConfig {
+  requestConfig: ReqConfig
+  pagingConfig: TablePaginationSetting
+  tableFieldsInfo: Array<TableFieldInfo>
+  queryInfo: Array<QueryInfo>
+  tableToolsConfig: TableToolsConfig
+}
+
+const { AllApi } = useRequest()
+const { allGameInfo } = useTableStore()
+
+// 控制模态框的显示与隐藏
+const dialogVisible = ref(false)
+// 模态框的标题
+const dialogTitle = ref('')
+// 成员表单数据
+const memberForm = ref({
+  id: '',
+  account: '',
+  name: '',
+  password: '',
+  createdAt: '',
+  updatedAt: '',
+  permission: ''
+})
+
+// 表格配置
+const tableConfig = ref<TableConfig>({
+  requestConfig: {
+    url: AllApi.memberList, // 假设这是获取成员列表的接口,可替换为实际路径
+    otherOptions: {}
+  },
+  pagingConfig: {
+    limit: 20,
+    currentPage: 1,
+    total: 0,
+    pageSizeList: [20, 30]
+  },
+  tableFieldsInfo: [
+    {
+      name: 'id',
+      cnName: 'ID',
+      isShow: false,
+      needSort: false
+    },
+    {
+      name: 'account',
+      cnName: '账号',
+      isShow: true,
+      needSort: false
+    },
+    {
+      name: 'name',
+      cnName: '姓名',
+      isShow: true,
+      needSort: false
+    },
+    {
+      name: 'password',
+      cnName: '密码',
+      isShow: false, // 默认不展示密码字段,防止泄露
+      needSort: false
+    },
+    {
+      name: 'createdAt',
+      cnName: '创建时间',
+      isShow: true,
+      needSort: false
+    },
+    {
+      name: 'updatedAt',
+      cnName: '更新时间',
+      isShow: true,
+      needSort: false
+    },
+    {
+      name: 'permission',
+      cnName: '权限',
+      isShow: true,
+      needSort: false
+    }
+  ],
+  queryInfo: [
+    {
+      name: 'search',
+      label: '搜索账号',
+      type: FilterType.INPUT,
+      placeholder: '请输入账号',
+      default: ''
+    }
+  ],
+  tableToolsConfig: {
+    add: true,
+    filterFields: true,
+    refresh: true,
+    download: false
+  }
+})
+
+/**
+ * 新增成员
+ */
+const addNewMember = () => {
+  dialogTitle.value = '新增成员'
+  memberForm.value = {
+    id: '',
+    account: '',
+    name: '',
+    password: '',
+    createdAt: '',
+    updatedAt: '',
+    permission: ''
+  }
+  dialogVisible.value = true
+}
+
+/**
+ * 编辑成员
+ * @param row 成员数据
+ */
+const editMember = (row: any) => {
+  dialogTitle.value = '修改成员'
+  memberForm.value = { ...row }
+  dialogVisible.value = true
+}
+
+/**
+ * 保存成员信息
+ */
+const saveMember = async () => {
+  try {
+    let url = AllApi.updateMember
+    if (memberForm.value.id) {
+      // 编辑成员
+      // await AllApi.updateMember(memberForm.value)
+      ElMessage.success('修改成功')
+    } else {
+      // 新增成员
+      url = AllApi.addMember
+      ElMessage.success('新增成功')
+    }
+    axiosInstance.post(url, memberForm.value)
+    dialogVisible.value = false
+  } catch (error) {
+    ElMessage.error('操作失败')
+  }
+}
+
+/**
+ * 删除成员
+ * @param row 成员数据
+ */
+const delMember = (row: any) => {
+  ElMessageBox.confirm('确定要删除该成员吗?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(() => {
+      // 这里可以添加删除成员的逻辑
+      console.log('删除成员', row)
+      ElMessage.success('删除成功')
+    })
+    .catch(() => {
+      ElMessage.info('已取消删除')
+    })
+}
+</script>
+
+<template>
+  <div class="memberTableContainer">
+    <div class="memberTable">
+      <CustomTable
+        ref="memberTable"
+        :request-config="tableConfig.requestConfig"
+        :open-page-query="true"
+        :pagination-config="tableConfig.pagingConfig"
+        :table-fields-info="tableConfig.tableFieldsInfo"
+        :query-info="tableConfig.queryInfo"
+        :tools="tableConfig.tableToolsConfig"
+        :open-filter-query="true"
+        :open-remote-query="true"
+        @add-new-item="addNewMember"
+      >
+        <template #tableOperation>
+          <el-table-column label="操作" align="center">
+            <template #default="scope">
+              <el-text class="operationBtn" type="primary" @click="editMember(scope.row)"
+                >修改</el-text
+              >
+              <el-text class="operationBtn" type="danger" @click="delMember(scope.row)"
+                >删除</el-text
+              >
+            </template>
+          </el-table-column>
+        </template>
+      </CustomTable>
+    </div>
+    <!-- 模态框组件 -->
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="400px">
+      <el-form :model="memberForm" label-width="100px">
+        <el-form-item label="账号">
+          <el-input v-model="memberForm.account" />
+        </el-form-item>
+        <el-form-item label="姓名">
+          <el-input v-model="memberForm.name" />
+        </el-form-item>
+        <el-form-item label="权限">
+          <el-select
+            v-model="memberForm.permission"
+            placeholder="请选择权限"
+            multiple
+            collapse-tags
+            clearable
+          >
+            <el-option
+              v-for="item in allGameInfo"
+              :key="item.gid"
+              :label="item.gameName"
+              :value="item.gid"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button class="dialogFooterBtn" type="primary" @click="saveMember">确定</el-button>
+          <el-button class="dialogFooterBtn" @click="dialogVisible = false">取消</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<style scoped>
+.memberTableContainer {
+  width: 98%;
+  margin: 1% auto;
+  background-color: white;
+  box-sizing: border-box;
+  position: relative; /* Keep relative positioning for the absolute positioned handleFileActions */
+}
+.functionalContainer {
+  width: 100%;
+  box-sizing: border-box;
+  padding: 0 24px 24px;
+}
+
+.toolBtn {
+  min-width: 80px;
+  height: 28px;
+  margin-right: 16px;
+  border-radius: 3px;
+  font-size: 12px;
+  font-weight: 500;
+  font-family:
+    PingFang SC,
+    Microsoft YaHei UI,
+    Microsoft YaHei,
+    Helvetica Neue,
+    Helvetica,
+    Hiragino Sans GB,
+    Arial,
+    sans-serif;
+}
+
+.operationBtn,
+.dialogFooterBtn {
+  margin-right: 10px;
+}
+
+/* 模态框样式优化 */
+.el-dialog {
+  border-radius: 10px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.el-dialog__header {
+  background-color: #f0f2f5;
+  border-bottom: 1px solid #ebeef5;
+  padding: 15px 20px;
+}
+
+.el-dialog__body {
+  padding: 20px;
+}
+
+.el-dialog__footer {
+  background-color: #f0f2f5;
+  border-top: 1px solid #ebeef5;
+  padding: 15px 20px;
+  text-align: right;
+}
+</style>