Pārlūkot izejas kodu

更新玩家管理、游戏管理布局,更新玩家管理的数据获取逻辑,更新趋势图组件数据获取逻辑,更新留存率页面格式

fxs 9 mēneši atpakaļ
vecāks
revīzija
a2e258ad93

+ 5 - 5
index.html

@@ -1,10 +1,10 @@
-<!DOCTYPE html>
+<!doctype html>
 <html lang="en">
   <head>
-    <meta charset="UTF-8">
-    <link rel="icon" href="/favicon.ico">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Vite App</title>
+    <meta charset="UTF-8" />
+    <link rel="icon" href="/logo.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>淳皓游戏管理平台</title>
   </head>
   <body>
     <div id="app"></div>

BIN
public/favicon.ico


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
public/logo.svg


+ 37 - 9
src/components/Table.vue

@@ -1,3 +1,12 @@
+<!--
+ * @Author: fxs bjnsfxs@163.com
+ * @Date: 2024-08-20 18:16:18
+ * @LastEditors: fxs bjnsfxs@163.com
+ * @LastEditTime: 2024-08-30 17:50:03
+ * @FilePath: \Game-Backstage-Management-System\src\components\Table.vue
+ * @Description: 
+ * 
+-->
 <script setup lang="ts">
 import type { PropsParams } from '@/types/table'
 import { FilterType, FieldSpecialEffectType } from '@/types/table'
@@ -138,12 +147,13 @@ const getData = () => {
             .filter((item) => item !== undefined)
           if (index === 0) rowData[item.name] = '均值'
           else if (item.name === 'count') rowData[item.name] = sum
-          else
-            rowData[item.name] =
-              (
-                averageList.reduce((accumulator, currentValue) => accumulator + currentValue, 0) /
-                averageList.length
-              ).toFixed(2) + '%'
+          else {
+            let num =
+              averageList.reduce((accumulator, currentValue) => accumulator + currentValue, 0) /
+              averageList.length
+
+            rowData[item.name] = isNaN(num) ? 0 : num.toFixed(2)
+          }
         })
         insertRow(0, rowData)
       }
@@ -251,6 +261,17 @@ const changeDataList = watch(
   }
 )
 
