فهرست منبع

feat(成员管理页): 完善成员管理页功能

fxs 4 روز پیش
والد
کامیت
4dbaff71ec
3فایلهای تغییر یافته به همراه134 افزوده شده و 41 حذف شده
  1. 1 1
      src/router/memberManage.ts
  2. 3 3
      src/views/IndexView.vue
  3. 130 37
      src/views/MemberManage/MemberTable.vue

+ 1 - 1
src/router/memberManage.ts

@@ -7,7 +7,7 @@ export default [
       {
         path: 'memberTable',
         name: 'MemberTable',
-        icon: 'PieChart',
+        icon: 'Avatar',
         cnName: '成员列表',
         component: () => import('@/views/MemberManage/MemberTable.vue'),
         meta: {

+ 3 - 3
src/views/IndexView.vue

@@ -111,8 +111,8 @@ const changeNavBar = (val: string) => {
 
 // 资源的加载路径
 const resourceInfo: Record<string, string> = {
-  // logo: `/img/logo.svg`,
-  logo: `/img/logoTest.svg`,
+  logo: `/img/logo.svg`,
+  // logo: `/img/logoTest.svg`,
   defaultHead: `/img/default/defaultHead.png`
 }
 
@@ -245,7 +245,7 @@ onMounted(() => {
       <div class="navBarBox">
         <div class="logoBox">
           <el-image :fit="'fill'" class="logoImg" :src="blobUrlInfo.logo"></el-image>
-          <!--          <span class="logoTitle">测试库</span>-->
+          <!--                    <span class="logoTitle">测试库</span>-->
           <span class="logoTitle">淳皓科技</span>
         </div>
 

+ 130 - 37
src/views/MemberManage/MemberTable.vue

@@ -1,8 +1,10 @@
 <script setup lang="ts">
+import CustomTable from '@/components/table/CustomTable.vue'
 import { useRequest } from '@/hooks/useRequest.ts'
 import { useTableStore } from '@/stores/useTable.ts'
 
 import type { ReqConfig } from '@/types/dataAnalysis.ts'
+import type { ResponseInfo } from '@/types/res.ts'
 import {
   FilterType,
   type QueryInfo,
@@ -10,10 +12,21 @@ import {
   type TablePaginationSetting,
   type TableToolsConfig
 } from '@/types/table.ts'
-import { FieldSpecialEffectType, TextType } from '@/types/tableText.ts'
+import { FieldSpecialEffectType } from '@/types/tableText.ts'
+
 import axiosInstance from '@/utils/axios/axiosInstance.ts'
-import { onMounted, ref } from 'vue'
-import { ElMessageBox, ElMessage } from 'element-plus'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { ref } from 'vue'
+
+type CustomTableType = InstanceType<typeof CustomTable>
+
+interface MemberInfo {
+  adminId?: number // 修改ID字段为可选
+  account: string
+  name: string
+  password?: string // 密码变为可选
+  permission: string[] // 权限保持数组类型
+}
 
 // 定义表格配置接口
 interface TableConfig {
@@ -24,24 +37,36 @@ interface TableConfig {
   tableToolsConfig: TableToolsConfig
 }
 
+type GameMap = Map<string, string>
+
 const { AllApi } = useRequest()
 const { allGameInfo } = useTableStore()
+const gameMap: GameMap = new Map(allGameInfo.map((item) => [item.gid, item.gameName]))
+
+const memberTableRef = ref<CustomTableType>()
+
+//  是否为编辑状态
+const isEdit = ref(false)
+
+// 当前是否编辑的是管理员
+const isAdmin = ref(false)
 
 // 控制模态框的显示与隐藏
 const dialogVisible = ref(false)
 // 模态框的标题
 const dialogTitle = ref('')
 // 成员表单数据
-const memberForm = ref({
-  id: '',
+const memberForm = ref<MemberInfo>({
   account: '',
   name: '',
-  password: '',
-  createdAt: '',
-  updatedAt: '',
-  permission: ''
+  password: '', // 新增时不需要传空值
+  permission: []
 })
 
+const getGameName = (gid: string) => {
+  return gameMap.get(gid) || '未知游戏'
+}
+
 // 表格配置
 const tableConfig = ref<TableConfig>({
   requestConfig: {
@@ -77,7 +102,15 @@ const tableConfig = ref<TableConfig>({
       name: 'password',
       cnName: '密码',
       isShow: false, // 默认不展示密码字段,防止泄露
-      needSort: false
+      needSort: false,
+      specialEffect: {
+        type: FieldSpecialEffectType.CUSTOM,
+        otherInfo: {
+          render: () => {
+            return '******'
+          }
+        }
+      }
     },
     {
       name: 'createdAt',
@@ -95,7 +128,18 @@ const tableConfig = ref<TableConfig>({
       name: 'permission',
       cnName: '权限',
       isShow: true,
-      needSort: false
+      needSort: false,
+      specialEffect: {
+        type: FieldSpecialEffectType.CUSTOM,
+        otherInfo: {
+          render: (val: string[]) => {
+            // console.log(val)
+            if (!val || val.length === 0) return '超级管理员'
+            console.log(val)
+            return val.map((item) => getGameName(item)).join(',')
+          }
+        }
+      }
     }
   ],
   queryInfo: [
@@ -121,24 +165,33 @@ const tableConfig = ref<TableConfig>({
 const addNewMember = () => {
   dialogTitle.value = '新增成员'
   memberForm.value = {
-    id: '',
     account: '',
     name: '',
-    password: '',
-    createdAt: '',
-    updatedAt: '',
-    permission: ''
+    password: '', // 新增时密码字段保留为空
+    permission: []
   }
   dialogVisible.value = true
+  isEdit.value = false
 }
-
 /**
  * 编辑成员
  * @param row 成员数据
  */
 const editMember = (row: any) => {
+  isEdit.value = true
   dialogTitle.value = '修改成员'
-  memberForm.value = { ...row }
+
+  console.log(allGameInfo)
+  isAdmin.value = !row.permission
+
+  console.log(isAdmin.value)
+  memberForm.value = {
+    adminId: row.id, // 注意字段映射
+    account: row.account,
+    name: row.name,
+    password: row.password, // 编辑时密码保留为空
+    permission: row.permission || allGameInfo.map((item) => item.gid)
+  }
   dialogVisible.value = true
 }
 
@@ -147,20 +200,35 @@ const editMember = (row: any) => {
  */
 const saveMember = async () => {
   try {
-    let url = AllApi.updateMember
-    if (memberForm.value.id) {
-      // 编辑成员
-      // await AllApi.updateMember(memberForm.value)
-      ElMessage.success('修改成功')
+    let url = AllApi.addMember
+    let msg = '新增成功'
+    let params = { ...memberForm.value }
+
+    console.log(memberForm.value)
+    // 新增和修改的区别处理
+    if (isEdit.value) {
+      // 修改情况
+      url = AllApi.updateMember
+      msg = '修改成功'
     } else {
-      // 新增成员
-      url = AllApi.addMember
-      ElMessage.success('新增成功')
+      // 新增情况
+      delete params.password
+      delete params.adminId // 确保新增时不发送adminId
     }
-    axiosInstance.post(url, memberForm.value)
+
+    const res = (await axiosInstance.post(url, params)) as ResponseInfo
+
+    if (res.code !== 0) {
+      ElMessage.error(res.msg)
+      return
+    }
+
+    ElMessage.success(msg)
     dialogVisible.value = false
   } catch (error) {
     ElMessage.error('操作失败')
+  } finally {
+    memberTableRef.value?.updateTableData()
   }
 }
 
@@ -169,19 +237,29 @@ const saveMember = async () => {
  * @param row 成员数据
  */
 const delMember = (row: any) => {
+  if (!row.permission) return // 管理员账户禁止删除
   ElMessageBox.confirm('确定要删除该成员吗?', '提示', {
     confirmButtonText: '确定',
     cancelButtonText: '取消',
     type: 'warning'
   })
-    .then(() => {
-      // 这里可以添加删除成员的逻辑
-      console.log('删除成员', row)
+    .then(async () => {
+      // 发送删除请求
+      const res = (await axiosInstance.post(AllApi.deleteMember, {
+        adminId: row.id
+      })) as ResponseInfo
+      if (res.code !== 0) {
+        ElMessage.error(res.msg)
+        return
+      }
       ElMessage.success('删除成功')
     })
     .catch(() => {
       ElMessage.info('已取消删除')
     })
+    .finally(() => {
+      memberTableRef.value?.updateTableData()
+    })
 }
 </script>
 
@@ -189,7 +267,7 @@ const delMember = (row: any) => {
   <div class="memberTableContainer">
     <div class="memberTable">
       <CustomTable
-        ref="memberTable"
+        ref="memberTableRef"
         :request-config="tableConfig.requestConfig"
         :open-page-query="true"
         :pagination-config="tableConfig.pagingConfig"
@@ -204,32 +282,46 @@ const delMember = (row: any) => {
           <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
-              >
+                >修改
+              </el-text>
+              <el-text
+                class="operationBtn"
+                :type="scope.row.permission ? 'danger' : 'info'"
+                @click="delMember(scope.row)"
+                >删除
+              </el-text>
             </template>
           </el-table-column>
         </template>
       </CustomTable>
     </div>
     <!-- 模态框组件 -->
-    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="400px">
+    <el-dialog
+      v-model="dialogVisible"
+      :title="dialogTitle"
+      width="400px"
+      :close-on-click-modal="false"
+    >
       <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="密码" v-if="isEdit">
+          <el-input v-model="memberForm.password" show-password type="password"></el-input>
+        </el-form-item>
         <el-form-item label="权限">
           <el-select
+            placement="bottom"
             v-model="memberForm.permission"
             placeholder="请选择权限"
             multiple
             collapse-tags
             clearable
+            :disabled="isAdmin"
           >
             <el-option
               v-for="item in allGameInfo"
@@ -258,6 +350,7 @@ const delMember = (row: any) => {
   box-sizing: border-box;
   position: relative; /* Keep relative positioning for the absolute positioned handleFileActions */
 }
+
 .functionalContainer {
   width: 100%;
   box-sizing: border-box;