wangbin 2 роки тому
батько
коміт
b7e6e35cb6

+ 23 - 0
src/api/log.js

@@ -172,4 +172,27 @@ export const getErrDeviceLog = (data) => {
     method: 'post',
     data
   })
+}
+
+// 设备Id异常信息
+export const getDeviceIdErr = (data) => {
+  return service({
+    url: '/loging/getDeviceIdErr',
+    method: 'post',
+    data
+  })
+}
+
+export const deviceErrRateExcel = (tableData, fileName) => {
+  service({
+    url: '/loging/deviceErrRateExcel',
+    method: 'post',
+    data: {
+      fileName: fileName,
+      infoList: tableData
+    },
+    responseType: 'blob'
+  }).then((res) => {
+    handleFileError(res, fileName)
+  })
 }

+ 175 - 0
src/view/logStatistics/deviceIdErr.vue

@@ -0,0 +1,175 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+          <el-form-item label="游戏id">
+            <el-input v-model="searchInfo.game_id" placeholder="游戏id" />
+          </el-form-item>
+          <el-form-item label="日期" prop="create_date">
+                <el-date-picker
+                    v-model="searchInfo.create_date"
+                    popper-class="picker-popovers"
+                    class="timefilter"
+                    type="datetime"
+                    placeholder="选择日期时间"
+                    value-format="YYYY-MM-DD"
+                >
+                </el-date-picker>
+          </el-form-item>
+    
+          <el-form-item>
+            <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button>
+            <el-button size="small" icon="refresh" @click="onReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="gva-table-box">
+        <el-table :data="tableData" @sort-change="sortChange">
+          <el-table-column align="left" label="游戏ID" min-width="100" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="账号" min-width="150" prop="account" sortable="custom" />
+          <el-table-column align="left" label="设备id" min-width="150" prop="first_device_id" sortable="custom" />
+          <el-table-column align="left" label="异常游戏ID" min-width="150" prop="current_game_id" sortable="custom" />
+          <el-table-column align="left" label="异常账号" min-width="150" prop="current_account" sortable="custom" />
+          <el-table-column align="left" label="异常设备id" min-width="150" prop="current_device_id" sortable="custom" />
+          <el-table-column align="left" label="上报时间" min-width="150" prop="create_time" sortable="custom" />
+          <el-table-column align="left" label="日期" min-width="150" prop="create_date" sortable="custom" />
+          <el-table-column align="left" label="备注" min-width="60" prop="status">
+          <template #default="scope">
+            <div>
+              {{ typeFiletr(scope.row.status) }}
+            </div>
+          </template>
+        </el-table-column>
+        </el-table>
+        <div class="gva-pagination">
+          <el-pagination
+            :current-page="page"
+            :page-size="pageSize"
+            :page-sizes="[10, 30, 50, 100]"
+            :total="total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @current-change="handleCurrentChange"
+            @size-change="handleSizeChange"
+          />
+        </div>
+  
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'DeviceId',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    getDeviceIdErr
+
+  } from '@/api/log'
+
+  import { toSQLLine } from '@/utils/stringFun'
+  import { ref } from 'vue'
+
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+
+  const searchStatusOptions = ref([
+    {
+      value: -1,
+      label: '否',
+      type: 'success'
+    },
+    {
+      value: 1,
+      label: '是',
+      type: ''
+    }
+  ])
+
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    getTableData()
+  }
+  
+  // 分页
+  const handleSizeChange = (val) => {
+    pageSize.value = val
+    getTableData()
+  }
+  
+  const handleCurrentChange = (val) => {
+    page.value = val
+    getTableData()
+  }
+  
+  // 排序
+  const sortChange = ({ prop, order }) => {
+    if (prop) {
+      if (prop === 'id') {
+        prop = 'id'
+      }
+      searchInfo.value.orderKey = toSQLLine(prop)
+      searchInfo.value.desc = order === 'descending'
+    }
+    getTableData()
+  }
+  
+  // 查询
+  const getTableData = async() => {
+    const table = await getDeviceIdErr({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data.list
+      total.value = table.data.total
+      page.value = table.data.page
+      pageSize.value = table.data.pageSize
+    }
+  }
+  
+  getTableData()
+  
+
+const typeFiletr = (value) => {
+  const target = typeOptions.value.filter(item => item.value === value)[0]
+  return target && `${target.label}`
+}
+const typeOptions = ref([
+  {
+    value: 1,
+    label: '设备id不同',
+    type: ''
+  },
+  {
+    value: 2,
+    label: '设备id相同',
+    type: ''
+  },
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 236 - 0
src/view/logStatistics/deviceLog.vue

@@ -0,0 +1,236 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+            <el-form-item label="是否异常">
+            <el-select v-model="searchInfo.is_err" placeholder="是否异常" >
+                <el-option
+                    v-for="item in searchStatusOptions"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                    :disabled="item.disabled"
+                />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="游戏id">
+            <el-input v-model="searchInfo.game_id" placeholder="游戏id" />
+          </el-form-item>
+          <el-form-item label="日期" prop="create_date">
+                <el-date-picker
+                    v-model="searchInfo.create_date"
+                    popper-class="picker-popovers"
+                    class="timefilter"
+                    type="datetime"
+                    placeholder="选择日期时间"
+                    value-format="YYYY-MM-DD"
+                >
+                </el-date-picker>
+          </el-form-item>
+    
+          <el-form-item>
+            <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button>
+            <el-button size="small" icon="refresh" @click="onReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="gva-table-box">
+        <el-table :data="tableData" @sort-change="sortChange">
+          <el-table-column align="left" label="游戏ID" min-width="80" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="电脑编号" min-width="80" prop="pc_code"/>
+          <el-table-column align="left" label="设备厂商" min-width="80" prop="device_manufacturer"/>
+          <el-table-column align="left" label="设备型号" min-width="80" prop="device_model"/>
+          <el-table-column align="left" label="设备Imei" min-width="150" prop="device_imei"/>
+          <el-table-column align="left" label="设备Sdk" min-width="150" prop="device_sdk" />
+          <el-table-column align="left" label="设备Mac" min-width="150" prop="device_mac" />
+          <el-table-column align="left" label="绑定手机号" min-width="120" prop="device_number"/>
+          <el-table-column align="left" label="设备id" min-width="120" prop="device_id" />
+          <el-table-column align="left" label="账号" min-width="120" prop="account" />
+          <el-table-column align="left" label="上报时间" min-width="150" prop="create_time"/>
+          <el-table-column align="left" label="日志uuid" min-width="150" prop="log_uuid" />
+          <el-table-column align="left" label="类型" min-width="60" prop="err_status">
+          <template #default="scope">
+            <div>
+              {{ typeFiletr(scope.row.err_status) }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column align="left" fixed="right" label="操作" width="100">
+            <template #default="scope">
+              <el-button
+                icon="edit"
+                size="small"
+                type="primary"
+                link
+                :disabled="scope.row.is_err != 1"
+                @click="getDeviceFunc(scope.row)"
+              >查看</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="gva-pagination">
+          <el-pagination
+            :current-page="page"
+            :page-size="pageSize"
+            :page-sizes="[10, 30, 50, 100]"
+            :total="total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @current-change="handleCurrentChange"
+            @size-change="handleSizeChange"
+          />
+        </div>
+  
+      </div>
+      <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="异常数据查看" width="80%">
+            <el-table :data="deviceData" height="500" border>
+              <el-table-column align="left" label="ID" min-width="80" prop="id" />
+              <el-table-column align="left" label="游戏ID" min-width="80" prop="game_id" />
+              <el-table-column align="left" label="电脑编号" min-width="80" prop="pc_code"/>
+              <el-table-column align="left" label="设备厂商" min-width="80" prop="device_manufacturer" />
+              <el-table-column align="left" label="设备型号" min-width="80" prop="device_model" />
+              <el-table-column align="left" label="设备Imei" min-width="150" prop="device_imei" />
+              <el-table-column align="left" label="设备Sdk" min-width="150" prop="device_sdk" />
+              <el-table-column align="left" label="设备Mac" min-width="150" prop="device_mac" />
+              <el-table-column align="left" label="绑定手机号" min-width="100" prop="device_number" />
+              <el-table-column align="left" label="设备id" min-width="120" prop="device_id" />
+              <el-table-column align="left" label="账号" min-width="100" prop="account" />
+              <el-table-column align="left" label="上报时间" min-width="120" prop="create_time"/>
+            </el-table>
+        </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'deviceLog',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    getDeviceInfoLog,
+    getErrDeviceLog
+
+  } from '@/api/log'
+
+  import { toSQLLine } from '@/utils/stringFun'
+  import { ref } from 'vue'
+
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+
+  const searchStatusOptions = ref([
+    {
+      value: -1,
+      label: '否',
+      type: 'success'
+    },
+    {
+      value: 1,
+      label: '是',
+      type: ''
+    }
+  ])
+
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    getTableData()
+  }
+  
+  // 分页
+  const handleSizeChange = (val) => {
+    pageSize.value = val
+    getTableData()
+  }
+  
+  const handleCurrentChange = (val) => {
+    page.value = val
+    getTableData()
+  }
+  
+  // 排序
+  const sortChange = ({ prop, order }) => {
+    if (prop) {
+      if (prop === 'id') {
+        prop = 'id'
+      }
+      searchInfo.value.orderKey = toSQLLine(prop)
+      searchInfo.value.desc = order === 'descending'
+    }
+    getTableData()
+  }
+  
+  // 查询
+  const getTableData = async() => {
+    const table = await getDeviceInfoLog({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data.list
+      total.value = table.data.total
+      page.value = table.data.page
+      pageSize.value = table.data.pageSize
+    }
+  }
+  
+  getTableData()
+  
+const dialogFormVisible = ref(false)
+const deviceData = ref([])
+  // 查看异常设备
+const getDeviceFunc = async (row) => {
+    const res = await getErrDeviceLog({ id: row.id, create_date: row.create_date })
+    deviceData.value = res.data.list
+    dialogFormVisible.value = true
+}
+
+const closeDialog = () => {
+    dialogFormVisible.value = false
+}
+
+const typeFiletr = (value) => {
+  const target = typeOptions.value.filter(item => item.value === value)[0]
+  return target && `${target.label}`
+}
+const typeOptions = ref([
+  {
+    value: 1,
+    label: '正常',
+    type: ''
+  },
+  {
+    value: 2,
+    label: '账号设备异常',
+    type: ''
+  },
+  {
+    value: 3,
+    label: '设备异常',
+    type: ''
+  },
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 202 - 0
src/view/logStatistics/deviceStatistics.vue

@@ -0,0 +1,202 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+            <el-form-item label="游戏id">
+            <el-input v-model="searchInfo.game_id" placeholder="游戏id" />
+          </el-form-item>
+          <el-form-item label="日期" prop="create_date">
+                <el-date-picker
+                    v-model="searchInfo.create_date"
+                    popper-class="picker-popovers"
+                    class="timefilter"
+                    type="datetime"
+                    placeholder="选择日期时间"
+                    value-format="YYYY-MM-DD"
+                >
+                </el-date-picker>
+          </el-form-item>
+    
+          <el-form-item>
+            <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button>
+            <el-button size="small" icon="refresh" @click="onReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="gva-table-box">
+        <div class="gva-btn-list">
+          <el-button class="excel-btn" size="small" type="primary" icon="download" @click="handleExcelExport">导出</el-button>
+        </div>
+        <el-table :data="tableData" @sort-change="sortChange">
+          
+          <el-table-column align="left" label="游戏ID" min-width="90" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="负责人" min-width="90" prop="user"  />
+          <el-table-column align="left" label="留存设备异常" min-width="110" prop="device_err_num"/>
+          <el-table-column align="left" label="留存设备id异常" min-width="110" prop="retained_device_id_err" />
+          <el-table-column align="left" label="留存完成目标" min-width="110" prop="retained_complete" />
+          <el-table-column align="left" label="留存异常率" min-width="120" prop="device_err_rate" sortable="custom">
+            <template #default="scope">
+							{{ scope.row.device_err_rate + '%'}}
+						</template>
+          </el-table-column>
+          <el-table-column align="left" label="留存设备id异常率" min-width="120" prop="retained_device_id_rate" sortable="custom">
+            <template #default="scope">
+							{{ scope.row.retained_device_id_rate + '%'}}
+						</template>
+          </el-table-column>
+          <el-table-column align="left" label="新增设备异常" min-width="110" prop="account_err_num" />
+          <el-table-column align="left" label="新增设备id异常" min-width="110" prop="new_device_id_err" />
+          <el-table-column align="left" label="新增完成目标" min-width="110" prop="new_complete" />
+          <el-table-column align="left" label="新增异常率" min-width="120" prop="account_err_rate" sortable="custom">
+            <template #default="scope">
+							{{ scope.row.account_err_rate + '%'}}
+						</template>
+          </el-table-column>
+          <el-table-column align="left" label="新增设备id异常率" min-width="120" prop="new_device_id_rate" sortable="custom">
+            <template #default="scope">
+							{{ scope.row.new_device_id_rate + '%'}}
+						</template>
+          </el-table-column>
+          <el-table-column align="left" label="模拟器成功数" min-width="110" prop="simulator_start_num"/>
+          <el-table-column align="left" label="统计日期" min-width="110" prop="create_date" />
+        </el-table>
+        <div class="gva-pagination">
+          <el-pagination
+            :current-page="page"
+            :page-size="pageSize"
+            :page-sizes="[10, 30, 50, 100]"
+            :total="total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @current-change="handleCurrentChange"
+            @size-change="handleSizeChange"
+          />
+        </div>
+  
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'deviceLog',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    getDeviceStatistics,
+    deviceErrRateExcel,
+
+  } from '@/api/log'
+
+  import { toSQLLine } from '@/utils/stringFun'
+  import { ref } from 'vue'
+
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+
+  const handleExcelExport = async() => {
+    var fileName = Date.parse(new Date()) + "-device.xlsx"
+    if(searchInfo.value.create_date == null){
+      let dt = new Date()
+            var y = dt.getFullYear()
+            var mt = (dt.getMonth() + 1).toString().padStart(2,'0')
+            var day = dt.getDate().toString().padStart(2,'0')
+            var timeStr = y + "-" + mt + "-" + day
+      fileName = timeStr + "-device.xlsx"
+    }else{
+      fileName = searchInfo.value.create_date + "-device.xlsx"
+    }
+    deviceErrRateExcel({ page: page.value, pageSize: pageSize.value, ...searchInfo.value },fileName)
+}
+
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    getTableData()
+  }
+  
+  // 分页
+  const handleSizeChange = (val) => {
+    pageSize.value = val
+    getTableData()
+  }
+  
+  const handleCurrentChange = (val) => {
+    page.value = val
+    getTableData()
+  }
+  
+  // 排序
+  const sortChange = ({ prop, order }) => {
+    if (prop) {
+      if (prop === 'id') {
+        prop = 'id'
+      }
+      searchInfo.value.orderKey = toSQLLine(prop)
+      searchInfo.value.desc = order === 'descending'
+    }
+    getTableData()
+  }
+  
+  // 查询
+  const getTableData = async() => {
+    const table = await getDeviceStatistics({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data.list
+      total.value = table.data.total
+      page.value = table.data.page
+      pageSize.value = table.data.pageSize
+    }
+  }
+  
+  getTableData()
+  
+
+const typeFiletr = (value) => {
+  const target = typeOptions.value.filter(item => item.value === value)[0]
+  return target && `${target.label}`
+}
+const typeOptions = ref([
+  {
+    value: 1,
+    label: '正常',
+    type: ''
+  },
+  {
+    value: 2,
+    label: '账号设备异常',
+    type: ''
+  },
+  {
+    value: 3,
+    label: '设备异常',
+    type: ''
+  },
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+