Explorar el Código

更新分类查询功能,更新分页查询功能,更新布局

fxs hace 9 meses
padre
commit
83e0d8ee8e

+ 76 - 20
src/components/Table.vue

@@ -2,7 +2,7 @@
 import type { PropsParams, TablePaginationSetting, QueryInfo } from '@/types/table'
 import { FilterType } from '@/types/table'
 
-import { computed, onMounted, reactive, ref } from 'vue'
+import { computed, onMounted, reactive, ref, watch } from 'vue'
 import { useTable } from '@/hooks/useTable'
 
 // 表格工具图标大小
@@ -22,9 +22,6 @@ const queryFormData = reactive<any>({})
 // 一些公用方法
 const { getTableData } = useTable(tableData, props.paginationConfig)
 
-// 查询操作
-const queryTable = () => {}
-
 // 所有类型为input的表单控件信息
 const inputFieldsList = computed(() => {
   return props.queryInfo?.filter((item) => item.type === FilterType.INPUT)
@@ -32,7 +29,12 @@ const inputFieldsList = computed(() => {
 
 // 所有类型为select的表单控件信息
 const selectFieldsList = computed(() => {
-  return props.queryInfo?.filter((item) => item.type === FilterType.SELECT)
+  return props.queryInfo?.filter((item) => {
+    if (item.default) {
+      queryFormData[item.name] = item.default
+    }
+    return item.type === FilterType.SELECT
+  })
 })
 
 // 所有类型为date的表单控件信息
@@ -50,23 +52,68 @@ const handleSizeChange = (val: number) => {
   props.paginationConfig.limit = val
 }
 
+// 获取数据
 const getData = () => {
-  getTableData(props.requestConfig.url, props.requestConfig.other)
+  if (props.openPageQuery) {
+    // 如果开启了分页查询,那么要计算出需要展示的页码位置所对应的偏移量
+    // 同时要将查询的条数改为对应的用户选择的展示条数
+    props.requestConfig.other.offset =
+      (props.paginationConfig.currentPage - 1) * props.paginationConfig.limit
+    props.requestConfig.other.limit = props.paginationConfig.limit
+  }
+
+  // 查询时要根据是否开启分页查询传入对应参数
+  getTableData(props.requestConfig.url, props.requestConfig.other, props.openPageQuery)
+}
+
+// 清空表格数据
+const resetTableData = () => {
+  tableData.splice(0, tableData.length)
+}
+
+// 根据分页大小的切换来更新数据
+// 这里将他赋值,用于根据传入的配置来选择是否开启该监听
+const changePageLimit = watch(
+  () => [props.paginationConfig.limit, props.paginationConfig.currentPage],
+  ([newLimit], [oldLimit]) => {
+    if (newLimit != oldLimit) {
+      // 需要给分页按钮加上:current-page.sync="current_page" 配置,不然不生效
+      // 当改变每页大小时把之前的缓存全部清除,重新开始
+      props.paginationConfig.currentPage = 1
+      resetTableData()
+      getData()
+    } else if (!tableData[props.paginationConfig.currentPage]) {
+      // 当对应的数组下标位置没有这页的数据的时候再去请求
+      getData()
+    }
+  },
+  { deep: true }
+)
+
+// 按条件查询
+const queryTableData = () => {
+  props.requestConfig.other = { ...props.requestConfig.other, ...queryFormData }
+  getData()
 }
 
+// 没有开启分页查询就关闭掉这个监听
+if (!props.openPageQuery) changePageLimit()
+
 // 定义暴露出去的方法
 defineExpose({
-  getData
+  getData,
+  resetTableData
 })
 
 onMounted(() => {
   getData()
+  console.log(selectFieldsList)
 })
 </script>
 
 <template>
   <div class="tableContent">
-    <div class="filterBox" v-if="isOpenQuery">
+    <div class="filterBox" v-if="openFilterQuery">
       <!-- slot -->
       <div class="filterHeader">
         <span>查询条件</span>
@@ -87,7 +134,7 @@ onMounted(() => {
           <el-form-item :label="item.label" v-for="item in selectFieldsList" class="filterItem">
             <!-- {{ item.placeholder }} -->
             <el-select v-model="queryFormData[item.name]" :placeholder="item.placeholder">
-              <el-option v-for="val in item.otherOption" :label="val.cnName" :value="val.name" />
+              <el-option v-for="val in item.otherOption" :label="val.cnName" :value="val.value" />
             </el-select>
           </el-form-item>
 
@@ -106,7 +153,7 @@ onMounted(() => {
         <div class="queryBox">
           <el-divider class="queryPartition" content-position="center" direction="vertical" />
           <div class="queryBtnBox">
-            <el-button class="queryBtn" color="#165dff">
+            <el-button class="queryBtn" color="#165dff" @click="queryTableData">
               <el-icon><Search /></el-icon>查询
             </el-button>
             <el-button class="refreshBtn" color="#f2f3f5">
@@ -120,7 +167,7 @@ onMounted(() => {
     <el-divider class="partition" content-position="center" />
     <div class="tableTools">
       <div class="leftTools">
-        <el-button type="primary" color="#165dff" @click="emits('addNewItem')">
+        <el-button v-if="needLeftTools" type="primary" color="#165dff" @click="emits('addNewItem')">
           <el-icon><Plus /></el-icon>新增
         </el-button>
       </div>
@@ -134,15 +181,21 @@ onMounted(() => {
     </div>
 
     <div class="tableBox">
-      <el-table :data="tableData" style="width: 100%">
-        <el-table-column label="#" type="index" :index="1" />
+      <el-table
+        :data="openPageQuery ? tableData[paginationConfig.currentPage] : tableData"
+        style="width: 100%"
+        class="tableBody"
+      >
+        <el-table-column align="center" label="#" type="index" :index="1" />
         <el-table-column
           v-for="item in tableFieldsInfo"
           :prop="item.name"
           :label="item.cnName"
           width="auto"
+          align="center"
           show-overflow-tooltip
-        />
+        >
+        </el-table-column>
         <slot name="tableOperation"></slot>
       </el-table>
       <div class="userTablePaginationBox">
@@ -167,8 +220,7 @@ onMounted(() => {
 .tableContent {
   margin: 0 auto;
   width: 98%;
-  height: 98%;
-  border: 1px solid #e5e6eb;
+  /* height: 100%; */
 }
 .filterBox,
 .tableBox {
@@ -192,10 +244,10 @@ onMounted(() => {
   display: flex;
   align-items: center;
   color: black;
-  font-size: 18px;
+  font-size: 20px;
   font-weight: bold;
   /* background-color: lightblue; */
-  margin-bottom: 30px;
+  /* margin-bottom: 1%; */
 }
 
 .filterBody {
@@ -218,6 +270,7 @@ onMounted(() => {
 
 .refreshBtn {
   margin-top: 10%;
+  margin-bottom: 10%;
 }
 
 .queryPartition {
@@ -252,9 +305,10 @@ onMounted(() => {
 
 .leftTools,
 .rightTools {
+  width: 10%;
   display: flex;
   align-items: center;
-  justify-content: space-around;
+  justify-content: space-between;
 }
 
 .rightTools {
@@ -263,8 +317,10 @@ onMounted(() => {
 
 .tableBox {
   width: 98%;
+  /* height: 98%; */
   margin: 0 auto;
-  margin-top: 0.5%;
+  /* margin-top: 0.5%;
+  margin-bottom: 2%; */
 }
 
 .userTablePaginationBox {

+ 15 - 6
src/hooks/useTable.ts

@@ -1,26 +1,35 @@
 import axiosInstance from '../utils/axios/axiosInstance'
 import { useRequest } from './useRequest'
+
 import type { TablePaginationSetting, DialogSetting } from '@/types/table'
 import { type FormInstance } from 'element-plus'
 
 export function useTable(tableData: Array<any>, paginationSetting: TablePaginationSetting) {
-  const { AllApi, analysisResCode } = useRequest()
+  const { analysisResCode } = useRequest()
 
   const getTableData = (url: string, option: any, isPagination: boolean = false) => {
-    return new Promise(async (reslove, reject) => {
+    return new Promise(async (reslove) => {
       try {
-        console.log(url, option)
         await axiosInstance.post(url, option).then((data) => {
           analysisResCode(data)
             .then((info) => {
               let data = info.data
+              // 如果开启了分页,那么默认这个tabledata是一个二维数组,每个位置对应当页的一个数据数组
+              // 没开启则是一个一维数组,直接赋值
               if (isPagination) {
-                tableData[paginationSetting.currentPage] = []
+                tableData[paginationSetting.currentPage] = data
               } else {
                 tableData.splice(0, tableData.length, ...data)
               }
-              console.log(tableData)
-              paginationSetting.total = info.count ? info.count : info.data.length
+
+              // 如果有的接口没有返回count属性,就需要自己写
+              // 这个length,如果数组长为0,则需要自己赋值,不然会报错
+              if (info.count) paginationSetting.total = info.count
+              else if (info.data) {
+                paginationSetting.total = info.data.length
+              } else {
+                paginationSetting.total = 0
+              }
               reslove(true)
             })
             .catch((err) => {

+ 1 - 1
src/router/home.ts

@@ -22,7 +22,7 @@ export default [
         }
       },
       {
-        path: 'playerManageView/:gid?',
+        path: 'playerManageView',
         name: 'PlayerManageView',
         component: PlayerManageView,
         meta: {

+ 0 - 12
src/stores/counter.ts

@@ -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 }
-})

+ 29 - 0
src/stores/useTable.ts

@@ -0,0 +1,29 @@
+import { ref, computed, reactive } from 'vue'
+import { defineStore } from 'pinia'
+
+// 你可以任意命名 `defineStore()` 的返回值,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。
+// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
+// 第一个参数是你的应用中 Store 的唯一 ID。
+interface QueryGameInfo {
+  gid: string
+  gameName: string
+}
+
+export const useTableStore = defineStore('tableStore', () => {
+  // 用户表查询的时候的参数
+  const playerQueryInfo = reactive({
+    gid: '1001',
+    pf: 'web'
+  })
+
+  // 更新用户表查询参数
+  const updateQueryInfo = (newGid: string, newPf: string) => {
+    playerQueryInfo.gid = newGid
+    playerQueryInfo.pf = newPf
+  }
+
+  // 所有的游戏信息
+  const allGameInfo = reactive<Array<QueryGameInfo>>([])
+
+  return { playerQueryInfo, allGameInfo, updateQueryInfo }
+})

+ 9 - 4
src/types/table.ts

@@ -31,6 +31,7 @@ export interface QueryInfo {
   type: FilterType
   placeholder: string
   otherOption?: any
+  default?: any
 }
 
 // 表格字段信息格式
@@ -42,11 +43,14 @@ export interface TableFieldInfo {
 
 // props的参数格式
 export interface PropsParams {
-  isOpenQuery: boolean
-  queryInfo?: Array<QueryInfo>
-  paginationConfig: TablePaginationSetting
-  tableFieldsInfo: Array<TableFieldInfo>
+  needLeftTools: boolean // 是否需要左侧的工具栏
+  openFilterQuery: boolean // 是否开启上方查询功能
+  openPageQuery: boolean // 是否开启分页查询
+  queryInfo?: Array<QueryInfo> // 上方查询功能所需要的信息
+  paginationConfig: TablePaginationSetting // 表格分页的信息
+  tableFieldsInfo: Array<TableFieldInfo> // 表格字段信息
   requestConfig: {
+    // 表格请求的配置
     url: string
     other: any
   }
@@ -56,6 +60,7 @@ export interface PropsParams {
 export interface SelectInfo {
   name: string
   cnName: string
+  value: any
 }
 
 // 对话框设置

+ 24 - 47
src/views/Home/GameManageView.vue

@@ -1,20 +1,16 @@
 <script setup lang="ts">
-import {
-  type TablePaginationSetting,
-  type QueryInfo,
-  FilterType,
-  type SelectInfo,
-  type TableFieldInfo
-} from '@/types/table'
+import { type TablePaginationSetting, type TableFieldInfo } from '@/types/table'
+import type { FormRules, FormInstance } from 'element-plus'
 
 import Table from '@/components/Table.vue'
-import { reactive, ref } from 'vue'
-
-import type { FormRules, FormInstance } from 'element-plus'
+import router from '@/router'
 
+import { reactive, ref } from 'vue'
+import { useTableStore } from '@/stores/useTable'
 import { useRequest } from '@/hooks/useRequest'
 import { useDialog } from '@/hooks/useDialog'
 
+const tableStore = useTableStore()
 const { AllApi } = useRequest()
 const { dialogClose, submitDialog, handleEdit, addNeweItem } = useDialog()
 
@@ -51,39 +47,6 @@ const paginationConfig = reactive<TablePaginationSetting>({
   hasLodingData: 0 // 已经加载的数据
 })
 
-// 所有平台
-const allPf = reactive<Array<SelectInfo>>([
-  {
-    name: 'wx',
-    cnName: '微信'
-  },
-  {
-    name: 'tt',
-    cnName: '抖音'
-  },
-  {
-    name: 'web',
-    cnName: 'Web'
-  }
-])
-
-// 查询字段设置
-const queryInfo = reactive<Array<QueryInfo>>([
-  {
-    name: 'gameName',
-    label: '游戏名',
-    type: FilterType.INPUT,
-    placeholder: '请输入游戏名查询'
-  },
-  {
-    name: 'pf',
-    label: '平台',
-    type: FilterType.SELECT,
-    placeholder: '请选择平台',
-    otherOption: allPf
-  }
-])
-
 // 字段信息
 const filedsInfo = reactive<Array<TableFieldInfo>>([
   {
@@ -232,6 +195,8 @@ const gameFormData = reactive<GameDialogFormData>({
 // 进入用户页面
 const enterUserPage = (row: any) => {
   console.log(row)
+  tableStore.updateQueryInfo(row.gid, 'web')
+  router.push('/home/playerManageView')
 }
 
 // 游戏配置提交
@@ -246,9 +211,10 @@ const submiteGameChange = () => {
   <div class="gameMangeBox">
     <Table
       ref="gameTableRef"
-      :is-open-query="true"
+      :need-left-tools="true"
+      :open-filter-query="false"
+      :open-page-query="false"
       :table-fields-info="filedsInfo"
-      :query-info="queryInfo"
       :request-config="requestConfig"
       :pagination-config="paginationConfig"
       @addNewItem="addNeweItem(dialogConfig)"
@@ -260,10 +226,16 @@ const submiteGameChange = () => {
               size="small"
               type="primary"
               @click="handleEdit(scope.row, gameFormData, dialogConfig)"
+              class="operationBtn"
             >
               修改
             </el-button>
-            <el-button size="small" type="success" @click="enterUserPage(scope.row)">
+            <el-button
+              class="operationBtn"
+              size="small"
+              type="success"
+              @click="enterUserPage(scope.row)"
+            >
               进入
             </el-button>
           </template>
@@ -304,7 +276,12 @@ const submiteGameChange = () => {
 <style scoped>
 .gameMangeBox {
   width: 100%;
-  height: 100%;
+  /* height: 100%; */
   padding-top: 2%;
+  background-color: white;
+}
+
+.operationBtn {
+  margin-right: 5%;
 }
 </style>

+ 2 - 2
src/views/Home/HomeView.vue

@@ -165,10 +165,10 @@ const changeCollapse = () => {
   /* position: absolute; */
 
   width: 100%;
-  height: 93%;
+  /* height: 93%; */
   margin-top: 7vh;
   overflow: scroll;
-  /* background-color: lightcoral; */
+  background-color: #f2f3f5;
   right: 0vw;
   top: 0vh;
 }

+ 96 - 28
src/views/Home/PlayerManageView.vue

@@ -9,17 +9,21 @@ import {
 
 import Table from '@/components/Table.vue'
 import CryptoJS from 'crypto-js'
+import axiosInstance from '@/utils/axios/axiosInstance'
 
-import { reactive, ref } from 'vue'
+import { onMounted, reactive, ref, watch } from 'vue'
 
 import type { FormRules, FormInstance } from 'element-plus'
 
+import { useTableStore } from '@/stores/useTable'
 import { useRequest } from '@/hooks/useRequest'
 import { useDialog } from '@/hooks/useDialog'
 
 const { AllApi } = useRequest()
+const tableStore = useTableStore()
 const { dialogClose, submitDialog, handleEdit, addNeweItem } = useDialog()
 
+// 对话框表单数据格式
 interface PlayerDialogFormData {
   gid: string
   openId: string
@@ -28,62 +32,72 @@ interface PlayerDialogFormData {
   userId: string
 }
 
+// 表格对象
 const playerTableRef = ref()
 
 // 游戏配置对话框对象
 const playerDialogFormRef = ref<FormInstance>()
 
-// 配置请求参数
-const requestConfig = reactive({
-  url: AllApi.getUserTable,
-  other: {
-    offset: 0,
-    limit: 10,
-    gid: '',
-    pf: ''
-  }
-})
-
 // 配置分页数据
 const paginationConfig = reactive<TablePaginationSetting>({
-  limit: 10, // 每页展示个数
+  limit: 15, // 每页展示个数
   currentPage: 1, // 当前页码
   total: 0, // 数据总数
-  pagesizeList: [10, 15], // 页数大小列表
+  pagesizeList: [15, 20], // 页数大小列表
   loading: true, // 加载图标
   hasLodingData: 0 // 已经加载的数据
 })
 
+// 配置请求参数
+const requestConfig = reactive({
+  url: AllApi.getUserTable,
+  other: {
+    offset: 0,
+    limit: paginationConfig.limit,
+    gid: tableStore.playerQueryInfo.gid,
+    pf: tableStore.playerQueryInfo.pf
+  }
+})
+
 // 所有平台
 const allPf = reactive<Array<SelectInfo>>([
   {
     name: 'wx',
-    cnName: '微信'
+    cnName: '微信',
+    value: 'wx'
   },
   {
     name: 'tt',
-    cnName: '抖音'
+    cnName: '抖音',
+    value: 'tt'
   },
   {
     name: 'web',
-    cnName: 'Web'
+    cnName: 'Web',
+    value: 'web'
   }
 ])
 
+// 所有游戏信息
+const allGameInfo = reactive<Array<SelectInfo>>([])
+
 // 查询字段设置
 const queryInfo = reactive<Array<QueryInfo>>([
   {
-    name: 'gameName',
+    name: 'gid',
     label: '游戏名',
-    type: FilterType.INPUT,
-    placeholder: '请输入游戏名查询'
+    type: FilterType.SELECT,
+    placeholder: '请输入游戏名查询',
+    otherOption: allGameInfo,
+    default: tableStore.playerQueryInfo.gid
   },
   {
     name: 'pf',
     label: '平台',
     type: FilterType.SELECT,
     placeholder: '请选择平台',
-    otherOption: allPf
+    otherOption: allPf,
+    default: tableStore.playerQueryInfo.pf
   }
 ])
 
@@ -178,12 +192,53 @@ const submiteOptionChange = (isEncrypt: boolean = false) => {
     }
   )
 }
+
+const getAllGameInfo = async () => {
+  try {
+    const response = await axiosInstance.post(AllApi.getGameTable, {
+      appSecret: '6YJSuc50uJ18zj45'
+    })
+    const result = JSON.parse(JSON.stringify(response))
+    const data = result.data // 拿到返回的数据
+
+    if (result.code === 0) {
+      if (Array.isArray(data)) {
+        let gameInfoList = data.map((item) => {
+          return { gid: item.gid, gameName: item.gameName }
+        })
+        tableStore.$patch({
+          allGameInfo: gameInfoList
+        })
+        gameInfoList.map((item) => {
+          allGameInfo.push({
+            name: item.gameName,
+            value: item.gid,
+            cnName: item.gameName
+          })
+        })
+        return gameInfoList
+      }
+    } else {
+      console.log('获取游戏列表失败')
+      return false
+    }
+  } catch (err) {
+    console.log(err)
+    throw new Error('获取游戏列表失败')
+  }
+}
+
+onMounted(() => {
+  getAllGameInfo()
+})
 </script>
 <template>
   <div class="gameMangeBox">
     <Table
       ref="playerTableRef"
-      :is-open-query="true"
+      :need-left-tools="false"
+      :open-page-query="true"
+      :open-filter-query="true"
       :table-fields-info="filedsInfo"
       :query-info="queryInfo"
       :request-config="requestConfig"
@@ -194,13 +249,19 @@ const submiteOptionChange = (isEncrypt: boolean = false) => {
           <template #default="scope">
             <el-button
               size="small"
-              type="primary"
+              type="warning"
               @click="handleEdit(scope.row, optionFormData, dialogConfig)"
+              class="operationBtn"
             >
               修改权限
             </el-button>
-            <el-button size="small" type="success" @click="blockedPlayer(scope.row)">
-              封禁
+            <el-button
+              class="operationBtn"
+              size="small"
+              @click="blockedPlayer(scope.row)"
+              :type="scope.row.inBlack ? 'success' : 'danger'"
+            >
+              {{ scope.row.inBlack ? '解封' : '封禁' }}
             </el-button>
           </template>
         </el-table-column>
@@ -247,12 +308,19 @@ const submiteOptionChange = (isEncrypt: boolean = false) => {
 
 <style scoped>
 .gameMangeBox {
-  width: 100%;
-  height: 100%;
-  padding-top: 2%;
+  width: 98%;
+  margin: 1% auto;
+  /* height: 100%; */
+  /* padding-top: 2%; */
+  background-color: white;
+  border: 1px solid #e5e6eb;
 }
 
 .subBtnItem {
   margin-right: 1%;
 }
+
+.operationBtn {
+  margin-right: 5%;
+}
 </style>