|
@@ -2,12 +2,14 @@
|
|
|
* @Author: fxs bjnsfxs@163.com
|
|
|
* @Date: 2024-09-02 17:57:15
|
|
|
* @LastEditors: fxs bjnsfxs@163.com
|
|
|
- * @LastEditTime: 2024-10-11 17:56:04
|
|
|
+ * @LastEditTime: 2024-10-12 16:45:15
|
|
|
* @FilePath: \Game-Backstage-Management-System\src\views\AppManage\EventManageView.vue
|
|
|
* @Description:
|
|
|
*
|
|
|
-->
|
|
|
<script setup lang="ts">
|
|
|
+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'
|
|
@@ -23,6 +25,57 @@ import { downLoadData } from '@/utils/table/table'
|
|
|
import { resetTimeToMidnight } from '@/utils/common'
|
|
|
import router from '@/router'
|
|
|
|
|
|
+interface uploadEvent {
|
|
|
+ id?: number // 更新需要传入id
|
|
|
+ gid: string
|
|
|
+ actionId: string
|
|
|
+ actionName: string
|
|
|
+ status: number
|
|
|
+ remark?: string
|
|
|
+}
|
|
|
+
|
|
|
+interface UploadOption {
|
|
|
+ id?: number // 更新需要传入id
|
|
|
+ optionId: string
|
|
|
+ optionName: string
|
|
|
+ optionType: string
|
|
|
+ actionId: number
|
|
|
+ status: number
|
|
|
+}
|
|
|
+
|
|
|
+interface DownLoadEvent {
|
|
|
+ actionId: string
|
|
|
+ actionName: string
|
|
|
+ createdAt: string
|
|
|
+ gid: string
|
|
|
+ id: number
|
|
|
+ remark: string
|
|
|
+ status: number
|
|
|
+ updatedAt: string
|
|
|
+}
|
|
|
+
|
|
|
+interface DownLoadOption {
|
|
|
+ actionId: number
|
|
|
+ createdAt: string
|
|
|
+ id: number
|
|
|
+ optionId: string
|
|
|
+ optionName: string
|
|
|
+ optionType: string
|
|
|
+ status: number
|
|
|
+ updatedAt: string
|
|
|
+}
|
|
|
+
|
|
|
+type GetTableReturn<T> = T extends 'all'
|
|
|
+ ? {
|
|
|
+ allEventTable: Array<DownLoadEvent>
|
|
|
+ allOptionsInfo: { [key: string]: Array<DownLoadOption> }
|
|
|
+ }
|
|
|
+ : T extends 'event'
|
|
|
+ ? { allEventTable: Array<DownLoadEvent> }
|
|
|
+ : T extends 'option'
|
|
|
+ ? { allOptionsInfo: { [key: string]: Array<DownLoadOption> } }
|
|
|
+ : never
|
|
|
+
|
|
|
const { selectInfo } = useCommonStore()
|
|
|
|
|
|
const { AllApi } = useRequest()
|
|
@@ -56,47 +109,57 @@ const headerAddPath = (info: any) => {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * @description: 展示上传之后的反馈信息
|
|
|
+ * @param {*} state 这个状态只表示是否全部成功,其余情况皆为false
|
|
|
+ * @param {*} name 区分是事件还是选项
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const showUploadMsg = (failedCount: number, totalCount: number, name: string): boolean => {
|
|
|
+ if (failedCount < 0) throw new Error('Error!FailedCount < 0')
|
|
|
+
|
|
|
+ let state = true
|
|
|
+ let duration = 3000
|
|
|
+ let title = '上传成功'
|
|
|
+ let position: 'top-left' | 'top-right' = 'top-left'
|
|
|
+ let message: string = `${name}全部上传成功`
|
|
|
+ let type: 'success' | 'warning' | 'error' = 'success'
|
|
|
+
|
|
|
+ // 有上传失败的情况下
|
|
|
+ if (failedCount > 0) {
|
|
|
+ state = false
|
|
|
+ position = 'top-right'
|
|
|
+ duration = 8000
|
|
|
+ if (failedCount === totalCount) {
|
|
|
+ message = `${name}全部上传失败`
|
|
|
+ type = 'error'
|
|
|
+ } else {
|
|
|
+ message = `${name}部分上传失败`
|
|
|
+ type = 'warning'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ElNotification({
|
|
|
+ type,
|
|
|
+ title,
|
|
|
+ message,
|
|
|
+ duration,
|
|
|
+ position
|
|
|
+ })
|
|
|
+
|
|
|
+ return state
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* @description: 提交所有新上传的事件及选项请求
|
|
|
* @param {*} reqList 请求列表
|
|
|
* @param {*} msg 提示信息,用于展示上传之后返回的消息
|
|
|
* @return {*}
|
|
|
*/
|
|
|
-const submitUpload = async (reqList: Array<Promise<boolean>>, msg?: string): Promise<boolean> => {
|
|
|
+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',
|
|
|
- duration: 3000
|
|
|
- })
|
|
|
- } else if (failedCount === totalCount) {
|
|
|
- // 全部失败
|
|
|
- ElNotification({
|
|
|
- type: 'error',
|
|
|
- title: '上传完成',
|
|
|
- message: `${msg}全部上传失败,请检查参数`,
|
|
|
- duration: 5000,
|
|
|
- position: 'top-left'
|
|
|
- })
|
|
|
- state = false
|
|
|
- } else {
|
|
|
- // 部分失败
|
|
|
- ElNotification({
|
|
|
- type: 'warning',
|
|
|
- title: '上传完成',
|
|
|
- message: `${msg}部分上传成功`,
|
|
|
- position: 'top-left',
|
|
|
- duration: 5000
|
|
|
- })
|
|
|
- }
|
|
|
+ let state = showUploadMsg(failedCount, totalCount, msg)
|
|
|
return state
|
|
|
})
|
|
|
|
|
@@ -126,21 +189,14 @@ 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) {
|
|
|
- // result = await getTableData(url, otherInfo, total, limit)
|
|
|
- // }
|
|
|
- if (resData.data && resData.count > total) {
|
|
|
+ if (!resData.data) return []
|
|
|
+
|
|
|
+ if (resData.count > total) {
|
|
|
result = await getTableData(url, otherInfo, total, limit)
|
|
|
- resultData = [...resData.data, ...result]
|
|
|
}
|
|
|
-
|
|
|
- return resultData
|
|
|
- // return [...resData.data, ...result]
|
|
|
+ return [...resData.data, ...result]
|
|
|
})
|
|
|
.catch((err) => {
|
|
|
console.log(err)
|
|
@@ -159,19 +215,19 @@ const getTableData = async (
|
|
|
const batReqOptionsData = async (
|
|
|
url: string,
|
|
|
reqParams: Array<any>,
|
|
|
- eventTable: Array<any>
|
|
|
-): Promise<Object> => {
|
|
|
+ eventTable: Array<DownLoadEvent>
|
|
|
+): Promise<{ [key: string]: Array<DownLoadOption> }> => {
|
|
|
let reqList: Array<Promise<any>> = []
|
|
|
let finalResult: {
|
|
|
- [key: string]: Array<any>
|
|
|
+ [key: string]: Array<DownLoadOption>
|
|
|
} = {}
|
|
|
|
|
|
reqParams.map((item) => {
|
|
|
reqList.push(
|
|
|
getTableData(url, item)
|
|
|
.then((res) => {
|
|
|
- let actionId = eventTable.find((i) => i.id === item.actionId).actionId
|
|
|
- finalResult[actionId] = res
|
|
|
+ let actionId = eventTable.find((i) => i.id === item.actionId)?.actionId
|
|
|
+ if (actionId) finalResult[actionId] = res
|
|
|
})
|
|
|
.catch((err) => {
|
|
|
console.log(err)
|
|
@@ -182,24 +238,26 @@ const batReqOptionsData = async (
|
|
|
return finalResult
|
|
|
}
|
|
|
|
|
|
-type GetTableReturn<T> = T extends 'all'
|
|
|
- ? { allEventTable: Array<any>; allOptionsInfo: any }
|
|
|
- : T extends 'event'
|
|
|
- ? { allEventTable: Array<any> }
|
|
|
- : T extends 'option'
|
|
|
- ? { allOptionsInfo: any }
|
|
|
- : never
|
|
|
-
|
|
|
/**
|
|
|
* @description: 拿到事件数据和选项数据,首先需要拿到所有的事件列表,然后将他们的actionId抽出来形成一个列表,这个列表去作为optin的查询参数批量查询
|
|
|
* @return {*} 返回事件数据和选项数据
|
|
|
*/
|
|
|
const getAllTable = async <T extends 'all' | 'event' | 'option' = 'all'>(
|
|
|
- table?: T
|
|
|
+ table: T = 'all' as any
|
|
|
): Promise<GetTableReturn<T>> => {
|
|
|
- let allEventTable: Array<any> = [],
|
|
|
- allOptionsInfo: any = null
|
|
|
+ let allEventTable: Array<DownLoadEvent> = [],
|
|
|
+ allOptionsInfo: { [key: string]: Array<DownLoadOption> } = {}
|
|
|
+
|
|
|
allEventTable = await getTableData(AllApi.gameActionList, { gid: selectInfo.gid })
|
|
|
+
|
|
|
+ let optionReqList = allEventTable.map((item) => {
|
|
|
+ return { actionId: item.id }
|
|
|
+ })
|
|
|
+ allOptionsInfo = await batReqOptionsData(
|
|
|
+ AllApi.gameActionOptionList,
|
|
|
+ optionReqList,
|
|
|
+ allEventTable
|
|
|
+ )
|
|
|
// 只需要事件列表在这里就返回
|
|
|
if (table === 'event') {
|
|
|
return { allEventTable } as GetTableReturn<T>
|
|
@@ -207,14 +265,6 @@ const getAllTable = async <T extends 'all' | 'event' | 'option' = 'all'>(
|
|
|
|
|
|
// 只需要选项在这里就只返回选项
|
|
|
if (table === 'option') {
|
|
|
- let optionReqList = allEventTable.map((item) => {
|
|
|
- return { actionId: parseInt(item.id) }
|
|
|
- })
|
|
|
- allOptionsInfo = await batReqOptionsData(
|
|
|
- AllApi.gameActionOptionList,
|
|
|
- optionReqList,
|
|
|
- allEventTable
|
|
|
- )
|
|
|
return { allOptionsInfo } as GetTableReturn<T>
|
|
|
}
|
|
|
|
|
@@ -243,6 +293,124 @@ const startDownload = async () => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @description: 创建一个上传请求函数
|
|
|
+ * @param {*} url 请求地址
|
|
|
+ * @param {*} reqParams 请求参数
|
|
|
+ * @param {*} name 上传的是事件还是选项
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const createUploadReqFunc = async (url: string, reqParams: any, name: string): Promise<boolean> => {
|
|
|
+ let result: boolean = false
|
|
|
+ try {
|
|
|
+ const res: ResponseInfo = await axiosInstance.post<string, ResponseInfo>(url, reqParams)
|
|
|
+
|
|
|
+ if (res.code !== 0) {
|
|
|
+ ElNotification({
|
|
|
+ type: 'warning',
|
|
|
+ title: '事件上传失败',
|
|
|
+ dangerouslyUseHTMLString: true,
|
|
|
+ message: `${name}上传失败.<br/>${res.msg}`,
|
|
|
+ position: 'top-left',
|
|
|
+ duration: 8000
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ result = res.code === 0
|
|
|
+ } catch (err: any) {
|
|
|
+ ElNotification({
|
|
|
+ type: 'error',
|
|
|
+ title: '上传失败',
|
|
|
+ message: `${name}上传失败,请检查参数`,
|
|
|
+ position: 'top-right',
|
|
|
+ duration: 5000
|
|
|
+ })
|
|
|
+ console.log(err)
|
|
|
+ }
|
|
|
+ return result
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 上传所有事件
|
|
|
+ * @param {*} uploadEventTable 上传的事件列表
|
|
|
+ * @param {*} allEventTable 获取的事件列表
|
|
|
+ * @return {Promise<boolean>} 返回是否上传成功
|
|
|
+ */
|
|
|
+const uploadEvent = async (
|
|
|
+ uploadEventTable: Array<uploadEvent>,
|
|
|
+ allEventTable: Array<DownLoadEvent>
|
|
|
+): Promise<boolean> => {
|
|
|
+ let eventReqUrl = AllApi.setGameAction
|
|
|
+ let eventReqList: Array<Promise<boolean>> = []
|
|
|
+ uploadEventTable.map((item: uploadEvent) => {
|
|
|
+ let { id, ...otherInfo } = item
|
|
|
+ if (allEventTable.some((i: DownLoadEvent) => i.actionId === item.actionId)) {
|
|
|
+ eventReqUrl = AllApi.updateGameAction
|
|
|
+ }
|
|
|
+ let eventReq = createUploadReqFunc(eventReqUrl, otherInfo, item.actionName)
|
|
|
+ eventReqList.push(eventReq) // 统一放入请求列表中
|
|
|
+ })
|
|
|
+ return await submitUpload(eventReqList, '事件') // 等待所有的事件请求完成
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: 上传所有选项
|
|
|
+ * @param {*} uploadOptionsInfo 上传的选项列表
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+const uploadOpiton = async (uploadOptionsInfo: { [key: string]: Array<UploadOption> }) => {
|
|
|
+ const { allEventTable, allOptionsInfo } = await getAllTable() // 重新获取所有事件列表和选项列表
|
|
|
+ let optionsReqList: Array<Promise<boolean>> = []
|
|
|
+ if (Object.keys(uploadOptionsInfo).length) {
|
|
|
+ // 开始上传选项
|
|
|
+ allEventTable.map((item) => {
|
|
|
+ // 在上传的事件列表中,找到有对应的事件的actionid的那一组数据
|
|
|
+ let uploadOptionItem = uploadOptionsInfo[item.actionId]
|
|
|
+ // 在现有的事件列表中,找到对应事件的actionid的那一组数据
|
|
|
+ let nowOptionItem = allOptionsInfo[item.actionId] // 找到所有在已有事件列表中的选项列表
|
|
|
+
|
|
|
+ // 如果有已存在的事件,并且上传的选项列表中也有对应的actionid,则开始上传
|
|
|
+ if (uploadOptionItem) {
|
|
|
+ // 对找到的那一组数据进行循环,区分出来哪些是已有的,哪些是新上传的
|
|
|
+ // 新上传的需要给他加上actionid,然后上传,这个actionid其实是事件列表的id字段
|
|
|
+ uploadOptionItem.map((i) => {
|
|
|
+ const { id, actionId: originalActionId, ...otherInfo } = i // 上传参数拆分出来
|
|
|
+ const isUpdate = nowOptionItem.some((k) => k.id === id) // 判断是否是更新选项
|
|
|
+
|
|
|
+ // 设置请求 URL 和参数
|
|
|
+ const optionReqUrl = isUpdate ? AllApi.updateGameActionOption : AllApi.addGameActionOption
|
|
|
+ const reqParams = isUpdate
|
|
|
+ ? { id, ...otherInfo } // 更新选项
|
|
|
+ : { actionId: item.id, ...otherInfo } // 新增选项
|
|
|
+
|
|
|
+ let eventReq = createUploadReqFunc(optionReqUrl, reqParams, item.actionName)
|
|
|
+ optionsReqList.push(eventReq) // 统一放入请求列表中
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ setTimeout(() => {
|
|
|
+ ElNotification({
|
|
|
+ type: 'warning',
|
|
|
+ title: `没有对应事件`,
|
|
|
+ message: `没有${item.actionName}事件,为事件添加的选项无效`,
|
|
|
+ position: 'top-right',
|
|
|
+ duration: 8000
|
|
|
+ })
|
|
|
+ }, 0)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ await submitUpload(optionsReqList, '选项') // 等待所有选项上传完成
|
|
|
+ } else {
|
|
|
+ ElNotification({
|
|
|
+ type: 'warning',
|
|
|
+ title: '没有选项被上传',
|
|
|
+ message: `上传选项为空`,
|
|
|
+ position: 'top-right',
|
|
|
+ duration: 8000
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 上传选项的时候,选项的键要设置为actionid
|
|
|
// 需要先上传事件,然后上传完了,用上传的选项中的第一个(如果有)的actionid去找到对应的事件的ID(不是actionid),然后作为选项上传的id
|
|
|
/**
|
|
@@ -254,96 +422,27 @@ const startDownload = async () => {
|
|
|
* @param {*} data 上传的文件数据,里面包含allEventTable:所有的事件列表,allOptionsInfo:所有选项列表
|
|
|
* @return {*}
|
|
|
*/
|
|
|
-const uploadSuccess = async (data: any) => {
|
|
|
+const uploadSuccess = async (data: {
|
|
|
+ allEventTable: Array<uploadEvent>
|
|
|
+ allOptionsInfo: { [key: string]: Array<UploadOption> }
|
|
|
+}) => {
|
|
|
let uploadEventTable = data.allEventTable
|
|
|
let uploadOptionsInfo = data.allOptionsInfo
|
|
|
- let allEventTable: Array<any> = [],
|
|
|
- allOptionsInfo: { [key: string]: any } = {}
|
|
|
+
|
|
|
+ let allEventTable: Array<DownLoadEvent> = []
|
|
|
+
|
|
|
// 上传的事件列表有值,则开始上传
|
|
|
;({ allEventTable } = await getAllTable('event')) // 获取所有事件列表和选项列表
|
|
|
|
|
|
- // 开始上传事件
|
|
|
- let eventReqList: Array<Promise<boolean>> = []
|
|
|
- let eventReqUrl = AllApi.setGameAction
|
|
|
let eventUploadResult = false
|
|
|
|
|
|
- if (Array.isArray(uploadEventTable) && uploadEventTable.length) {
|
|
|
+ if (Array.isArray(uploadEventTable) && uploadEventTable.length > 0) {
|
|
|
// 将新事件和旧事件区分,对于新事件走新增,对于旧事件走更新
|
|
|
- uploadEventTable.map((item) => {
|
|
|
- let { id, createdAt, updatedAt, ...otherInfo } = item
|
|
|
- if (allEventTable.some((i) => i.actionId === item.actionId)) {
|
|
|
- eventReqUrl = AllApi.updateGameAction
|
|
|
- } else {
|
|
|
- eventReqUrl = AllApi.setGameAction
|
|
|
- }
|
|
|
- let eventReq = axiosInstance
|
|
|
- .post(eventReqUrl, otherInfo)
|
|
|
- .then((res: any) => {
|
|
|
- return res.code === 0
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.log(err)
|
|
|
- return false
|
|
|
- })
|
|
|
- eventReqList.push(eventReq) // 统一放入请求列表中
|
|
|
- })
|
|
|
|
|
|
- eventUploadResult = await submitUpload(eventReqList, '事件') // 等待所有的事件请求完成
|
|
|
+ eventUploadResult = await uploadEvent(uploadEventTable, allEventTable)
|
|
|
// 如果事件上传全部失败,那么就不要再上传选项了
|
|
|
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
|
|
|
- })
|
|
|
- }
|
|
|
+ uploadOpiton(uploadOptionsInfo)
|
|
|
}
|
|
|
} else {
|
|
|
ElNotification({
|