Forráskód Böngészése

更新节流方法,对于可能会短时间内发生大量请求的方法进行了封装,如登录,表格查询、刷新等;修复了玩家管理页上方平台选择与实际请求不符的BUG;优化了对话框的确认按钮的文字,现在可以自定义文字;

fxs 7 hónapja
szülő
commit
58c9948e73

+ 23 - 9
src/components/Table.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 18:16:18
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-28 17:18:02
+ * @LastEditTime: 2024-10-12 17:55:51
  * @FilePath: \Game-Backstage-Management-System\src\components\Table.vue
  * @Description: 
  * 
@@ -24,8 +24,13 @@ import { useRequest } from '@/hooks/useRequest'
 import type { FormInstance } from 'element-plus'
 import axiosInstance from '@/utils/axios/axiosInstance'
 
+import { throttleFunc } from '@/utils/common'
+
 const { analysisResCode } = useRequest()
 
+// 节流的延迟时间
+const throttleTime = 500
+
 // 表格工具图标大小
 const toolsIconSize = ref(25)
 
@@ -234,9 +239,8 @@ const resetTableData = () => {
 const queryTableData = () => {
   if (props.requestConfig) {
     reqconfig.otherOptions = { ...props.requestConfig.otherOptions, ...queryFormData }
-  }
-  if (props.openPageQuery) getData()
-  else {
+    getData()
+  } else {
     let filteredTable = []
     // 过滤出来所有符合formData数据的条件
     filteredTable = backupTableData.filter((item) => {
@@ -255,6 +259,9 @@ const queryTableData = () => {
   }
 }
 
+// 把查询方法包装一下,节流
+const throttleQueryTableData = throttleFunc(queryTableData, throttleTime)
+
 /**
  * @description: 重置整个查询表单,重置后,再请求一次全部表格
  * @param {*} formEl  表单对象
@@ -276,6 +283,9 @@ const resetQueryForm = (formEl: FormInstance | undefined) => {
   queryTableData()
 }
 
+// 把重置方法包装一下,节流
+const throttleResetQueryForm = throttleFunc(resetQueryForm, throttleTime)
+
 /**
  * @description: 在获取完数据后,插入均值行
  * @param {*} start 插入的位置
@@ -543,7 +553,7 @@ onMounted(() => {
         >
           <!-- 所有的input查询框 -->
           <el-form-item
-            @keyup.enter.native="queryTableData"
+            @keyup.enter.native="throttleQueryTableData"
             :label="item.label"
             v-for="item in inputFieldsList"
             class="filterItem"
@@ -584,10 +594,14 @@ onMounted(() => {
         <div class="queryBox">
           <el-divider class="queryPartition" content-position="center" direction="vertical" />
           <div class="queryBtnBox">
-            <el-button class="queryBtn" color="#165dff" @click="queryTableData">
+            <el-button class="queryBtn" color="#165dff" @click="throttleQueryTableData">
               <el-icon><Search /></el-icon>查询
             </el-button>
-            <el-button class="refreshBtn" color="#f2f3f5" @click="resetQueryForm(queryFormRef)">
+            <el-button
+              class="refreshBtn"
+              color="#f2f3f5"
+              @click="throttleResetQueryForm(queryFormRef)"
+            >
               <el-icon><RefreshRight /></el-icon>重置
             </el-button>
           </div>
@@ -622,8 +636,8 @@ onMounted(() => {
         >
           <el-icon><Download /></el-icon>下载
         </el-button>
-
-        <RegreshBtn @refresh-table="queryTableData" :icon-size="toolsIconSize"></RegreshBtn>
+        <!-- throttleFunc(queryTableData, 200) -->
+        <RegreshBtn @refresh-table="throttleQueryTableData" :icon-size="toolsIconSize"></RegreshBtn>
 
         <FilterPopover
           :table-fields-info="tableFieldsInfo"

+ 6 - 3
src/components/common/Dialog.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-09-04 11:21:05
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-09 15:51:28
+ * @LastEditTime: 2024-10-12 18:06:12
  * @FilePath: \Game-Backstage-Management-System\src\components\common\Dialog.vue
  * @Description: 
  * 
@@ -18,6 +18,7 @@ import type { DialogConfig } from '@/types/dialog'
 
 interface DialogProps {
   config: DialogConfig
+  configBtnText?: string
 }
 
 // 临时用的close
@@ -33,7 +34,9 @@ const updateUrl = ref<string>('')
 const dialogFormRef = ref<InstanceType<typeof Form>>()
 
 // props
-const props = withDefaults(defineProps<DialogProps>(), {})
+const props = withDefaults(defineProps<DialogProps>(), {
+  configBtnText: '确定'
+})
 
 // props中的关于配置的信息
 const dialogConfigInfo = props.config
@@ -134,7 +137,7 @@ defineExpose({
           <slot name="otherBtn"></slot>
           <slot name="btnGroup">
             <el-button class="dialogBtn" type="primary" @click="submiteGameChange()">
-              确认
+              {{ configBtnText }}
             </el-button>
             <el-button class="dialogBtn" @click="closeDialog">取消</el-button>
           </slot>

+ 1 - 0
src/components/form/FileUpload.vue

@@ -130,6 +130,7 @@ defineExpose({
       v-model="uploadInfo.uploadVisible"
       title="文件上传"
       width="500"
+      :close-on-click-modal="false"
       @close="closeUpload"
     >
       <div class="uploadBox" v-loading="loading" element-loading-text="正在上传...">

+ 4 - 1
src/stores/useCommon.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-28 11:46:10
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-09 15:06:30
+ * @LastEditTime: 2024-10-12 17:07:58
  * @FilePath: \Game-Backstage-Management-System\src\stores\useCommon.ts
  * @Description:通用的store,在多个页面均会使用
  *
@@ -26,6 +26,9 @@ export const useCommonStore = defineStore('commonStore', () => {
   let gid = getLocalInfo('selectInfo', 'gid')
   gid = gid ? gid : '1001'
   let pf = getLocalInfo('selectInfo', 'pf')
+  if (pf.length > 1) {
+    pf = [pf[0]]
+  }
   pf = pf ? pf : ['wx']
   const selectInfo = reactive<SelectInfo>({
     gid: gid as string,

+ 1 - 1
src/types/dialog.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-09-04 14:02:44
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-04 14:12:51
+ * @LastEditTime: 2024-10-12 18:03:07
  * @FilePath: \Game-Backstage-Management-System\src\types\dialog.ts
  * @Description:
  *

+ 29 - 2
src/utils/common/index.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-26 15:46:42
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-13 17:35:33
+ * @LastEditTime: 2024-10-12 17:37:45
  * @FilePath: \Game-Backstage-Management-System\src\utils\common\index.ts
  * @Description:
  *
@@ -10,7 +10,12 @@
 
 import { ElMessage } from 'element-plus'
 
-// 防抖
+/**
+ * @description:  包装防抖函数
+ * @param {array} func 函数
+ * @param {number} delay 时间
+ * @return {*}
+ */
 export function debounceFunc<T extends (...args: any[]) => any>(
   func: T,
   delay: number
@@ -24,6 +29,28 @@ export function debounceFunc<T extends (...args: any[]) => any>(
   }
 }
 
+/**
+ * @description: 包装节流函数
+ * @param {T} func 函数
+ * @param {number} delay 时间
+ * @return {*}
+ */
+export function throttleFunc<T extends (...args: any[]) => any>(
+  func: T,
+  delay: number
+): (...args: Parameters<T>) => void {
+  let lastCall = 0
+
+  return function (...args: Parameters<T>) {
+    const now = Date.now()
+
+    if (now - lastCall >= delay) {
+      lastCall = now
+      func(...args)
+    }
+  }
+}
+
 // 小数转百分比
 export function decimalToPercentage(decimal: number, decimalPlaces: number = 0): string {
   // Convert the decimal to a percentage by multiplying by 100

+ 11 - 9
src/views/AppManage/EventManageView.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-09-02 17:57:15
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-12 16:45:15
+ * @LastEditTime: 2024-10-12 17:58:07
  * @FilePath: \Game-Backstage-Management-System\src\views\AppManage\EventManageView.vue
  * @Description: 
  * 
@@ -11,19 +11,18 @@
 import type { ResponseInfo } from '@/types/res'
 
 import HeaderCard from '@/components/dataAnalysis/HeaderCard.vue'
-import { shouldListenToEvent } from '@/utils/table/table'
-import { ref, reactive, computed } from 'vue'
-
-// import { ElMessage, ElNotification } from 'element-plus'
-
+import router from '@/router'
 import FileUpload from '@/components/form/FileUpload.vue'
 import axiosInstance from '@/utils/axios/axiosInstance'
+
+import { ref, reactive, computed } from 'vue'
 import { useRequest } from '@/hooks/useRequest'
 import { useCommonStore } from '@/stores/useCommon'
 import { downLoadData } from '@/utils/table/table'
-
 import { resetTimeToMidnight } from '@/utils/common'
-import router from '@/router'
+import { shouldListenToEvent } from '@/utils/table/table'
+
+import { throttleFunc } from '@/utils/common'
 
 interface uploadEvent {
   id?: number // 更新需要传入id
@@ -293,6 +292,9 @@ const startDownload = async () => {
   })
 }
 
+// 把开始下载方法包装一下,节流
+const throttleStartDownload = throttleFunc(startDownload, 1000)
+
 /**
  * @description: 创建一个上传请求函数
  * @param {*} url 请求地址
@@ -473,7 +475,7 @@ const uploadSuccess = async (data: {
     <div class="handleEvent" v-if="nowRouteName === 'EventTable'">
       <div class="fileGroup">
         <el-button class="fileBtn" color="#626aef" @click="startUpload">上传</el-button>
-        <el-button class="fileBtn" @click="startDownload">下载</el-button>
+        <el-button class="fileBtn" @click="throttleStartDownload">下载</el-button>
       </div>
     </div>
     <div class="eventTableBox">

+ 21 - 61
src/views/Home/InfoManage/PlayerManageView.vue

@@ -25,8 +25,8 @@ import { FormFieldType } from '@/types/form'
 import { useTableStore } from '@/stores/useTable'
 import { useRequest } from '@/hooks/useRequest'
 import { useCommonStore } from '@/stores/useCommon'
-import { useAnalysis } from '@/hooks/useAnalysis'
-const { updateReqConfig } = useAnalysis()
+// import { useAnalysis } from '@/hooks/useAnalysis'
+// const { updateReqConfig } = useAnalysis()
 
 const { AllApi, analysisResCode } = useRequest()
 
@@ -34,7 +34,7 @@ const tableStore = useTableStore()
 const { selectInfo } = useCommonStore()
 
 // 是否是单选pf
-const isSinglePf = true
+// const isSinglePf = true
 
 // 表格对象
 const playerTableRef = ref()
@@ -84,16 +84,16 @@ const allPf: Array<SelectInfo> = [
 const allGameInfo = reactive<Array<SelectInfo>>([])
 
 // 查询字段设置
-const queryInfo: Array<QueryInfo> = [
+const queryInfo = reactive<Array<QueryInfo>>([
   {
     name: 'pf',
     label: '平台',
     type: FilterType.SELECT,
     placeholder: '请选择平台',
     otherOption: allPf,
-    default: tableStore.playerQueryInfo.pf
+    default: selectInfo.pf[0]
   }
-]
+])
 
 // 字段信息
 const filedsInfo = reactive<Array<TableFieldInfo>>([
@@ -175,51 +175,6 @@ const filedsInfo = reactive<Array<TableFieldInfo>>([
   }
 ])
 
-// // 游戏配置对话框设置
-// const dialogConfig = reactive({
-//   dialogVisible: false,
-//   title: '用户权限配置',
-//   formLabelWidth: '150px',
-//   type: 0 // 0 是新增 1是修改
-// })
-
-// // 表单校验规则
-// const optionFormRule = reactive({
-//   option: ''
-// })
-
-// // 表单规则
-// const gameRules = reactive<FormRules<typeof optionFormRule>>({
-//   option: [
-//     { required: true, message: '请输入权限', trigger: 'blur' },
-//     { min: 1, max: 255, message: '最短1位,最长255位', trigger: 'blur' }
-//   ]
-// })
-
-// // 对话框表单数据
-// const optionFormData = reactive<PlayerDialogFormData>({
-//   gid: '',
-//   openId: '',
-//   pf: '',
-//   option: '',
-//   userId: ''
-// })
-
-// // 游戏配置提交
-// const submiteOptionChange = (isEncrypt: boolean = false) => {
-//   let option = optionFormData.option
-//   if (isEncrypt) {
-//     let message = `${optionFormData.gid}${optionFormData.userId}${optionFormData.pf}`
-//     option = CryptoJS.HmacMD5(message, optionFormData.option).toString()
-//   }
-//   submitDialog(playerDialogFormRef.value, dialogConfig, AllApi.addOption, {
-//     ...optionFormData,
-//     option
-//   }).then(() => {
-//     playerTableRef.value.getData()
-//   })
-// }
-
 // 表单校验规则
 const optionFormRule = reactive({
   option: ''
@@ -304,18 +259,18 @@ const encrypt = () => {
   playerDialogFormRef.value.encrypt('option', true, ['gid', 'userId', 'pf'])
 }
 
-const updateSelect = (gid: any, pf: any) => {
-  pf = isSinglePf ? pf[0] : pf
-  updateReqConfig(requestConfig, { pf, gid })
-  // requestConfig.otherOptions.gid = gid
-}
+// 表格的查询应该和全局的平台选择独立开来
+// const updateSelect = (gid: any, pf: any) => {
+//   pf = isSinglePf ? pf[0] : pf
+//   updateReqConfig(requestConfig, { pf, gid })
+// }
 
-const backupSelect = reactive([])
+// const backupSelect = reactive([])
 
-import { usePage } from '@/hooks/usePage'
-const { watchPageChange } = usePage()
+// import { usePage } from '@/hooks/usePage'
+// const { watchPageChange } = usePage()
 
-watchPageChange(() => [selectInfo.gid, selectInfo.pf], backupSelect, updateSelect)
+// watchPageChange(() => [selectInfo.gid, selectInfo.pf], backupSelect, updateSelect)
 
 onMounted(() => {
   tableStore.allGameInfo.map((item) => {
@@ -366,7 +321,12 @@ onMounted(() => {
       </template>
     </Table>
     <div class="optionDialog">
-      <Dialog @form-submit="formSub" ref="playerDialogFormRef" :config="optionDialogConfig">
+      <Dialog
+        :config-btn-text="'普通上传'"
+        @form-submit="formSub"
+        ref="playerDialogFormRef"
+        :config="optionDialogConfig"
+      >
         <template #otherBtn>
           <el-button class="operationBtn" type="warning" @click="encrypt"> 加密上传 </el-button>
         </template>

+ 15 - 5
src/views/Login/LoginView.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { onMounted, reactive } from 'vue'
+import { onMounted, reactive, ref } from 'vue'
 import type { RuleInfo } from '@/types/input'
 import { useRequest } from '@/hooks/useRequest'
 import router from '@/router'
@@ -22,12 +22,21 @@ const loginInfo = reactive<LoginInfoType>({
   password: ''
 })
 
-const userLogin = () => {
+// 判断目前是否在登陆
+const isLogining = ref(false)
+
+/**
+ * @description: 用户登录
+ * @return {*}
+ */
+const userLogin = async () => {
+  if (isLogining.value) return
+  isLogining.value = true
   let vaild = Object.keys(loginInfo).every((key) => {
     return formFieldsRules[key].rules.every((item) => item.validator())
   })
   if (vaild) {
-    axiosInstance
+    await axiosInstance
       .post(AllApi.userLogin, loginInfo)
       .then((data) => {
         let result = JSON.parse(JSON.stringify(data))
@@ -36,14 +45,15 @@ const userLogin = () => {
             setToken(result.token)
             setRefreshToken(result.refreshToken)
             setLoginState(true)
-            // localStorage.setItem('token', result.token)
-            // localStorage.setItem('refreshToken', result.refreshToken)
             axiosInstance.defaults.headers['Authorization'] = result.token // 需要在这里设置,不然又会触发拦截器
             router.push('/')
           })
           .catch((err) => {
             console.log(err)
           })
+          .finally(() => {
+            isLogining.value = false
+          })
       })
       .catch((err) => {
         console.log(err)