Преглед изворни кода

更新事件管理界面布局;修复事件管理详情页和事件分析详情页的路由切换BUG,现在直接刷新或者不带参进入详情页会直接跳转到table页;更新上传逻辑;

fxs пре 8 месеци
родитељ
комит
01d1e0d57c

+ 12 - 2
src/components/form/FileUpload.vue

@@ -7,8 +7,12 @@ interface UploadProps {
   title: string
 }
 
+// 上传组价
 const uploadRef = ref<UploadInstance>()
 
+// 侧边弹出框组件
+const tipVisisble = ref(false)
+
 // 上传成功的对外回调
 const emits = defineEmits(['uploadSuccess'])
 
@@ -80,13 +84,19 @@ const handleExceed = (files: UploadRawFile[]) => {
   file.uid = genFileId()
   uploadRef.value!.handleStart(file)
 }
-const tipVisisble = ref(false)
+
 const openTip = () => {
   tipVisisble.value = true
 }
 
+const closeUpload = () => {
+  uploadRef.value?.clearFiles()
+  uploadInfo.uploadVisible = false
+}
+
 defineExpose({
-  startUpload
+  startUpload,
+  closeUpload
 })
 </script>
 

+ 16 - 3
src/router/appManage.ts

@@ -2,12 +2,12 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:24:58
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-06 14:54:04
+ * @LastEditTime: 2024-09-12 17:45:31
  * @FilePath: \Game-Backstage-Management-System\src\router\appManage.ts
  * @Description:
  *
  */