+// 监听gid的变化
+const changeGid = watch(
+  () => props.requestConfig?.otherOptions.gid,
+  () => {
+    getData()
+  }
+)
+
+// 没有传入请求配置就关掉这个监听
+if (!props.requestConfig) changeGid()
+
 // 没传入datalist则取消该监听
 if (!props.dataList) {
   changeDataList()
@@ -266,8 +287,8 @@ defineExpose({
 })
 
 onMounted(() => {
-  if (props.dataLoading !== undefined) {
-    loading.value = props.dataLoading
+  if (props.loadingState !== undefined) {
+    loading.value = props.loadingState
   }
   getData()
 })
@@ -421,7 +442,14 @@ onMounted(() => {
 
               <el-text v-else>
                 <!-- 其他列按默认方式显示 -->
-                {{ scope.row[item.name] }}
+                {{
+                  props.needAverage &&
+                  scope.row[item.name] !== undefined &&
+                  item.name !== 'count' &&
+                  item.name !== 'date'
+                    ? scope.row[item.name] + '%'
+                    : scope.row[item.name]
+                }}
               </el-text>
             </template>
           </el-table-column>

+ 42 - 4
src/components/dataAnalysis/HeaderCard.vue

@@ -67,18 +67,29 @@ const shortcuts = [
 ]
 
 // 选择的日期
-const selectDate = ref(shortcuts[0].value())
+const selectDate = ref<Array<Date>>(shortcuts[0].value())
 
+// 日期变化
 const dateChange = (val: any) => {
   emits('changeDate', val)
 }
 
+// 平台变化
 const changePf = (val: any) => {
   emits('changePf', val)
 }
 
+// 控制日期范围
+/**
+ * @description: 禁止选取今天之后的日期
+ * @param {*} date
+ * @return {*}
+ */
+const disableDate = (time: Date) => {
+  return time.getTime() > Date.now()
+}
+
 onMounted(() => {
-  // 这里是为了让外面的组件能够获取到这个组件的默认选择日期,以便发送请求
   dateChange(selectDate.value)
 })
 </script>
@@ -100,15 +111,17 @@ onMounted(() => {
     <div v-if="props.openDateSelect" class="datePicker">
       <el-date-picker
         v-model="selectDate"
+        :disabled-date="disableDate"
+        :unlink-panels="false"
         @change="dateChange"
         type="daterange"
-        unlink-panels
         range-separator="至"
         start-placeholder="Start date"
         end-placeholder="End date"
         :shortcuts="shortcuts"
         :size="'small'"
-      />
+      >
+      </el-date-picker>
     </div>
   </div>
 </template>
@@ -144,4 +157,29 @@ onMounted(() => {
   /* 可以将他单独的右对齐 */
   margin-left: auto;
 }
+
+.dateItem {
+  display: inline-block;
+  width: 100%;
+  height: 100%;
+  border-radius: 4%;
+}
+
+.canSelect {
+  background-color: #cce3f8;
+  color: black;
+}
+
+.selected {
+  background-color: #2d8cf0;
+}
+
+.disableSelect {
+  color: #c7c9cc;
+  background-color: white;
+}
+
+.disableSelect:hover {
+  cursor: no-drop;
+}
 </style>

+ 21 - 15
src/components/dataAnalysis/TemporalTrend.vue

@@ -23,8 +23,11 @@ const iconSize = ref(20) // 图标的尺寸
 // 表格数据
 const tableDataList = reactive<Array<any>>([])
 
-const loading = ref<Boolean>(true) // 是否在加载
-const dataState = ref<Boolean>(false) //数据是否加载成功
+// 数据的加载情况
+const loadDataState = reactive({
+  loading: true,
+  state: false
+})
 
 // 配置表格分页数据
 const paginationConfig = reactive<TablePaginationSetting>({
@@ -46,7 +49,7 @@ const chartInfo = reactive<OptionsProps>({
   legendData: [],
   xAxisData: [],
   seriesData: [],
-  loadingState: ref(loading) as unknown as boolean
+  loadingState: loadDataState.loading
 })
 
 /**
@@ -88,8 +91,10 @@ const createTableData = (data: any) => {
   // 把所有的表格需要的数据假如valInfo,其中index字段需要单独拿出来用x轴的信息填充
   props.resDataFieldsInfo['values'].map((key: string) => {
     valInfo[key] = Object.values(data[key])
+    // console.log(data[key])
   })
   valInfo['index'] = xInfo
+  // console.log(valInfo)
   // 生成表格数据
   let newList = reactive<Array<any>>([])
 
@@ -98,14 +103,13 @@ const createTableData = (data: any) => {
   let fieldList = tableFieldsInfo.map((field) => field.name)
 
   // 生成每一行的数据
-  xInfo.map(() => {
+  for (let i = 0; i < xInfo.length; i++) {
     let newItem: any = {}
-    fieldList.map((item, index) => {
-      newItem[item] = valInfo[item][index]
+    fieldList.map((item) => {
+      newItem[item] = valInfo[item][i]
     })
     newList.push(newItem)
-  })
-
+  }
   tableDataList.splice(0, tableDataList.length, ...newList)
   paginationConfig.total = xInfo.length
 }
@@ -139,7 +143,7 @@ const getData = async (type: number) => {
     .post(props.requestConfig.url, { ...props.requestConfig.otherOptions, type })
     .then((info) => {
       let data = info.data
-      dataState.value = true
+      loadDataState.state = true
       // 生成表格字段
       createTableField()
       // 生成表格数据
@@ -160,11 +164,11 @@ const getData = async (type: number) => {
       }
     })
     .catch((err) => {
-      dataState.value = false
+      loadDataState.state = false
       console.log(err)
     })
     .finally(() => {
-      loading.value = false
+      loadDataState.loading = false
     })
 }
 
@@ -195,8 +199,10 @@ watch(
     deep: true
   }
 )
-getData(1)
+
 onMounted(() => {
+  if (!props.waitTimeSelect) getData(1)
+
   if (props.tabInfo) activeTab.value = props.tabInfo[0].name
 })
 </script>
@@ -229,7 +235,7 @@ onMounted(() => {
         <div class="chartContent" v-if="selectShape === 1">
           <div class="yesterDayDataBox">
             <StatisticText
-              v-if="staticFields && dataState"
+              v-if="staticFields && loadDataState.state"
               :fields-info="staticFields"
               :value-class="'chartStaticValue'"
             ></StatisticText>
@@ -240,7 +246,7 @@ onMounted(() => {
             :legend-data="chartInfo.legendData"
             :series-data="chartInfo.seriesData"
             :x-axis-data="chartInfo.xAxisData"
-            :loading-state="chartInfo.loadingState"
+            :loading-state="loadDataState.loading"
             class="chart"
           ></TimeLineChart>
         </div>
@@ -248,8 +254,8 @@ onMounted(() => {
           <Table
             ref="chartTable"
             v-if="props.needTable"
+            :loading-state="loadDataState.loading"
             :data-list="tableDataList"
-            :data-loading="loading"
             :need-rowindex="true"
             :need-average="false"
             :need-right-tools="false"

+ 3 - 3
src/hooks/useRequest.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-20 17:24:06
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-08-30 12:01:31
+ * @LastEditTime: 2024-08-30 17:26:07
  * @FilePath: \Game-Backstage-Management-System\src\hooks\useRequest.ts
  * @Description:
  *
@@ -16,8 +16,8 @@ import type { AxiosResponse } from 'axios'
 import type { ResponseInfo } from '@/types/res'
 
 export function useRequest() {
-  // const baseIp = 'http://server.ichunhao.cn' // 线上
-  const baseIp = 'http://192.168.1.139:8000' // 本地
+  const baseIp = 'http://server.ichunhao.cn' // 线上
+  // const baseIp = 'http://192.168.1.139:8000' // 本地
 
   const AllApi = {
     mock: `http://127.0.0.1:8003/mock`,

+ 3 - 1
src/types/dataAnalysis.ts

@@ -2,7 +2,7 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-23 14:58:29
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-08-30 10:36:03
+ * @LastEditTime: 2024-08-30 17:10:35
  * @FilePath: \Game-Backstage-Management-System\src\types\dataAnalysis.ts
  * @Description:用于dataAnalysis相关组件的type
  *
@@ -83,6 +83,8 @@ export interface TrendTableField {
 
 // 时间趋势组件所需要的props
 export interface TemporalTrendProps {
+  waitTimeSelect: boolean // 是否需要等待时间组件选择完成后请求
+
   tabInfo?: Array<TabInfo> // 用于切换的tab的信息
 
   type: number // 趋势组件的类型,1为小时段,2为日期统计

+ 1 - 1
src/types/table.ts

@@ -66,7 +66,7 @@ export interface TableFieldInfo {
 
 // props的参数格式
 export interface PropsParams {
-  dataLoading?: boolean // 加载图表,这个配置是当数据直接由外部控制时触发
+  loadingState?: boolean // loading动画,这个配置是当数据直接由外部控制时触发
   needRowindex?: boolean // 是否需要行号
   needAverage?: boolean // 是否需要均值功能
   needLeftTools?: boolean // 是否需要左侧的工具栏

+ 2 - 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-08-27 17:38:24
+ * @LastEditTime: 2024-08-30 15:45:41
  * @FilePath: \Game-Backstage-Management-System\src\utils\common\index.ts
  * @Description:
  *
@@ -64,7 +64,7 @@ export function resetTimeToMidnight(dateTime: Date): string {
   // 将时间部分设置为 00:00:00
   dateTime.setHours(0, 0, 0, 0)
 
-  // 格式化日期为 'YYYY-MM-DD HH:mm:ss' 格式
+  // 格式化日期为 'YYYY-MM-DD' 格式
   const year = dateTime.getFullYear()
   const month = String(dateTime.getMonth() + 1).padStart(2, '0') // 月份从0开始,需要加1
   const day = String(dateTime.getDate()).padStart(2, '0')

+ 31 - 20
src/views/Home/Analysis/KeepView.vue

@@ -2,13 +2,13 @@
  * @Author: fxs bjnsfxs@163.com
  * @Date: 2024-08-27 17:11:23
  * @LastEditors: fxs bjnsfxs@163.com
- * @LastEditTime: 2024-08-30 10:45:10
+ * @LastEditTime: 2024-08-30 17:45:40
  * @FilePath: \Game-Backstage-Management-System\src\views\Home\Analysis\KeepView.vue
  * @Description: 
  * 
 -->
 <script setup lang="ts">
-import { watch, reactive, onMounted, ref } from 'vue'
+import { watch, reactive, ref } from 'vue'
 import Table from '@/components/Table.vue'
 import HeaderCard from '@/components/dataAnalysis/HeaderCard.vue'
 import axiosInstance from '@/utils/axios/axiosInstance'
@@ -23,7 +23,7 @@ import { useAnalysis } from '@/hooks/useAnalysis'
 const { updateReqConfig } = useAnalysis()
 const { selectInfo } = useCommonStore()
 
-const { AllApi } = useRequest()
+const { AllApi, analysisResCode } = useRequest()
 
 // 选择的信息
 const keepViewSelect = reactive({
@@ -99,6 +99,16 @@ const keepDataTableInfo = reactive<{
       name: '+7day',
       cnName: '+7日',
       isShow: true
+    },
+    {
+      name: '+14day',
+      cnName: '+14日',
+      isShow: true
+    },
+    {
+      name: '+30day',
+      cnName: '+30日',
+      isShow: true
     }
   ]
 })
@@ -141,22 +151,25 @@ const getTableData = () => {
       ...keepDataTableInfo.requestConfig.otherOptions
     })
     .then((info) => {
-      let data = info.data
-      let newList = reactive<Array<any>>([])
-      for (const [key, val] of Object.entries(data)) {
-        // 为了编译通过,不做任何事
-        if (key) {
-        }
-        let nVal = val as Object
-        newList.push({
-          ...nVal
+      analysisResCode(info)
+        .then(() => {
+          let data = info.data
+          let newList = reactive<Array<any>>([])
+          for (const [key, val] of Object.entries(data)) {
+            // 为了编译通过,不做任何事
+            if (key) {
+            }
+            let nVal = val as Object
+            newList.push({
+              ...nVal
+            })
+          }
+          keepTableData.splice(0, keepTableData.length, ...newList)
+          keepDataTableInfo.paginationConfig.total = newList.length
+        })
+        .finally(() => {
+          loading.value = false
         })
-      }
-      keepTableData.splice(0, keepTableData.length, ...newList)
-      keepDataTableInfo.paginationConfig.total = newList.length
-    })
-    .finally(() => {
-      loading.value = false
     })
 }
 
@@ -183,8 +196,6 @@ watch(
   },
   { deep: true }
 )
-
-onMounted(() => {})
 </script>
 <template>
   <div class="KeepViewBox">

+ 15 - 12
src/views/Home/Analysis/UserTrendView.vue

@@ -14,7 +14,7 @@ import { resetTimeToMidnight } from '@/utils/common'
 import axiosInstance from '@/utils/axios/axiosInstance'
 
 const { updateReqConfig } = useAnalysis()
-const { AllApi } = useRequest()
+const { AllApi, analysisResCode } = useRequest()
 const { selectInfo } = useCommonStore()
 
 // 总览数据的ref
@@ -249,17 +249,19 @@ const getDetailData = () => {
       ...detailDataTableInfo.requestConfig.otherOptions
     })
     .then((info) => {
-      let data = info.data
-      let newList = reactive<Array<any>>([])
-      for (const [key, val] of Object.entries(data)) {
-        let nVal = val as Object
-        newList.push({
-          date: key,
-          ...nVal
-        })
-      }
-      detailDataTableData.splice(0, detailDataTableData.length, ...newList)
-      detailDataTableInfo.paginationConfig.total = newList.length
+      analysisResCode(info).then(() => {
+        let data = info.data
+        let newList = reactive<Array<any>>([])
+        for (const [key, val] of Object.entries(data)) {
+          let nVal = val as Object
+          newList.push({
+            date: key,
+            ...nVal
+          })
+        }
+        detailDataTableData.splice(0, detailDataTableData.length, ...newList)
+        detailDataTableInfo.paginationConfig.total = newList.length
+      })
     })
 }
 
@@ -297,6 +299,7 @@ onMounted(() => {})
     </div>
     <div class="dataTrendBox">
       <TemporalTrend
+        :wait-time-select="true"
         :need-charts="true"
         :table-fields-info="dataTrendInfo.trendTableFields"
         :res-data-fields-info="dataTrendInfo.resDataField"

+ 3 - 11
src/views/Home/InfoManage/GameManageView.vue

@@ -3,14 +3,12 @@ import { type TablePaginationSetting, type TableFieldInfo } from '@/types/table'
 import type { FormRules, FormInstance } from 'element-plus'
 
 import Table from '@/components/Table.vue'
-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()
 
@@ -192,12 +190,6 @@ const gameFormData = reactive<GameDialogFormData>({
   appSecret: ''
 })
 
-// 进入用户页面
-const enterUserPage = (row: any) => {
-  tableStore.updateQueryInfo(row.gid, 'web')
-  router.push('/home/playerManageView')
-}
-
 // 游戏配置提交
 const submiteGameChange = () => {
   gameFormData.appSecret = '6YJSuc50uJ18zj45'
@@ -232,14 +224,14 @@ const submiteGameChange = () => {
             >
               修改
             </el-button>
-            <el-button
+            <!-- <el-button
               class="operationBtn"
               size="small"
               type="success"
               @click="enterUserPage(scope.row)"
             >
               进入
-            </el-button>
+            </el-button> -->
           </template>
         </el-table-column>
       </template>

+ 12 - 10
src/views/Home/InfoManage/PlayerManageView.vue

@@ -13,16 +13,19 @@ import Table from '@/components/Table.vue'
 import CryptoJS from 'crypto-js'
 import axiosInstance from '@/utils/axios/axiosInstance'
 
-import { onMounted, reactive, ref } from 'vue'
+import { onMounted, reactive, ref, watch } from 'vue'
 import { ElMessageBox } from 'element-plus'
 import type { FormRules, FormInstance } from 'element-plus'
 
 import { useTableStore } from '@/stores/useTable'
 import { useRequest } from '@/hooks/useRequest'
 import { useDialog } from '@/hooks/useDialog'
+import { useCommonStore } from '@/stores/useCommon'
 
 const { AllApi, analysisResCode } = useRequest()
+
 const tableStore = useTableStore()
+const commonStore = useCommonStore()
 const { dialogClose, submitDialog, handleEdit } = useDialog()
 
 // 对话框表单数据格式
@@ -56,7 +59,7 @@ const requestConfig = reactive({
   otherOptions: {
     offset: 0,
     limit: paginationConfig.limit,
-    gid: tableStore.playerQueryInfo.gid,
+    gid: commonStore.selectInfo.gid,
     pf: tableStore.playerQueryInfo.pf
   }
 })
@@ -86,14 +89,6 @@ const allGameInfo = reactive<Array<SelectInfo>>([])
 // 查询字段设置
 const queryInfo = reactive<Array<QueryInfo>>([
   {
-    name: 'gid',
-    label: '游戏名',
-    type: FilterType.SELECT,
-    placeholder: '请输入游戏名查询',
-    otherOption: allGameInfo,
-    default: tableStore.playerQueryInfo.gid
-  },
-  {
     name: 'pf',
     label: '平台',
     type: FilterType.SELECT,
@@ -234,6 +229,13 @@ const submiteOptionChange = (isEncrypt: boolean = false) => {
   )
 }
 
+watch(
+  () => commonStore.selectInfo.gid,
+  (val) => {
+    requestConfig.otherOptions.gid = val
+  }
+)
+
 onMounted(() => {
   tableStore.allGameInfo.map((item) => {
     allGameInfo.push({

+ 2 - 0
src/views/Home/Overview/OverView.vue

@@ -211,6 +211,7 @@ onMounted(() => {})
     </div>
     <div class="periodTrendBox">
       <TemporalTrend
+        :wait-time-select="false"
         :need-charts="true"
         :table-fields-info="periodInfo.trendTableFields"
         :res-data-fields-info="periodInfo.resDataField"
@@ -227,6 +228,7 @@ onMounted(() => {})
     </div>
     <div class="oneMonthTrendBox">
       <TemporalTrend
+        :wait-time-select="false"
         :need-charts="true"
         :table-fields-info="monthInfo.trendTableFields"
         :res-data-fields-info="monthInfo.resDataField"

+ 9 - 0
vite.config.ts

@@ -1,3 +1,12 @@
+/*
+ * @Author: fxs bjnsfxs@163.com
+ * @Date: 2024-08-20 14:06:49
+ * @LastEditors: fxs bjnsfxs@163.com
+ * @LastEditTime: 2024-08-30 12:09:21
+ * @FilePath: \Game-Backstage-Management-System\vite.config.ts
+ * @Description:
+ *
+ */
 import { defineConfig } from 'vite'
 import vue from '@vitejs/plugin-vue'
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels