Ver Fonte

修复了文件上传的BUG,现在可以正确处理不同情况下的上传行为;优化代码结构()

fxs há 8 meses atrás
pai
commit
f755d8268f

+ 1 - 1
.eslintrc.cjs

@@ -3,7 +3,7 @@ require('@rushstack/eslint-patch/modern-module-resolution')
 
 module.exports = {
   root: true,
-  'extends': [
+  extends: [
     'plugin:vue/vue3-essential',
     'eslint:recommended',
     '@vue/eslint-config-typescript',

+ 21 - 0
components.d.ts

@@ -10,25 +10,46 @@ declare module 'vue' {
     Dialog: typeof import('./src/components/common/Dialog.vue')['default']
     DropDownSelection: typeof import('./src/components/dataAnalysis/DropDownSelection.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
+    ElDrawer: typeof import('element-plus/es')['ElDrawer']
+    ElDropdown: typeof import('element-plus/es')['ElDropdown']
+    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
+    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
+    ElForm: typeof import('element-plus/es')['ElForm']
+    ElFormItem: typeof import('element-plus/es')['ElFormItem']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
+    ElInput: typeof import('element-plus/es')['ElInput']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
+    ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
+    ElSwitch: typeof import('element-plus/es')['ElSwitch']
+    ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
+    ElTabPane: typeof import('element-plus/es')['ElTabPane']
+    ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
+    ElTooltip: typeof import('element-plus/es')['ElTooltip']
+    ElUpload: typeof import('element-plus/es')['ElUpload']
     FileUpload: typeof import('./src/components/form/FileUpload.vue')['default']
     FilterPopover: typeof import('./src/components/toolsBtn/FilterPopover.vue')['default']
     Form: typeof import('./src/components/form/Form.vue')['default']
     HeaderCard: typeof import('./src/components/dataAnalysis/HeaderCard.vue')['default']
+    IconIcBaselineVisibility: typeof import('~icons/ic/baseline-visibility')['default']
+    IconIcBaselineVisibilityOff: typeof import('~icons/ic/baseline-visibility-off')['default']
     IconIconParkGameThree: typeof import('~icons/icon-park/game-three')['default']
     IconMaterialSymbolsLightLogout: typeof import('~icons/material-symbols-light/logout')['default']
     IconMdiPassword: typeof import('~icons/mdi/password')['default']
+    IconTablerPointFilled: typeof import('~icons/tabler/point-filled')['default']
     MyButton: typeof import('./src/components/form/MyButton.vue')['default']
     MyInput: typeof import('./src/components/form/MyInput.vue')['default']
     RegreshBtn: typeof import('./src/components/toolsBtn/RegreshBtn.vue')['default']

+ 51 - 2
src/components/common/WithIconSelect.vue

@@ -5,6 +5,10 @@ import type { IconDropdownItem } from '@/types/dataAnalysis'
 import { onMounted, ref, reactive, watch } from 'vue'
 import { initLoadResouce } from '@/utils/resource'
 import { useCommonStore } from '@/stores/useCommon'
+// import {
+//   getPfSelectTourShowState,
+//   setPfSelectTourShowState
+// } from '@/utils/localStorage/localStorage'
 
 const { selectInfo, tempMultipleChioce, saveSelectInfo, saveTempMultipleChioce } = useCommonStore()
 
@@ -18,6 +22,12 @@ const props = withDefaults(defineProps<DropdownInfo>(), {
   isRadio: true
 })
 
+// 下拉框
+const dromDownMenu = ref()
+
+// 引导层显示状态
+// const tourOpen = ref(false)
+
 /**
  * @description:  初始化选择信息
  * @return {*}
@@ -34,6 +44,9 @@ const isConfimClose = ref<Boolean>(false)
 // emits
 const emits = defineEmits(['changePf'])
 
+// 引导层是否已经展示过
+// const isTourShowed = ref<boolean>(false)
+
 // 下拉框
 const dropDownRef = ref<DropdownInstance>()
 
@@ -91,9 +104,22 @@ const cancleSelect = () => {
  */
 const dropdownVis = (state: boolean) => {
   if (state) {
+    // if (!isTourShowed.value) {
+    //   nextTick(() => {
+    //     tourOpen.value = true
+    //   })
+    // }
+
     // 打开的时候,需要备份一下当前选择
     Object.assign(backupInfo, JSON.parse(JSON.stringify(selectBaseInfo)))
   } else {
+    // 关闭的时候,同时把引导框关闭,并且标记一下
+    // if (!isTourShowed.value) {
+    //   isTourShowed.value = true
+    //   tourOpen.value = false
+    //   setPfSelectTourShowState(true)
+    // }
+
     // 关闭的时候,如果一个都没有选中,那么就需要把备份的信息恢复回去
     // 这里只针对于多选情况,因为单选的逻辑中不存在一个都没有选中的情况,因为无法取消已经选中
     // 而多选的情况下,因为即使可以取消,也不会立即改变selectInfo中的信息,只有点击了确认按钮才会改变,所以这里只需要恢复props的selectinfo就行了
@@ -144,6 +170,14 @@ const syncTempMultipleChioce = () => {
 }
 
 /**
+ * @description: 引导层关闭
+ * @return {*}
+ */
+// const tourClose = () => {
+//   setPfSelectTourShowState(false)
+// }
+
+/**
  * @description: 监听selectinfo的变化,然后同步到页面上
  * @return {*}
  */
@@ -185,8 +219,8 @@ const initSelectInfo = () => {
 initSelectInfo()
 
 onMounted(() => {
+  // isTourShowed.value = getPfSelectTourShowState() ?? false
   // 去加载所有需要的资源
-
   initLoadResouce(resourceInfo).then((data) => {
     Object.assign(blobUrlInfo, data)
   })
@@ -218,7 +252,7 @@ onMounted(() => {
         </el-icon>
       </span>
       <template #dropdown>
-        <el-dropdown-menu :class="{ radioMenu: isRadio }">
+        <el-dropdown-menu ref="dromDownMenu" :class="{ radioMenu: isRadio }">
           <el-dropdown-item
             v-for="item in selectBaseInfo"
             :key="item.value"
@@ -243,6 +277,21 @@ onMounted(() => {
         </span>
       </template>
     </el-dropdown>
+    <!-- 引导 -->
+    <!-- <el-tour
+      @close="tourClose"
+      v-if="!isRadio && !isTourShowed"
+      v-model="tourOpen"
+      type="primary"
+      :mask="false"
+    >
+      <el-tour-step
+        :target="dromDownMenu?.$el"
+        title="多选框"
+        placement="right-start"
+        description="多选框需要点击确定后才会发送请求."
+      />
+    </el-tour> -->
   </div>
 </template>
 

+ 1 - 1
src/components/dataAnalysis/DropDownSelection.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-23 14:42:47
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-09 16:18:29
+ * @LastEditTime: 2024-10-11 15:34:29
  * @FilePath: \Game-Backstage-Management-System\src\components\dataAnalysis\DropDownSelection.vue
  * @Description: 下拉选择框,可用于分类字段或者切换平台等
  * 

+ 11 - 6
src/components/form/FileUpload.vue

@@ -172,7 +172,6 @@ defineExpose({
           <br />
           <p>
             <b>allEventTable</b>用于存放所有需要更新或者需要新增的事件,<b>以数组形式传入.</b>
-
             如果是需要更新的事件,需要提供<b>id</b>字段,否则不需要。如果不传入id字段则<b
               >默认为新增</b
             >
@@ -183,13 +182,17 @@ defineExpose({
             >用于存放所有的事件选项,以<b>对象</b>形式传入,<b>对象的键为该选项所对应的事件的actionId</b>,
             同样,新增的选项不需要传入id字段,如果不传入id字段则<b>默认为新增</b>
           </p>
+          <br />
+          <p>
+            <b>请确保上传的选项对应的均是同一游戏的选项,否则可能会上传失败</b>
+          </p>
           <pre>
                     <code>
 {
     "allEventTable": [
       // 更新
         {
-            "id": 1,
+            "id": 1,  // 更新需要传入id
             "gid": "1200",
             "actionId": "123",
             "actionName": "第二关过关",
@@ -205,12 +208,13 @@ defineExpose({
             "remark": "t"
         }
     ],
+
     // 选项的键需要对应对应事件的actionId
-    "allOptionsInfo": {
+    "allOptionsInfo": { 
       // 更新  
-        "button": [
+        "123": [
             {
-                "id": 1,
+                "id": 1,  // 更新需要传入id
                 "optionId": "test",
                 "optionName": "test",
                 "optionType": "string",
@@ -218,7 +222,8 @@ defineExpose({
             }
         ],
         // 新增
-        "123":[
+        // 如果不存在这个actionid则视为新增
+        "888":[
             {
                 "optionId": "ba",
                 "optionName": "bgbb",

+ 3 - 3
src/router/index.ts

@@ -2,8 +2,8 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:06:49
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-10 17:35:00
- * @FilePath: \Game-Backstage-Management-System\src\router\index.ts
+ * @LastEditTime: 2024-10-11 16:42:42
+ * @FilePath: \无标题 (工作区)c:\Users\NINGMEI\Desktop\Game-Backstage-Management-System\src\router\index.ts
  * @Description:
  *
  */
@@ -20,7 +20,7 @@ const routes = [
   {
     path: '/index',
     name: 'Index',
-    redirect: '/index/home/overView',
+    redirect: '/home/overView',
     component: () => import('@/views/Index.vue'),
     children: [...HomeRoutes, ...AppManage]
   },

+ 2 - 2
src/stores/useTable.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-22 10:05:10
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-08-28 11:44:55
+ * @LastEditTime: 2024-10-11 14:57:48
  * @FilePath: \Game-Backstage-Management-System\src\stores\useTable.ts
  * @Description:
  *
@@ -23,7 +23,7 @@ export const useTableStore = defineStore('tableStore', () => {
   // 用户表查询的时候的参数
   const playerQueryInfo = reactive({
     gid: '1001',
-    pf: 'web'
+    pf: 'wx'
   })
 
   // 更新用户表查询参数

+ 1 - 30
src/utils/axios/auth.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-21 11:12:21
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-10 17:29:59
+ * @LastEditTime: 2024-10-10 18:31:10
  * @FilePath: \Game-Backstage-Management-System\src\utils\axios\auth.ts
  * @Description:
  *
@@ -12,35 +12,6 @@ import { ElMessage } from 'element-plus'
 import { MessageType } from '@/types/res'
 import { getLoginState } from '../localStorage/localStorage'
 
-// export const authToken = () => {
-//   return new Promise((reslove, reject) => {
-//     if (!getLoginState()) {
-//       ElMessage({
-//         type: 'warning',
-//         message: '请先登录',
-//         duration: 1500
-//       })
-//       reject(false)
-
-//       // return // 如果没有登录,就跳转到登录页面
-//     } else {
-//       reslove(true)
-//     }
-//     // let refreshToken = localStorage.getItem('refreshToken')
-//     // let token = localStorage.getItem('token')
-//     // if (refreshToken || token) {
-//     //   reslove(true)
-//     // } else {
-//     //   ElMessage({
-//     //     type: MessageType.Warning,
-//     //     message: '请先登录',
-//     //     duration: 1500
-//     //   })
-//     //   reject(false)
-//     // }
-//   })
-// }
-
 export const authLogin = (): boolean => {
   const state = getLoginState()
   if (!state) {

+ 21 - 23
src/utils/axios/axiosInstance.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 17:18:52
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-10 17:14:03
+ * @LastEditTime: 2024-10-10 18:31:00
  * @FilePath: \Game-Backstage-Management-System\src\utils\axios\axiosInstance.ts
  * @Description:
  *
@@ -13,7 +13,7 @@ import router from '@/router'
 import { ElMessage } from 'element-plus'
 import { useRequest } from '@/hooks/useRequest'
 import { MessageType } from '@/types/res'
-import { getToken, refreshToken, setToken } from '../token/token'
+import { getToken, refreshToken, setToken, removeAllToeken } from '../token/token'
 import { setLoginState } from '../localStorage/localStorage'
 
 const { baseURL } = useRequest()
@@ -29,6 +29,22 @@ const axiosInstance = axios.create({
 let isRefreshing = false // 是否正在刷新token
 let requestQueue: any[] = [] // 存储请求队列
 
+/**
+ * @description: 未登录的情况下展示的信息
+ * @param {*} ElMessage
+ * @return {*}
+ */
+const showUnloginInfo = (msg: string = '请先登录') => {
+  ElMessage({
+    type: MessageType.Warning,
+    message: msg,
+    duration: 1500
+  })
+  removeAllToeken()
+  setLoginState(false)
+  router.push('/login')
+}
+
 // 添加响应拦截器
 axiosInstance.interceptors.response.use(
   async function (response) {
@@ -36,13 +52,7 @@ axiosInstance.interceptors.response.use(
 
     // -2是token为空的情况
     if (code === -2) {
-      ElMessage({
-        type: MessageType.Warning,
-        message: '请先登录',
-        duration: 1500
-      })
-      setLoginState(false)
-      router.push('/login')
+      showUnloginInfo()
     }
     // -1是token过期的情况
     if (code === -1) {
@@ -60,24 +70,12 @@ axiosInstance.interceptors.response.use(
               requestQueue = []
               return axiosInstance(config)
             } else {
-              ElMessage({
-                type: MessageType.Warning,
-                message: '登录已过期,请重新登陆',
-                duration: 1500
-              })
-              setLoginState(false)
-              router.push('/login')
+              showUnloginInfo('登录已过期,请重新登陆')
             }
           })
           .catch((err) => {
             console.log(err)
-            ElMessage({
-              type: MessageType.Warning,
-              message: '登录已过期,请重新登陆',
-              duration: 1500
-            })
-            setLoginState(false)
-            router.push('/login')
+            showUnloginInfo('登录已过期,请重新登陆')
           })
           .finally(() => {
             isRefreshing = false

+ 34 - 7
src/utils/localStorage/localStorage.ts

@@ -6,13 +6,15 @@
  */
 const getLocalInfo = (name: string, prop?: string): string | string[] => {
   let selectInfo = localStorage.getItem(name)
-  if (selectInfo) {
-    let jsonSelectInfo = JSON.parse(selectInfo)
+  let result = ''
+  if (!selectInfo) return result
 
-    if (prop) return jsonSelectInfo[prop]
-    else return jsonSelectInfo
-  }
-  return ''
+  let jsonSelectInfo = JSON.parse(selectInfo)
+
+  if (prop) result = jsonSelectInfo[prop]
+  else result = jsonSelectInfo
+
+  return result
 }
 
 /**
@@ -50,4 +52,29 @@ const getLoginState = (): boolean => {
   return JSON.parse(localStorage.getItem('loginState') as string) as boolean
 }
 
-export { getLocalInfo, saveLocalInfo, setLoginState, getLoginState }
+/**
+ * @description: 设置平台选择下拉框的引导层的显示状态
+ * @param {boolean} state 状态
+ * @return {*}
+ */
+const setPfSelectTourShowState = (state: boolean) => {
+  localStorage.setItem('pfSelectTourShowState', JSON.stringify(state))
+}
+
+/**
+ * @description:
+ * @param {*} boolean
+ * @return {*}
+ */
+const getPfSelectTourShowState = (): boolean => {
+  return JSON.parse(localStorage.getItem('pfSelectTourShowState') as string)
+}
+
+export {
+  getLocalInfo,
+  saveLocalInfo,
+  setLoginState,
+  getLoginState,
+  setPfSelectTourShowState,
+  getPfSelectTourShowState
+}

+ 35 - 1
src/utils/token/token.ts

@@ -56,4 +56,38 @@ const refreshToken = async () => {
   )
 }
 
-export { getToken, setToken, getrefreshToken, setRefreshToken, refreshToken }
+/**
+ * @description: 移除token
+ * @return {*}
+ */
+const removeToken = () => {
+  localStorage.removeItem(TokenKey)
+}
+
+/**
+ * @description: 移除refreshtoken
+ * @return {*}
+ */
+const removeRefreshToken = () => {
+  localStorage.removeItem(RefreshTokenKey)
+}
+
+/**
+ * @description: 移除所有token
+ * @return {*}
+ */
+const removeAllToeken = () => {
+  removeToken()
+  removeRefreshToken()
+}
+
+export {
+  getToken,
+  setToken,
+  getrefreshToken,
+  setRefreshToken,
+  refreshToken,
+  removeToken,
+  removeRefreshToken,
+  removeAllToeken
+}

+ 114 - 65
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-10 15:40:15
+ * @LastEditTime: 2024-10-11 17:56:04
  * @FilePath: \Game-Backstage-Management-System\src\views\AppManage\EventManageView.vue
  * @Description: 
  * 
@@ -61,30 +61,46 @@ const headerAddPath = (info: any) => {
  * @param {*} msg 提示信息,用于展示上传之后返回的消息
  * @return {*}
  */
-const submitUpload = async (reqList: Array<Promise<boolean>>, msg?: string) => {
-  await Promise.allSettled(reqList).then((res) => {
-    if (
-      res.every((item) => {
-        return item.status === 'fulfilled' && item.value === true
-      })
-    ) {
+const submitUpload = async (reqList: Array<Promise<boolean>>, msg?: string): Promise<boolean> => {
+  const result = await Promise.allSettled(reqList).then((res) => {
+    const failedList = res.filter((item: any) => item.value === false)
+    const failedCount = failedList.length
+    const totalCount = res.length
+    let state = true
+
+    if (failedCount === 0) {
+      // 全部成功
       ElNotification({
         type: 'success',
         title: '上传完成',
-        message: `${msg}上传成功`,
-        position: 'top-left'
+        message: `${msg}全部上传成功`,
+        position: 'top-left',
+        duration: 3000
       })
-    } else {
+    } else if (failedCount === totalCount) {
+      // 全部失败
       ElNotification({
         type: 'error',
         title: '上传完成',
-        message: `${msg}部上传失败,请检查参数`,
-        duration: 3000,
+        message: `${msg}部上传失败,请检查参数`,
+        duration: 5000,
         position: 'top-left'
       })
-      // ElMessage.error()
+      state = false
+    } else {
+      // 部分失败
+      ElNotification({
+        type: 'warning',
+        title: '上传完成',
+        message: `${msg}部分上传成功`,
+        position: 'top-left',
+        duration: 5000
+      })
     }
+    return state
   })
+
+  return result
 }
 
 /**
@@ -110,14 +126,21 @@ const getTableData = async (
       ...otherInfo
     })
     .then(async (res) => {
+      let resultData: any = []
       let resData = JSON.parse(JSON.stringify(res))
       let result = []
-      if (!resData.data) return []
-      // nowOptionList.push(...resData.data)
-      if (resData.count > total) {
+      // if (!resData.data) return []
+      // // nowOptionList.push(...resData.data)
+      // if (resData.count > total) {
+      //   result = await getTableData(url, otherInfo, total, limit)
+      // }
+      if (resData.data && resData.count > total) {
         result = await getTableData(url, otherInfo, total, limit)
+        resultData = [...resData.data, ...result]
       }
-      return [...resData.data, ...result]
+
+      return resultData
+      // return [...resData.data, ...result]
     })
     .catch((err) => {
       console.log(err)
@@ -176,11 +199,13 @@ const getAllTable = async <T extends 'all' | 'event' | 'option' = 'all'>(
 ): Promise<GetTableReturn<T>> => {
   let allEventTable: Array<any> = [],
     allOptionsInfo: any = null
+  allEventTable = await getTableData(AllApi.gameActionList, { gid: selectInfo.gid })
+  // 只需要事件列表在这里就返回
   if (table === 'event') {
-    allEventTable = await getTableData(AllApi.gameActionList, { gid: selectInfo.gid })
     return { allEventTable } as GetTableReturn<T>
   }
 
+  // 只需要选项在这里就只返回选项
   if (table === 'option') {
     let optionReqList = allEventTable.map((item) => {
       return { actionId: parseInt(item.id) }
@@ -240,6 +265,8 @@ const uploadSuccess = async (data: any) => {
   // 开始上传事件
   let eventReqList: Array<Promise<boolean>> = []
   let eventReqUrl = AllApi.setGameAction
+  let eventUploadResult = false
+
   if (Array.isArray(uploadEventTable) && uploadEventTable.length) {
     // 将新事件和旧事件区分,对于新事件走新增,对于旧事件走更新
     uploadEventTable.map((item) => {
@@ -252,8 +279,7 @@ const uploadSuccess = async (data: any) => {
       let eventReq = axiosInstance
         .post(eventReqUrl, otherInfo)
         .then((res: any) => {
-          if (res.code === 0) return true
-          return false
+          return res.code === 0
         })
         .catch((err) => {
           console.log(err)
@@ -261,51 +287,74 @@ const uploadSuccess = async (data: any) => {
         })
       eventReqList.push(eventReq) // 统一放入请求列表中
     })
-    await submitUpload(eventReqList, '事件') // 等待所有的事件请求完成
-  }
-  ;({ allEventTable, allOptionsInfo } = await getAllTable()) // 重新获取所有事件列表和选项列表
-  let optionsReqList: Array<Promise<boolean>> = []
-
-  allEventTable.map((item) => {
-    // 在上传的事件列表中,找到有对应的事件的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 = {}
-        // 分出来哪些是新增加的选项,哪些是需要更新的选项
-        // 新增的选项需要加入的是事件列表的主键,而更新中需要加入的是option的id
-        if (nowOptionItem.some((k) => k.id === i.id)) {
-          reqParams = { id, ...otherInfo }
-
-          optionReqUrl = AllApi.updateGameActionOption
-        } else {
-          actionId = item.id
-          reqParams = { actionId, ...otherInfo }
-          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)
-      })
+
+    eventUploadResult = await submitUpload(eventReqList, '事件') // 等待所有的事件请求完成
+    // 如果事件上传全部失败,那么就不要再上传选项了
+    if (eventUploadResult) {
+      ;({ allEventTable, allOptionsInfo } = await getAllTable()) // 重新获取所有事件列表和选项列表
+      let optionsReqList: Array<Promise<boolean>> = []
+      if (uploadOptionsInfo) {
+        // 开始上传选项
+        allEventTable.map((item) => {
+          // 在上传的事件列表中,找到有对应的事件的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 = {}
+              // 分出来哪些是新增加的选项,哪些是需要更新的选项
+              // 新增的选项需要加入的是事件列表的主键,而更新中需要加入的是option的id
+              if (nowOptionItem.some((k) => k.id === i.id)) {
+                reqParams = { id, ...otherInfo }
+
+                optionReqUrl = AllApi.updateGameActionOption
+              } else {
+                actionId = item.id
+                reqParams = { actionId, ...otherInfo }
+                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, '选项') // 等待所有选项上传完成
+      } else {
+        ElNotification({
+          type: 'warning',
+          title: '没有选项参数',
+          message: `上传选项为空`,
+          position: 'top-left',
+          duration: 5000
+        })
+      }
     }
-  })
-  await submitUpload(optionsReqList, '选项') // 等待所有选项上传完成
+  } else {
+    ElNotification({
+      type: 'error',
+      title: '上传参数有误',
+      message: `上传参数为空,请检查参数`,
+      position: 'top-left',
+      duration: 5000
+    })
+  }
+
   uploadRef.value?.uploadCallback()
   eventTableRef.value?.updateData()
 }

+ 3 - 3
src/views/Index.vue

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 14:06:49
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-10-10 17:43:52
+ * @LastEditTime: 2024-10-11 09:06:56
  * @FilePath: \Game-Backstage-Management-System\src\views\Index.vue
  * @Description: 
  * 
@@ -20,6 +20,7 @@ import DropDownSelection from '@/components/dataAnalysis/DropDownSelection.vue'
 import { useCommonStore } from '@/stores/useCommon'
 import { initLoadResouce } from '@/utils/resource'
 import { setLoginState } from '@/utils/localStorage/localStorage'
+import { removeAllToeken } from '@/utils/token/token'
 
 const route = useRoute()
 const { selectInfo, allGameInfo, saveSelectInfo } = useCommonStore()
@@ -66,8 +67,7 @@ const logOut = () => {
     duration: 1000
   })
   setLoginState(false)
-  localStorage.removeItem('token')
-  localStorage.removeItem('refreshToken')
+  removeAllToeken()
   router.push('/login')
 }