-
+import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
 export default [
   {
     path: '/appManage',
@@ -41,7 +41,20 @@ export default [
           {
             path: 'eventDetail', // 注意:这里没有使用动态参数,而是使用查询参数
             name: 'EventDetail',
-            component: () => import('@/views/AppManage/EventDetailsView.vue')
+            component: () => import('@/views/AppManage/EventDetailsView.vue'),
+            beforeEnter: (
+              to: RouteLocationNormalized,
+              from: RouteLocationNormalized,
+              next: NavigationGuardNext
+            ) => {
+              // next()
+              if (!from.name || to.fullPath === '/appManage/eventManage/eventDetail') {
+                // 当页面刷新(即没有来源路由)时,重定向到 /eventManage/eventTable
+                next({ path: '/appManage/eventManage/eventTable' })
+              } else {
+                next()
+              }
+            }
           },
           {
             path: 'eventTable',

+ 19 - 3
src/router/home.ts

@@ -2,12 +2,12 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:24:58
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-09 12:12:28
+ * @LastEditTime: 2024-09-12 17:47:02
  * @FilePath: \Game-Backstage-Management-System\src\router\home.ts
  * @Description:
  *
  */
-
+import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
 export default [
   {
     path: '/home',
@@ -99,7 +99,23 @@ export default [
               {
                 path: 'eventAnalysisDetail',
                 name: 'EventAnalysisDetail',
-                component: () => import('@/views/Home/Analysis/EventAnalysisDetail.vue')
+                component: () => import('@/views/Home/Analysis/EventAnalysisDetail.vue'),
+                beforeEnter: (
+                  to: RouteLocationNormalized,
+                  from: RouteLocationNormalized,
+                  next: NavigationGuardNext
+                ) => {
+                  // next()
+                  if (
+                    !from.name ||
+                    to.fullPath === '/home/dataAnalysis/eventAnalysisView/eventAnalysisDetail'
+                  ) {
+                    // 当页面刷新(即没有来源路由)时,重定向到 /eventManage/eventTable
+                    next({ path: '/home/dataAnalysis/eventAnalysisView/eventAnalysisTable' })
+                  } else {
+                    next()
+                  }
+                }
               }
             ]
           }

+ 2 - 3
src/views/AppManage/EventDetailsView.vue

@@ -6,7 +6,7 @@ import FileUpload from '@/components/form/FileUpload.vue'
 
 import type { ReqConfig } from '@/types/dataAnalysis'
 import { type FormField, FormFieldType } from '@/types/form'
-import { ElMessage, ElMessageBox, type FormRules } from 'element-plus'
+import { ElMessageBox, type FormRules } from 'element-plus'
 import type { FormConfig } from '@/types/form'
 import {
   type TablePaginationSetting,
@@ -14,7 +14,7 @@ import {
   FieldSpecialEffectType
 } from '@/types/table'
 import type { DialogConfig } from '@/types/dialog'
-import { reactive, onMounted, ref } from 'vue'
+import { reactive, ref } from 'vue'
 import { useRoute } from 'vue-router'
 import { useRequest } from '@/hooks/useRequest'
 import axiosInstance from '@/utils/axios/axiosInstance'
@@ -392,7 +392,6 @@ const formSub = () => {
  * @return {*}
  */
 const editOption = (row: any) => {
-  console.log(row)
   attrDialog.value.editForm(row, AllApi.updateGameActionOption)
 }
 

+ 68 - 88
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-09-12 15:05:20
+ * @LastEditTime: 2024-09-12 18:01:11
  * @FilePath: \Game-Backstage-Management-System\src\views\AppManage\EventManageView.vue
  * @Description: 
  * 
@@ -10,7 +10,7 @@
 <script setup lang="ts">
 import HeaderCard from '@/components/dataAnalysis/HeaderCard.vue'
 import { shouldListenToEvent } from '@/utils/table/table'
-import { onMounted, ref, reactive, toRaw } from 'vue'
+import { onMounted, ref, reactive } from 'vue'
 import { ElMessage } from 'element-plus'
 import FileUpload from '@/components/form/FileUpload.vue'
 import axiosInstance from '@/utils/axios/axiosInstance'
@@ -18,11 +18,15 @@ 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'
 
 const { selectInfo } = useCommonStore()
 
 const { AllApi } = useRequest()
 
+// 事件表格ref
+const eventTableRef = ref()
+
 // 头部ref
 const headerCard = ref<typeof HeaderCard>()
 
@@ -56,7 +60,6 @@ const submitUpload = async (reqList: Array<Promise<boolean>>) => {
   await Promise.allSettled(reqList).then((res) => {
     if (
       res.every((item) => {
-        console.log(item)
         return item.status === 'fulfilled' && item.value === true
       })
     ) {
@@ -107,10 +110,11 @@ const getTableData = async (
 }
 
 /**
- * @description: 批量请求
- * @param {*} url 请求地址
- * @param {*} reqParams 请求参数列表
- * @return {*}
+ * @description:  批量请求选项数据
+ * @param {*} url 请求的地址
+ * @param {*} reqParams 请求的参数列表,主要是actionid
+ * @param {*} eventTable 事件列表
+ * @return {Promise<Object>}  返回一个最终的结果,其中key是每个事件的actionid,值是选项列表
  */
 const batReqOptionsData = async (
   url: string,
@@ -139,8 +143,7 @@ const batReqOptionsData = async (
 }
 
 /**
- * @description: 拿到事件数据和选项数据
- * @param {*} needTable 需要拿到哪些数据,默认是all,即所有数据。'event'表示只拿事件数据,'option'表示只拿选项数据
+ * @description: 拿到事件数据和选项数据,首先需要拿到所有的事件列表,然后将他们的actionId抽出来形成一个列表,这个列表去作为optin的查询参数批量查询
  * @return {*} 返回事件数据和选项数据
  */
 const getAllTable = async (): Promise<{ allEventTable: Array<any>; allOptionsInfo: any }> => {
@@ -158,7 +161,6 @@ const getAllTable = async (): Promise<{ allEventTable: Array<any>; allOptionsInf
 
 /**
  * @description: 开始上传
- * @param{Array<any>} tableData  表格数据
  * @return {*}
  */
 const startUpload = async () => {
@@ -168,7 +170,7 @@ const startUpload = async () => {
 }
 
 /**
- * @description: 开始下载
+ * @description: 获取事件列表和选项列表的数据,开始下载
  * @return {*}
  */
 const startDownload = async () => {
@@ -181,35 +183,33 @@ const startDownload = async () => {
 
 // 上传选项的时候,选项的键要设置为actionid
 // 需要先上传事件,然后上传完了,用上传的选项中的第一个(如果有)的actionid去找到对应的事件的ID(不是actionid),然后作为选项上传的id
-
-const uploadSuccess2 = async (data: any) => {
+/**
+ * @description: 当文件添加后,开始进行上传前的处理
+ *  首先需要上传事件,如果现有上传的列表中的actionid已经包含在了现有列表中,那么判定为更新,否则为新增
+ *  上传完成后,需要首先获取一次新的数据,然后再开始上传选项。
+ *  分别在上传和已有的选项列表中,找到对应的acionID的那一组选项,对这一组数据,如果已经存在对应的id,那么就是更新,否则为新增
+ *  然后上传,上传完毕后,整体列表刷新,关闭弹框
+ * @param {*} data 上传的文件数据,里面包含allEventTable:所有的事件列表,allOptionsInfo:所有选项列表
+ * @return {*}
+ */
+const uploadSuccess = async (data: any) => {
   let uploadEventTable = data.allEventTable
   let uploadOptionsInfo = data.allOptionsInfo
 
   // 上传的事件列表有值,则开始上传
   let { allEventTable, allOptionsInfo } = await getAllTable() // 获取所有事件列表和选项列表
-  // console.log(allEventTable, allOptionsInfo, uploadOptionsInfo)
-  let newEventKeys: Array<any> = [] // 拿到所有需要新上传的事件
-  Object.keys(uploadOptionsInfo).map((item) => {
-    if (allEventTable.every((i) => i.actionId !== item)) {
-      newEventKeys.push(item)
-    }
-  })
-
-  // 1、新事件、新选项
-  // 2、旧事件、新选项 + 旧选项
 
+  // 开始上传事件
   let eventReqList: Array<Promise<boolean>> = []
   let eventReqUrl = AllApi.setGameAction
   if (Array.isArray(uploadEventTable) && uploadEventTable.length) {
+    // 将新事件和旧事件区分,对于新事件走新增,对于旧事件走更新
     uploadEventTable.map((item) => {
       let { id, createdAt, updatedAt, ...otherInfo } = item
       if (allEventTable.some((i) => i.actionId === item.actionId)) {
         eventReqUrl = AllApi.updateGameAction
-        console.log('更新一个事件', item)
       } else {
         eventReqUrl = AllApi.setGameAction
-        console.log('新增一个事件', item)
       }
       let eventReq = axiosInstance
         .post(eventReqUrl, otherInfo)
@@ -221,71 +221,55 @@ const uploadSuccess2 = async (data: any) => {
           console.log(err)
           return false
         })
-      eventReqList.push(eventReq)
+      eventReqList.push(eventReq) // 统一放入请求列表中
     })
-    await submitUpload(eventReqList)
+    await submitUpload(eventReqList) // 等待所有的事件请求完成
   }
-  ;({ allEventTable, allOptionsInfo } = await getAllTable()) // 获取所有事件列表和选项列表
+  ;({ allEventTable, allOptionsInfo } = await getAllTable()) // 重新获取所有事件列表和选项列表
   let optionsReqList: Array<Promise<boolean>> = []
-  // console.log(allEventTable)
 
   allEventTable.map((item) => {
-    let uploadOptionItem = uploadOptionsInfo[item.actionId] as Array<any> // 找到所有在已有事件列表中的选项列表
+    // 在上传的事件列表中,找到有对应的事件的actionid的那一组数据
+    let uploadOptionItem = uploadOptionsInfo[item.actionId] as Array<any>
+    // 在现有的事件列表中,找到对应事件的actionid的那一组数据
     let nowOptionItem = allOptionsInfo[item.actionId] as Array<any> // 找到所有在已有事件列表中的选项列表
 
+    // 如果有已存在的事件,并且上传的选项列表中也有对应的actionid,则开始上传
     if (uploadOptionItem) {
+      // 对找到的那一组数据进行循环,区分出来哪些是已有的,哪些是新上传的
+      // 新上传的需要给他加上actionid,然后上传,这个actionid其实是事件列表的id字段
       uploadOptionItem.map((i) => {
         let optionReqUrl = AllApi.addGameActionOption // 选项上传的url
         let { id, actionId, createdAt, updatedAt, ...otherInfo } = i // 上传参数拆分出来
         let reqParams = {}
-        if (newEventKeys.find((k) => k === item.actionId)) {
-          // 是新增的事件的选项
-          console.log('全新增')
+        // 分出来哪些是新增加的选项,哪些是需要更新的选项
+        // 新增的选项需要加入的是事件列表的主键,而更新中需要加入的是option的id
+        if (nowOptionItem.some((k) => k.id === i.id)) {
+          reqParams = { id, ...otherInfo }
+
+          optionReqUrl = AllApi.updateGameActionOption
+        } else {
           actionId = item.id
-          console.log(actionId)
-          optionReqUrl = AllApi.addGameActionOption
           reqParams = { actionId, ...otherInfo }
-          let optionReq = axiosInstance
-            .post(optionReqUrl, reqParams)
-            .then((res: any) => {
-              if (res.code === 0) return true
-              return false
-            })
-            .catch((err) => {
-              console.log(err)
-              return false
-            })
-          optionsReqList.push(optionReq)
-        } else {
-          // 是已有事件的选项
-          // 分出来哪些是新增加的选项,哪些是需要更新的选项
-          if (nowOptionItem.some((k) => k.id === i.id)) {
-            reqParams = { id, ...otherInfo }
-
-            optionReqUrl = AllApi.updateGameActionOption
-            console.log('更新一个选项', i)
-          } else {
-            actionId = item.id
-            reqParams = { actionId, ...otherInfo }
-            optionReqUrl = AllApi.addGameActionOption
-            console.log('新增一个选项', i)
-          }
-          let optionReq = axiosInstance
-            .post(optionReqUrl, reqParams)
-            .then((res: any) => {
-              if (res.code === 0) return true
-              return false
-            })
-            .catch((err) => {
-              console.log(err)
-              return false
-            })
-          optionsReqList.push(optionReq)
+          optionReqUrl = AllApi.addGameActionOption
         }
+        let optionReq = axiosInstance
+          .post(optionReqUrl, reqParams)
+          .then((res: any) => {
+            if (res.code === 0) return true
+            return false
+          })
+          .catch((err) => {
+            console.log(err)
+            return false
+          })
+        optionsReqList.push(optionReq)
       })
     }
   })
   await submitUpload(optionsReqList)
+  uploadRef.value?.closeUpload()
+  eventTableRef.value?.updateData()
 }
 
 onMounted(() => {})
@@ -301,7 +285,8 @@ onMounted(() => {})
         :need-pf-select="false"
       ></HeaderCard>
     </div>
-    <div class="handleEvent">
+
+    <div class="handleEvent" v-if="router.currentRoute.value.name === 'EventTable'">
       <div class="fileGroup">
         <el-button class="fileBtn" color="#626aef" @click="startUpload">上传</el-button>
         <el-button class="fileBtn" @click="startDownload">下载</el-button>
@@ -315,6 +300,7 @@ onMounted(() => {})
 
         <component
           :is="Component"
+          ref="eventTableRef"
           v-if="shouldListenToEvent(route.name, 'EventTable')"
           @enterDetail="headerAddPath"
         />
@@ -325,7 +311,7 @@ onMounted(() => {})
     </div>
     <div class="uploadFileBox">
       <FileUpload
-        @upload-success="uploadSuccess2"
+        @upload-success="uploadSuccess"
         ref="uploadRef"
         :title="uploadInfo.dialogTitle"
       ></FileUpload>
@@ -339,6 +325,7 @@ onMounted(() => {})
   margin: 1% auto;
   background-color: white;
   box-sizing: border-box;
+  position: relative;
 }
 
 .breadcrumbBox {
@@ -358,30 +345,23 @@ onMounted(() => {})
 }
 
 .handleEvent {
-  width: 100%;
+  position: absolute;
+  /* width: 12%; */
   background-color: white;
   box-sizing: border-box;
-  height: 48px;
-  padding: 0 24px;
+  /* height: 48px; */
   font-size: 16px;
   font-weight: 600;
-  position: relative;
-  display: flex;
-  align-items: center;
+  top: 20px;
+  right: 24px;
+  /* position: relative; */
   /* justify-content: flex-end; */
 }
 
 .fileGroup {
-  position: absolute;
-  right: 5%;
-  width: 12%;
-  box-sizing: border-box;
-  display: flex;
-  justify-content: space-around;
+  width: 100%;
 }
-
 .fileBtn {
-  /* color: white; */
-  /* margin-left: 50px; */
+  margin-right: 10px;
 }
 </style>

+ 14 - 0
src/views/AppManage/EventMangeTable.vue

@@ -263,6 +263,14 @@ const subForm = () => {
   }
 }
 
+/**
+ * @description: 更新表格数据
+ * @return {*}
+ */
+const updateData = () => {
+  eventTable.value?.getData()
+}
+
 watch(
   () => selectInfo.gid,
   (val: string) => {
@@ -270,6 +278,10 @@ watch(
   }
 )
 
+defineExpose({
+  updateData
+})
+
 onMounted(() => {})
 </script>
 
@@ -283,7 +295,9 @@ onMounted(() => {})
       :pagination-config="pagingConfig"
       :table-fields-info="tableFieldsInfo"
       :query-info="queryInfo"
+      :need-left-tools="true"
       :open-filter-query="true"
+      :need-right-tools="true"
       @add-new-item="addNewEvent"
     >
       <template #tableOperation>

+ 1 - 5
vite.config.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:06:49
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-09-02 16:34:08
+ * @LastEditTime: 2024-09-12 17:31:14
  * @FilePath: \Game-Backstage-Management-System\vite.config.ts
  * @Description:
  *
@@ -111,10 +111,6 @@ export default defineConfig(({ mode }) => {
         drop: mode === 'production' ? ['console', 'debugger'] : []
       }
     },
-
-    esbuild: {
-      drop: ['console', 'debugger']
-    },
     plugins: [
       vue(),
       ViteImageOptimizer(DEFAULT_OPTIONS),