wangbin 3 lat temu
rodzic
commit
f0b5b70332

+ 4 - 0
.eslintrc.js

@@ -6,6 +6,10 @@ module.exports = {
     parser: 'babel-eslint',
     sourceType: 'module'
   },
+  globals: {
+    defineProps: "readonly",
+    defineEmits: "readonly"
+  },
   env: {
     browser: true,
     node: true,

+ 15 - 0
src/api/log.js

@@ -27,3 +27,18 @@ export const logComputerList = (data) => {
   })
 }
 
+export const logGameIdList = (data) => {
+  return service({
+    url: '/loging/getGameIdStatistics',
+    method: 'post',
+    data
+  })
+}
+
+export const logComputerNum = (data) => {
+  return service({
+    url: '/loging/getComputerNum',
+    method: 'post',
+    data
+  })
+}

+ 6 - 6
src/style/main.scss

@@ -436,7 +436,7 @@ th,
 td {
     border: none;
     font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
-    font-size: 14px;
+    font-size: 12px;
     margin: 0px;
     padding: 0px;
 }
@@ -683,7 +683,7 @@ li {
 
 .admin-box {
     min-height: calc(100vh - 200px);
-    padding: 12px 16px;
+    padding: 6px 16px;
     margin: 100px 2px 20px;
     .el-table--border {
         border-radius: 4px;
@@ -694,19 +694,19 @@ li {
             color: $color-table-thead;
         }
         th {
-            padding: 6px 0;
+            padding: 3px 0;
             .cell {
                 color: rgba($color: #000000, $alpha: 0.85);
-                font-size: 14px;
+                font-size: 10px;
                 line-height: 40px;
                 min-height: 40px;
             }
         }
         td {
-            padding: 6px 0;
+            padding: 3px 0;
             .cell {
                 min-height: 40px;
-                line-height: 40px;
+                line-height: 30px;
                 color: rgba($color: #000000, $alpha: 0.65);
             }
         }

+ 32 - 3
src/view/logComputer/list.vue

@@ -8,6 +8,9 @@
           <el-form-item label="开发者">
             <el-input v-model="searchInfo.operator" placeholder="开发者" />
           </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"
@@ -25,8 +28,18 @@
           </el-form-item>
         </el-form>
       </div>
+      <div class="row center">
+      <el-tooltip
+        class="box-item"
+        effect="dark"
+        content="Top Left prompts info"
+        placement="top-start"
+      >
+        <el-button>运行电脑 : {{computerNum}} 台</el-button>
+      </el-tooltip>
+    </div>
       <div class="gva-table-box">
-        <el-table :data="tableData" :span-method="objectSpanMethod" @sort-change="sortChange" @selection-change="handleSelectionChange"
+        <el-table :data="tableData"  @sort-change="sortChange" @selection-change="handleSelectionChange"
         border
         >
           <el-table-column
@@ -37,8 +50,13 @@
           <el-table-column align="left" label="脚本负责人" min-width="150" prop="operator" />
           <el-table-column align="left" label="日期" min-width="150" prop="create_date" />
           <el-table-column align="left" label="游戏id" min-width="150" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="总任务" min-width="150" prop="target_num" />
           <el-table-column align="left" label="拉取账号" min-width="150" prop="pull_account_num" />
-          <el-table-column align="left" label="完成任务" min-width="150" prop="task_success_num" />
+          <el-table-column align="left" label="进入主线" min-width="150" prop="enter_main" />
+          <el-table-column align="left" label="主线成功" min-width="150" prop="task_success_num" />
+          <el-table-column align="left" label="半小时内付费" min-width="150" prop="computer_fee_rate" />
+          <el-table-column align="left" label="任务完成效率(/h)" min-width="150" prop="computer_hour_average_rate" />
+          <el-table-column align="left" label="空闲时间" min-width="150" prop="computer_free_time" />
         </el-table>
         <div class="gva-pagination">
           <el-pagination
@@ -82,6 +100,7 @@
   <script setup>
   import {
     logComputerList,
+    logComputerNum,
   } from '@/api/log'
   import { toSQLLine } from '@/utils/stringFun'
   import { ref } from 'vue'
@@ -260,9 +279,19 @@
       page.value = table.data.page
       pageSize.value = table.data.pageSize
       getSpanArr(table.data.list)
+      getComputerNum()
+    }
+  }
+
+  const computerNum = ref('')
+    // 查询
+    const getComputerNum = async() => {
+    const table = await logComputerNum({})
+    if (table.code === 0) {
+      console.log(table.data)
+      computerNum.value = table.data
     }
   }
-  
   getTableData()
   
   // 批量操作

+ 382 - 0
src/view/logComputer/listGameId.vue

@@ -0,0 +1,382 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+          <el-form-item label="电脑编号">
+            <el-input v-model="searchInfo.pc_code" placeholder="电脑编号" />
+          </el-form-item>
+          <el-form-item label="开发者">
+            <el-input v-model="searchInfo.operator" placeholder="开发者" />
+          </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" @selection-change="handleSelectionChange"
+        border
+        >
+          <el-table-column
+            type="selection"
+            width="55"
+          />
+          <el-table-column align="left" label="游戏id" min-width="150" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="电脑数" min-width="100" prop="pc_code_total" />
+          <el-table-column align="left" label="日期" min-width="150" prop="create_date" />
+          <el-table-column align="left" label="总任务" min-width="150" prop="target_num" />
+          <el-table-column align="left" label="进入主线总数" min-width="150" prop="enter_main_total" />
+          <el-table-column align="left" label="主线成功总数" min-width="150" prop="task_success_total" />
+          <el-table-column align="left" label="单台电脑完成任务" min-width="150" prop="one_computer_average_num" />
+          <el-table-column align="left" label="最后半小时内付费" min-width="150" prop="game_fee_rate" />
+          <el-table-column align="left" label="任务完成效率(/h)" min-width="150" prop="computer_hour_average_total" />
+          <el-table-column align="left" label="电脑总空闲时间" min-width="150" prop="computer_free_time_total" />
+        </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="dialogTitle">
+        <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px">
+          <el-form-item label="游戏名称" prop="game_name">
+            <el-input v-model="form.game_name" autocomplete="off" />
+          </el-form-item>
+          <el-form-item label="游戏包名" prop="game_package_name">
+            <el-input v-model="form.game_package_name" autocomplete="off" />
+          </el-form-item>
+        </el-form>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button size="small" @click="closeDialog">取 消</el-button>
+            <el-button size="small" type="primary" @click="enterDialog">确 定</el-button>
+          </div>
+        </template>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'GameIdList',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    logGameIdList,
+  } from '@/api/log'
+  import { toSQLLine } from '@/utils/stringFun'
+  import { ref } from 'vue'
+  import { ElMessage, ElMessageBox } from 'element-plus'
+  import warningBar from '@/components/warningBar/warningBar.vue'
+  
+  const apis = ref([])
+  const form = ref({
+      game_name: '',
+      game_package_name: ''
+  })
+  
+  
+  const type = ref('')
+  const rules = ref({
+    game_name: [{ required: true, message: '请输入游戏名称', trigger: 'blur' }],
+    game_package_name: [
+      { required: true, message: '请输入游戏包名', trigger: 'blur' }
+    ]
+  })
+  
+  const typeFiletr = (value) => {
+    const target = typeOptions.value.filter(item => item.value === value)[0]
+    return target && `${target.label}`
+  }
+    
+    const typeOptions = ref([
+    {
+      value: 0,
+      label: '脚本',
+      type: ''
+    },
+    {
+      value: 1,
+      label: '中控',
+      type: ''
+    }
+  ])
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  let spanArr = []
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+  
+  const spanArrReset = () => {
+    for (var i = 0; i < spanArr.length; i++) {
+        spanArr.pop()
+    } 
+  }
+  
+
+  const value = ref('')
+  const statusList = [
+    {
+      value: 1,
+      label: '成功',
+    },
+    {
+      value: 2,
+      label: '失败',
+    },
+  ]
+  
+  const options = [
+    {
+      value: 45010,
+      label: '启动游戏',
+    },
+    {
+      value: 46010,
+      label: '小绵羊登录',
+    },
+    {
+      value: 46020,
+      label: '微信登录',
+    },
+    {
+      value: 46030,
+      label: '魅族登录',
+    },
+    {
+      value: 46050,
+      label: '进入游戏',
+    },
+    {
+      value: 47010,
+      label: '主线教程',
+    },
+    {
+      value: 46040,
+      label: '选区',
+    },
+    {
+      value: 46070,
+      label: '实名认证',
+    },
+  ]
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    searchInfo.value.coding = Number(searchInfo.value.coding)
+    getTableData()
+  }
+
+  const getSpanArr = (data) => {
+    spanArr = []
+    var pos = 0
+    for (var i = 0; i < data.length; i++) {
+          if (i === 0) {
+            spanArr.push(1);
+            pos = 0
+          } else {
+            if (data[i].pc_code === data[i - 1].pc_code) {
+              spanArr[pos] += 1;
+              spanArr.push(0);
+            } else {
+              spanArr.push(1);
+              pos = i;
+            }
+          }
+        }
+        console.log(spanArr)  
+  }
+
+  const objectSpanMethod = (row) => {
+    if (row.columnIndex === 1 || row.columnIndex === 2 || row.columnIndex === 3 || row.columnIndex === 0) {
+          const rowspan = spanArr[row.rowIndex];
+          const colspan = rowspan > 0 ? 1 : 0;
+          return {
+            rowspan: rowspan,
+            colspan: colspan
+          }
+        }
+  }
+ 
+
+  
+  // 分页
+  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 logGameIdList({ 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
+      getSpanArr(table.data.list)
+    }
+  }
+  
+  getTableData()
+  
+  // 批量操作
+  const handleSelectionChange = (val) => {
+    apis.value = val
+  }
+  
+  const deleteVisible = ref(false)
+  
+  
+  // 弹窗相关
+  const apiForm = ref(null)
+  const initForm = () => {
+    apiForm.value.resetFields()
+    form.value = {
+      game_name: '',
+      game_package_name: ''
+    }
+  }
+  
+  const dialogTitle = ref('新增game')
+  const dialogFormVisible = ref(false)
+  const openDialog = (key) => {
+    switch (key) {
+      case 'addGame':
+        dialogTitle.value = '新增game'
+        break
+      case 'edit':
+        dialogTitle.value = '编辑game'
+        break
+      default:
+        break
+    }
+    type.value = key
+    dialogFormVisible.value = true
+  }
+  const closeDialog = () => {
+    initForm()
+    dialogFormVisible.value = false
+  }
+  
+  const editCardFunc = async(row) => {
+    const res = await getGameById({ id: row.id })
+    form.value = res.data
+    openDialog('edit')
+  }
+  
+  const enterDialog = async() => {
+    apiForm.value.validate(async valid => {
+      if (valid) {
+        switch (type.value) {
+          case 'addGame':
+            {
+              const res = await cuGame(form.value)
+              if (res.code === 0) {
+                ElMessage({
+                  type: 'success',
+                  message: '添加成功',
+                  showClose: true
+                })
+              }
+              getTableData()
+              closeDialog()
+            }
+  
+            break
+          case 'edit':
+            {
+              const res = await cuGame(form.value)
+              if (res.code === 0) {
+                ElMessage({
+                  type: 'success',
+                  message: '编辑成功',
+                  showClose: true
+                })
+              }
+              getTableData()
+              closeDialog()
+            }
+            break
+          default:
+            // eslint-disable-next-line no-lone-blocks
+            {
+              ElMessage({
+                type: 'error',
+                message: '未知操作',
+                showClose: true
+              })
+            }
+            break
+        }
+      }
+    })
+  }
+  
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 352 - 0
src/view/logStatistics/codeList.vue

@@ -0,0 +1,352 @@
+<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" @selection-change="handleSelectionChange" height="500" style="width: 100%">
+          <el-table-column
+            type="selection"
+            width="55"
+          />
+          <el-table-column fixed="left" align="left" label="游戏id" min-width="90" prop="game_id" sortable="custom" />
+          <el-table-column fixed="left" align="left" label="日期" min-width="90" prop="create_date" />
+          <el-table-column fixed="left" align="left" label="脚本负责人" min-width="90" prop="operator" />
+          <el-table-column fixed="left" align="left" label="类型" min-width="60" prop="type" sortable="custom">
+          <template #default="scope">
+            <div>
+              {{ typeFiletr(scope.row.type) }}
+            </div>
+          </template>
+        </el-table-column>
+      <el-table-column label="拉取账号">
+        <el-table-column prop="pull_account_ok" label="成功" width="60" />
+        <el-table-column prop="pull_account_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="启动代理">
+        <el-table-column prop="start_proxy_ok" label="成功" width="60" />
+        <el-table-column prop="start_proxy_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="模拟器启动">
+        <el-table-column prop="simulator_start_ok" label="成功" width="60" />
+        <el-table-column prop="start_proxy_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="网络检查">
+        <el-table-column prop="network_check_ok" label="成功" width="60" />
+        <el-table-column prop="network_check_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="启动游戏">
+        <el-table-column prop="enter_start_game" label="进入" width="60" />
+        <el-table-column prop="game_start_ok" label="成功" width="60" />
+        <el-table-column prop="game_start_fail" label="失败" width="60" />
+        
+      </el-table-column>
+      <el-table-column label="登录游戏">
+        <el-table-column prop="enter_login" label="进入" width="60" />
+        <el-table-column prop="login_ok" label="成功" width="60" />
+        <el-table-column prop="login_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="实名认证">
+        <el-table-column prop="enter_authentication" label="进入" width="60" />
+        <el-table-column prop="authentication_ok" label="成功" width="60" />
+        <el-table-column prop="authentication_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="选区">
+        <el-table-column prop="enter_constituency" label="进入" width="60" />
+        <el-table-column prop="constituency_ok" label="成功" width="60" />
+        <el-table-column prop="constituency_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="角色">
+        <el-table-column prop="has_role" label="有" width="60" />
+        <el-table-column prop="not_role" label="无" width="60" />
+      </el-table-column>
+      <el-table-column label="进入游戏">
+        <el-table-column prop="enter_game" label="进入" width="60" />
+        <el-table-column prop="enter_game_ok" label="成功" width="60" />
+        <el-table-column prop="enter_game_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="主线教程">
+        <el-table-column prop="enter_main" label="进入" width="60" />
+        <el-table-column prop="enter_main_ok" label="成功" width="60" />
+        <el-table-column prop="enter_main_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="付费">
+        <el-table-column prop="enter_fee" label="进入" width="60" />
+        <el-table-column prop="fee_ok" label="成功" width="60" />
+        <el-table-column prop="fee_fail" label="失败" width="60" />
+      </el-table-column>
+      <el-table-column label="封号" min-width="60" prop="ban_off" />
+      <el-table-column label="冻结" min-width="60" prop="freeze" />
+        </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="dialogTitle">
+        <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange" height="500" style="width: 100%">
+          <el-table-column
+            type="selection"
+            width="55"
+          />
+          <el-table-column fixed="left" align="left" label="游戏id" min-width="90" prop="game_id" sortable="custom" />
+          <el-table-column fixed="left" align="left" label="日期" min-width="90" prop="create_date" />
+          <el-table-column fixed="left" align="left" label="脚本负责人" min-width="90" prop="operator" />
+          </el-table>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'LogStatisticsList',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    logStatistics,
+  } from '@/api/log'
+  import { toSQLLine } from '@/utils/stringFun'
+  import { ref } from 'vue'
+  import { ElMessage, ElMessageBox } from 'element-plus'
+  import warningBar from '@/components/warningBar/warningBar.vue'
+  
+  const apis = ref([])
+  const form = ref({
+      game_name: '',
+      game_package_name: ''
+  })
+  
+  
+  const type = ref('')
+  const rules = ref({
+    game_name: [{ required: true, message: '请输入游戏名称', trigger: 'blur' }],
+    game_package_name: [
+      { required: true, message: '请输入游戏包名', trigger: 'blur' }
+    ]
+  })
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  const tableFailData = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    searchInfo.value.coding = Number(searchInfo.value.coding)
+    getTableData()
+  }
+
+  const searchFailData = (gameid) => {
+    //form.value.parent_id = String(id)
+    getTableFailData
+    dialogFormVisible.value = true
+  }
+
+  // 查询
+  const getTableFailData = async() => {
+    const table = await logStatistics({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data
+    }
+  }
+
+  const typeFiletr = (value) => {
+  const target = typeOptions.value.filter(item => item.value === value)[0]
+  return target && `${target.label}`
+}
+  
+  const typeOptions = ref([
+  {
+    value: 0,
+    label: '新增',
+    type: ''
+  },
+  {
+    value: 1,
+    label: '活跃',
+    type: ''
+  }
+])
+
+  // 分页
+  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 logStatistics({ 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 handleSelectionChange = (val) => {
+    apis.value = val
+  }
+  
+  const deleteVisible = ref(false)
+  
+  
+  // 弹窗相关
+  const apiForm = ref(null)
+  const initForm = () => {
+    apiForm.value.resetFields()
+    form.value = {
+      game_name: '',
+      game_package_name: ''
+    }
+  }
+  
+  const dialogTitle = ref('新增game')
+  const dialogFormVisible = ref(false)
+  const openDialog = (key) => {
+    switch (key) {
+      case 'addGame':
+        dialogTitle.value = '新增game'
+        break
+      case 'edit':
+        dialogTitle.value = '编辑game'
+        break
+      default:
+        break
+    }
+    type.value = key
+    dialogFormVisible.value = true
+  }
+  const closeDialog = () => {
+    dialogFormVisible.value = false
+  }
+  
+  const editCardFunc = async(row) => {
+    const res = await getGameById({ id: row.id })
+    form.value = res.data
+    openDialog('edit')
+  }
+  
+  const enterDialog = async() => {
+    apiForm.value.validate(async valid => {
+      if (valid) {
+        switch (type.value) {
+          case 'addGame':
+            {
+              const res = await cuGame(form.value)
+              if (res.code === 0) {
+                ElMessage({
+                  type: 'success',
+                  message: '添加成功',
+                  showClose: true
+                })
+              }
+              getTableData()
+              closeDialog()
+            }
+  
+            break
+          case 'edit':
+            {
+              const res = await cuGame(form.value)
+              if (res.code === 0) {
+                ElMessage({
+                  type: 'success',
+                  message: '编辑成功',
+                  showClose: true
+                })
+              }
+              getTableData()
+              closeDialog()
+            }
+            break
+          default:
+            // eslint-disable-next-line no-lone-blocks
+            {
+              ElMessage({
+                type: 'error',
+                message: '未知操作',
+                showClose: true
+              })
+            }
+            break
+        }
+      }
+    })
+  }
+  
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 150 - 54
src/view/logStatistics/list.vue

@@ -23,78 +23,128 @@
         </el-form>
       </div>
       <div class="gva-table-box">
-        <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange" height="500" style="width: 100%">
+        <el-table border 
+        :data="tableData" 
+        :span-method="objectSpanMethod"
+        @sort-change="sortChange" 
+        @selection-change="handleSelectionChange" 
+        height="500" 
+        header-align="center"
+        >
           <el-table-column
             type="selection"
             width="55"
           />
-          <el-table-column fixed="left" align="left" label="游戏id" min-width="90" prop="game_id" sortable="custom" />
+          <el-table-column fixed="left" align="left" label="游戏id" min-width="70" prop="game_id" sortable="custom" />
           <el-table-column fixed="left" align="left" label="日期" min-width="90" prop="create_date" />
-          <el-table-column fixed="left" align="left" label="脚本负责人" min-width="90" prop="operator" />
-          <el-table-column fixed="left" align="left" label="类型" min-width="60" prop="type" sortable="custom">
+          <el-table-column fixed="left" align="left" label="脚本负责人" min-width="70" prop="operator" />
+          <el-table-column fixed="left" align="left" label="类型" min-width="70" prop="type">
           <template #default="scope">
             <div>
               {{ typeFiletr(scope.row.type) }}
             </div>
           </template>
         </el-table-column>
-      <el-table-column label="拉取账号">
-        <el-table-column prop="pull_account_ok" label="成功" width="60" />
-        <el-table-column prop="pull_account_fail" label="失败" width="60" />
-      </el-table-column>
-      <el-table-column label="启动代理">
-        <el-table-column prop="start_proxy_ok" label="成功" width="60" />
-        <el-table-column prop="start_proxy_fail" label="失败" width="60" />
-      </el-table-column>
-      <el-table-column label="模拟器启动">
-        <el-table-column prop="simulator_start_ok" label="成功" width="60" />
-        <el-table-column prop="start_proxy_fail" label="失败" width="60" />
-      </el-table-column>
-      <el-table-column label="网络检查">
-        <el-table-column prop="network_check_ok" label="成功" width="60" />
-        <el-table-column prop="network_check_fail" label="失败" width="60" />
-      </el-table-column>
-      <el-table-column label="启动游戏">
-        <el-table-column prop="enter_start_game" label="进入" width="60" />
-        <el-table-column prop="game_start_ok" label="成功" width="60" />
-        <el-table-column prop="game_start_fail" label="失败" width="60" />
-      </el-table-column>
-      <el-table-column label="登录游戏">
-        <el-table-column prop="enter_login" label="进入" width="60" />
-        <el-table-column prop="login_ok" label="成功" width="60" />
-        <el-table-column prop="login_fail" label="失败" width="60" />
+        <el-table-column fixed="left" align="center" label="任务总数" min-width="70" prop="target_num" />
+        <el-table-column fixed="left" align="center" label="下发账号" min-width="70" prop="issued_account" />
+        <el-table-column label="留存账号" align="center"  min-width="100" >
+        <el-table-column label="能付费" align="center">
+          <template #default="scope">
+              {{ scope.row.retained_account_num }}
+							<el-divider style="margin:0" />
+              {{ scope.row.fee_account_num}}
+          </template>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="实名认证">
-        <el-table-column prop="enter_authentication" label="进入" width="60" />
-        <el-table-column prop="authentication_ok" label="成功" width="60" />
-        <el-table-column prop="authentication_fail" label="失败" width="60" />
+      <el-table-column label="下拉成功率" align="center"  min-width="100">
+        <el-table-column label="拉取账号" align="center" >
+            <el-table-column prop="pull_account_ok,pull_account_fail" label="下发账号" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.pull_account_ok }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.issued_account}}
+							<el-divider style="margin:0" />
+							{{ scope.row.pull_account_ok == 0  || scope.row.issued_account == 0 ? 0 + '%' : Math.round(scope.row.pull_account_ok/scope.row.issued_account * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="选区">
-        <el-table-column prop="enter_constituency" label="进入" width="60" />
-        <el-table-column prop="constituency_ok" label="成功" width="60" />
-        <el-table-column prop="constituency_fail" label="失败" width="60" />
+      <el-table-column label="启动成功率" align="center" min-width="100">
+        <el-table-column label="启动成功" align="center">
+            <el-table-column prop="game_start_ok,pull_account_ok" label="拉取成功" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.simulator_start_ok }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.pull_account_ok}}
+							<el-divider style="margin:0" />
+							{{ scope.row.pull_account_ok == 0 ? 0 + '%' : Math.round(scope.row.simulator_start_ok/scope.row.pull_account_ok * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="角色">
-        <el-table-column prop="has_role" label="有" width="60" />
-        <el-table-column prop="not_role" label="无" width="60" />
+      <el-table-column label="主线成功率" align="center"  min-width="100">
+        <el-table-column label="进入主线" align="center">
+            <el-table-column prop="enter_main,game_start_ok" label="启动成功" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.enter_main }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.game_start_ok}}
+							<el-divider style="margin:0" />
+							{{ scope.row.enter_game == 0 || scope.row.game_start_ok == 0 ? 0 + '%' : Math.round(scope.row.enter_game/scope.row.game_start_ok * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="进入游戏">
-        <el-table-column prop="enter_game" label="进入" width="60" />
-        <el-table-column prop="enter_game_ok" label="成功" width="60" />
-        <el-table-column prop="enter_game_fail" label="失败" width="60" />
+      <el-table-column label="任务成功率" align="center"  min-width="100">
+        <el-table-column label="进入主线" align="center">
+          <el-table-column prop="enter_main,pull_account_fail" label="总任务数" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.enter_main }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.target_num}}
+							<el-divider style="margin:0" />
+							{{ scope.row.enter_game == 0 || scope.row.target_num == 0 ? 0 + '%' : Math.round(scope.row.enter_main/scope.row.target_num * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="主线教程">
-        <el-table-column prop="enter_main" label="进入" width="60" />
-        <el-table-column prop="enter_main_ok" label="成功" width="60" />
-        <el-table-column prop="enter_main_fail" label="失败" width="60" />
+      <el-table-column label="微信扫码率" align="center"  min-width="100">
+        <el-table-column label="任务总数" align="center">
+          <el-table-column prop="pull_account_fail,pull_account_fail" label="扫码总数" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.target_num }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.new_scanning_code}}
+							<el-divider style="margin:0" />
+							{{ scope.row.target_num == 0 || scope.row.new_scanning_code == 0 ? 0 + '%' : Math.round(scope.row.target_num/scope.row.new_scanning_code * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
-      <el-table-column label="付费">
-        <el-table-column prop="enter_fee" label="进入" width="60" />
-        <el-table-column prop="fee_ok" label="成功" width="60" />
-        <el-table-column prop="fee_fail" label="失败" width="60" />
+      <el-table-column label="订单完成率" align="center"  min-width="100">
+        <el-table-column label="付费成功" align="center">
+          <el-table-column prop="fee_ok,pull_account_fail" label="下发付费" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.fee_ok }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.order_create}}
+							<el-divider style="margin:0" />
+							{{ scope.row.fee_ok == 0 || scope.row.order_create == 0 ? 0 + '%' : Math.round(scope.row.fee_ok/scope.row.order_create * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
       </el-table-column>
+      <el-table-column align="center" label="付费任务" min-width="70" prop="pay_target"/>
+      <el-table-column align="center" label="付费完成" min-width="70" prop="pay_complete"/>
+      <el-table-column align="center" label="下发付费" min-width="70" prop="order_create"/>
+      <el-table-column align="center" label="订单数" min-width="70" prop="order_success"/>
+      <el-table-column align="center" label="付费成功" min-width="70" prop="fee_ok"/>
+      
+        
       <el-table-column label="封号" min-width="60" prop="ban_off" />
       <el-table-column label="冻结" min-width="60" prop="freeze" />
+      <el-table-column prop="has_role" label="新增有角色" width="60" />
+      <el-table-column prop="not_role" label="活跃无角色" width="60" />
         </el-table>
         <div class="gva-pagination">
           <el-pagination
@@ -135,7 +185,7 @@
     logStatistics,
   } from '@/api/log'
   import { toSQLLine } from '@/utils/stringFun'
-  import { ref } from 'vue'
+  import { createElementBlock, ref } from 'vue'
   import { ElMessage, ElMessageBox } from 'element-plus'
   import warningBar from '@/components/warningBar/warningBar.vue'
   
@@ -160,7 +210,7 @@
   const tableData = ref([])
   const tableFailData = ref([])
   const searchInfo = ref({})
-  
+  let spanArr = []
   const onReset = () => {
     searchInfo.value = {}
   }
@@ -193,6 +243,11 @@
   return target && `${target.label}`
 }
   
+const renderheader = ({ column, $index  }) => {
+  console.log(column)
+  console.log($index)
+}
+
   const typeOptions = ref([
   {
     value: 0,
@@ -217,6 +272,11 @@
     getTableData()
   }
   
+  const headerStyle = () => {
+    return {
+      fontSize:"12px"
+    }
+  }
   // 排序
   const sortChange = ({ prop, order }) => {
     if (prop) {
@@ -228,6 +288,38 @@
     }
     getTableData()
   }
+
+  
+  const getSpanArr = (data) => {
+    spanArr = []
+    var pos = 0
+    for (var i = 0; i < data.length; i++) {
+          if (i === 0) {
+            spanArr.push(1);
+            pos = 0
+          } else {
+            if (data[i].game_id === data[i - 1].game_id) {
+              spanArr[pos] += 1;
+              spanArr.push(0);
+            } else {
+              spanArr.push(1);
+              pos = i;
+            }
+          }
+        }
+        console.log(spanArr)  
+  }
+
+  const objectSpanMethod = (row) => {
+    if (row.columnIndex === 1 || row.columnIndex === 3 || row.columnIndex === 7 || row.columnIndex === 0 || row.columnIndex === 2 || row.columnIndex === 12|| row.columnIndex === 14|| row.columnIndex === 15|| row.columnIndex === 16|| row.columnIndex === 17) {
+          const rowspan = spanArr[row.rowIndex];
+          const colspan = rowspan > 0 ? 1 : 0;
+          return {
+            rowspan: rowspan,
+            colspan: colspan
+          }
+        }
+  }
   
   // 查询
   const getTableData = async() => {
@@ -237,6 +329,7 @@
       total.value = table.data.total
       page.value = table.data.page
       pageSize.value = table.data.pageSize
+      getSpanArr(table.data.list)
     }
   }
   
@@ -338,6 +431,9 @@
   </script>
   
   <style scoped lang="scss">
+  .el-table .cell {
+  white-space: pre-wrap;   /*这是重点。文本换行*/
+}
   .button-box {
     padding: 10px 20px;
     .el-button {