Browse Source

Merge branch 'master' of http://10.8.230.114:3000/wangbin/log-server-web

倚楼听风雨 3 years ago
parent
commit
45e500113e

+ 79 - 0
src/api/ipLog.js

@@ -0,0 +1,79 @@
+import service from '@/utils/request'
+//获取ip列表
+export const ipLogList = (data) => {
+    return service({
+        url: '/ipLog/getIpLogList',
+        method: 'post',
+        data
+    })
+}
+
+//获取ip
+export const getIp = (data) => {
+    return service({
+        url: '/ipLog/getIp',
+        method: 'post',
+        data
+    })
+}
+
+//gameId分组获取ip列表
+export const gameIpList = (data) => {
+    return service({
+        url: '/ipLog/getGameIpList',
+        method: 'post',
+        data
+    })
+}
+
+//gameId分组获取ip
+export const getGameIp = (data) => {
+    return service({
+        url: '/ipLog/getGameIp',
+        method: 'post',
+        data
+    })
+}
+
+
+const handleFileError = (res, fileName) => {
+    if (typeof (res.data) !== 'undefined') {
+        if (res.data.type === 'application/json') {
+            const reader = new FileReader()
+            reader.onload = function () {
+                const message = JSON.parse(reader.result).msg
+                ElMessage({
+                    showClose: true,
+                    message: message,
+                    type: 'error'
+                })
+            }
+            reader.readAsText(new Blob([res.data]))
+        }
+    } else {
+        var downloadUrl = window.URL.createObjectURL(new Blob([res]))
+        var a = document.createElement('a')
+        a.style.display = 'none'
+        a.href = downloadUrl
+        a.download = fileName
+        var event = new MouseEvent('click')
+        a.dispatchEvent(event)
+    }
+}
+
+
+
+//导出gameIp列表
+export const gameIpExport = (tableData, fileName) => {
+    service({
+        url: '/ipLog/gameIpExport',
+        method: 'post',
+        data: {
+            fileName: fileName,
+            infoList: tableData
+        },
+        responseType: 'blob'
+    }).then((res) => {
+        handleFileError(res, fileName)
+    })
+}

+ 9 - 1
src/api/log.js

@@ -77,6 +77,14 @@ export const getLogScanningList = (data) => {
 }
 
 
+export const computerSevenRate = (data) => {
+  return service({
+    url: '/loging/computerSevenRate',
+    method: 'post',
+    data
+  })
+}
+
 const handleFileError = (res, fileName) => {
   if (typeof (res.data) !== 'undefined') {
     if (res.data.type === 'application/json') {
@@ -137,4 +145,4 @@ export const computerRateExport = (tableData, fileName) => {
   }).then((res) => {
     handleFileError(res, fileName)
   })
-}
+}

+ 18 - 0
src/api/responsiblePerson.js

@@ -155,3 +155,21 @@ export const selectResponsiblePerson = (data) => {
     data,
   });
 };
+
+//更改负责人状态
+export const statusChange = (data) => {
+  return service({
+    url: '/responsiblePerson/statusChange',
+    method: 'post',
+    data
+  })
+}
+
+//更改负责人推送状态
+export const pushStatusChange = (data) => {
+  return service({
+    url: '/responsiblePerson/pushStatusChange',
+    method: 'post',
+    data
+  })
+}

File diff suppressed because it is too large
+ 0 - 1268
src/view/fileManager/qiniuTransfer.vue


File diff suppressed because it is too large
+ 681 - 722
src/view/gameTarget/target.vue


+ 593 - 0
src/view/gameTarget/txTarget.vue

@@ -0,0 +1,593 @@
+<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.task_id" placeholder="任务ID" />
+          </el-form-item>
+          <el-form-item label="负责人">
+            <el-input v-model="searchInfo.user" placeholder="负责人" />
+          </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" border @sort-change="sortChange" @selection-change="handleSelectionChange">
+          <el-table-column label="任务日期" min-width="70" prop="create_date" />
+          <el-table-column label="任务名称" min-width="80" prop="task_name" sortable="custom" />
+          <el-table-column label="负责人" min-width="60" prop="user" sortable="custom" />
+          <el-table-column label="新增目标" min-width="45" prop="new_target" />
+          <el-table-column  label="新增完成" min-width="45" prop="new_complete" />
+          <el-table-column  label="留存目标" min-width="45" prop="retained_target" />
+          <el-table-column label="留存完成" min-width="45" prop="retained_complete" />
+          <el-table-column  label="付费目标" min-width="45" prop="pay_target" />
+          <el-table-column  label="付费完成" min-width="45" prop="pay_complete" />
+          <el-table-column  label="付费流水" min-width="45" prop="amount"/>
+          <el-table-column align="left" fixed="right" label="操作" width="200">
+            <template #default="scope">
+              <el-button
+                icon="edit"
+                size="small"
+                type="primary"
+                link
+                @click="editCardFunc(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="dialogTitle">
+        <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px" :inline="true">
+
+          <el-form-item label="任务名称" prop="task_name">
+            <el-input v-model="form.task_name" autocomplete="off" :disabled="true"/>
+          </el-form-item>
+          <el-form-item label="负责人" prop="user" >
+            <el-input v-model="form.user" autocomplete="off" :disabled="true"/>
+          </el-form-item>
+          <el-form-item label="任务日期" prop="create_date" >
+            <el-input v-model="form.create_date" autocomplete="off" :disabled="true"/>
+          </el-form-item>
+        </el-form>
+        <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px" :inline="true">
+                <el-form-item  label="新增目标" prop="new_target">
+                <el-input v-model="form.new_target" autocomplete="off" />
+              </el-form-item>
+              <el-form-item label="付费目标" prop="pay_target">
+                <el-input v-model="form.pay_target" 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: 'TxTargetTask',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    getGameTaskTargetById,
+    updateGameTaskTarget,
+    getGameTxTaskList,
+  } from '@/api/task'
+  import { toSQLLine } from '@/utils/stringFun'
+  import warningBar from '@/components/warningBar/warningBar.vue'
+  import { ref } from 'vue'
+  import { ElMessage, ElMessageBox } from 'element-plus'
+
+
+
+  
+  const apis = ref([])
+  const rules = ref({
+    task_id: [{ required: true, message: '输入任务ID', trigger: 'blur' }],
+    task_name: [
+      { required: true, message: '请输入任务名称', trigger: 'blur' }
+    ],
+    user: [
+      { required: true, message: '请输入使用者', trigger: 'blur' }
+    ],
+    new_retained: [
+      { required: true, message: '请选择重要参数', trigger: 'blur' }
+    ],
+    game_name: [
+      { required: true, message: '请选择游戏', trigger: 'blur' }
+    ],
+    date: [
+      { required: true, message: '请选择开始时间', trigger: 'blur' }
+    ],
+    game_port_id: [
+      { required: true, message: '请选择游戏端口', trigger: 'blur' }
+    ],
+    account_type: [
+      { required: true, message: '请选择账号类型', trigger: 'blur' }
+    ],
+    login_method: [
+      { required: true, message: '请选择登录方式', trigger: 'blur' }
+    ],
+    tx_channel: [
+      { required: true, message: '请输入腾讯渠道号', trigger: 'blur' }
+    ],
+    mz_channel: [
+      { required: true, message: '请输入魅族渠道号', trigger: 'blur' }
+    ],
+    new_target: [
+      { required: true, message: '请输入新增目标', trigger: 'blur' }
+    ],
+    pay_target: [
+      { required: true, message: '请输入付费目标', trigger: 'blur' }
+    ],
+    retained_target: [
+      { required: true, message: '请输入留存目标', trigger: 'blur' }
+    ],
+    retained_target: [
+      { required: true, message: '请输入付费单价', trigger: 'blur' }
+    ]
+  })
+  const form = ref({
+    task_id: '',
+    task_name: '',
+    user: '',
+    new_retained: '1',
+    game_name:'',
+    date:'',
+    game_port_id:'',
+    account_type:'',
+    login_method:'',
+    tx_channel:'',
+    tx_game_id:'',
+    mz_channel:'',
+    mz_game_id:'',
+    game_id_xmy:'',
+    new_target:'',
+    pay_target:'',
+    retained_target:'',
+    pay_price:'',
+    free:-1
+  })
+  const GamePortOptions = ref([
+    {
+      id: 1,
+      name: '腾讯游戏',
+    },
+    {
+      id: 2,
+      name: '360游戏',
+    },
+    {
+      id: 3,
+      name: '网易游戏',
+    },
+    {
+      id: 4,
+      name: '酷派游戏',
+    },
+    {
+      id: 5,
+      name: '魅族游戏',
+    },
+  ])
+
+  const accountTypeOptions = ref([
+    {
+      id: 1,
+      name: '小绵羊账号',
+    },
+    {
+      id: 2,
+      name: 'QQ账号',
+    },
+    {
+      id: 3,
+      name: '魅族账号',
+    },
+    {
+      id: 4,
+      name: '华为账号',
+    },
+    {
+      id: 5,
+      name: '测试类型',
+    },
+    {
+      id: 6,
+      name: '微信',
+    },
+    {
+      id: 7,
+      name: '微信+QQ',
+    },
+  ])
+
+  const loginMethodOptions = ref([
+    {
+      id: 1,
+      name: '小绵羊登录',
+    },
+    {
+      id: 2,
+      name: '魅族账号登录',
+    },
+    {
+      id: 3,
+      name: 'QQ账号登录',
+    },
+    {
+      id: 4,
+      name: '网易账号登录',
+    },
+    {
+      id: 5,
+      name: '微信授权登录',
+    },
+    {
+      id: 6,
+      name: '微信+QQ授权登录',
+    },
+  ])
+
+  const FreeMethodOptions = ref([
+    {
+      id: 1,
+      name: 'QQ卡',
+    },
+    {
+      id: 2,
+      name: '微信',
+    },
+    {
+      id: 3,
+      name: '支付宝',
+    },
+    {
+      id: 4,
+      name: '银行卡',
+    },
+  ])
+  // 新增可控按钮
+const addBtn = (form) => {
+  if (!form.card_list) {
+    form.card_list = []
+  }
+  form.card_list.push({
+    card: '',
+    amount: 0
+  })
+}
+// 删除可控按钮
+const deleteBtn = async(btns, index) => {
+  const btn = btns[index]
+  if (btn.ID === 0) {
+    btns.splice(index, 1)
+    return
+  }
+  btns.splice(index, 1)
+
+}
+  
+  const type = ref('')
+  
+  
+  const page = ref(1)
+  const total = ref(0)
+  const pageSize = ref(10)
+  const tableData = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.task_id = Number(searchInfo.value.task_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 getGameTxTaskList({ 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 onClose = async() => {
+    const ids = apis.value.map(item => item.id)
+    console.log(ids)
+    const status = -1
+    const res = await colsePc({ ids,status })
+    if (res.code === 0) {
+      ElMessage({
+        type: 'success',
+        message: res.msg
+      })
+      if (tableData.value.length === ids.length && page.value > 1) {
+        page.value--
+      }
+      deleteVisible.value = false
+      getTableData()
+    }
+  }
+  
+  const onOpen = async() => {
+    const ids = apis.value.map(item => item.id)
+    console.log(ids)
+    const status = 1
+    const res = await colsePc({ ids,status })
+    if (res.code === 0) {
+      ElMessage({
+        type: 'success',
+        message: res.msg
+      })
+      if (tableData.value.length === ids.length && page.value > 1) {
+        page.value--
+      }
+      deleteVisible.value = false
+      getTableData()
+    }
+  }
+  
+  // 弹窗相关
+  const apiForm = ref(null)
+  const initForm = () => {
+    apiForm.value.resetFields()
+    form.value = {
+      task_id: '',
+      task_name: '',
+      user: '',
+      new_retained: '1',
+      game_name:'',
+      date:'',
+      game_port_id:'',
+      account_type:'',
+      login_method:'',
+      tx_channel:'',
+      tx_game_id:'',
+      mz_channel:'',
+      mz_game_id:'',
+      game_id_xmy:'',
+      new_target:'',
+      pay_target:'',
+      retained_target:'',
+      pay_price:'',
+    }
+  }
+  
+  const dialogTitle = ref('新增')
+  const dialogFormVisible = ref(false)
+  const openDialog = (key) => {
+    switch (key) {
+      case 'addCard':
+        dialogTitle.value = '新增'
+        form.value.is_add = 1
+        break
+      case 'edit':
+        dialogTitle.value = '编辑'
+        form.value.is_add = 0
+        break
+      default:
+        break
+    }
+    type.value = key
+    dialogFormVisible.value = true
+  }
+  const closeDialog = () => {
+    initForm()
+    dialogFormVisible.value = false
+  }
+  
+  const editCardFunc = async(row) => {
+    const res = await getGameTaskTargetById({ id: row.task_id, create_date:row.create_date })
+    if (res.code === 0) {
+      form.value = res.data
+      openDialog('edit')
+    }
+    
+  }
+  
+  const enterDialog = async() => {
+    apiForm.value.validate(async valid => {
+      form.value.task_id = Number(form.value.task_id)
+      form.value.new_target = Number(form.value.new_target)
+      form.value.pay_price = Number(form.value.pay_price)
+      form.value.pay_target = Number(form.value.pay_target)
+      form.value.retained_target = Number(form.value.retained_target)
+      form.value.hand_new_complete = Number(form.value.hand_new_complete)
+      form.value.hand_retained_complete = Number(form.value.hand_retained_complete)
+      form.value.hand_pay_complete = Number(form.value.hand_pay_complete)
+      form.value.hand_amount_total = Number(form.value.hand_amount_total)
+      form.value.is_free = Number(form.value.is_free)
+      form.value.free_method = Number(form.value.free_method)
+      form.value.is_upload_xjf = Number(form.value.is_upload_xjf)
+      form.value.is_upload_wt = Number(form.value.is_upload_wt)
+      if (valid) {
+        switch (type.value) {
+          case 'edit':
+            {
+              const res = await updateGameTaskTarget(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
+        }
+      }
+    })
+  }
+  
+  const deleteApiFunc = async(row) => {
+    ElMessageBox.confirm('此操作将永久删除所有角色下该api, 是否继续?', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning'
+    })
+      .then(async() => {
+        const res = await deleteGameTask(row)
+        if (res.code === 0) {
+          ElMessage({
+            type: 'success',
+            message: '删除成功!'
+          })
+          if (tableData.value.length === 1 && page.value > 1) {
+            page.value--
+          }
+          getTableData()
+        }
+      })
+  }
+
+  const switchEnable = async(row) => {
+    const res = await statusOperation({task_id:row.task_id, status:row.status})
+    if (res.code === 0) {
+      ElMessage({ type: 'success', message: `${row.status === -1 ? '停止' : '开启'}成功` })
+    }
+}
+
+const links = ref([])
+
+const querySearch = (queryString, cb) => {
+  const results = queryString
+    ? links.value.filter(createFilter(queryString))
+    : links.value
+  // call callback function to return suggestion objects
+  cb(results)
+}
+const createFilter = (queryString) => {
+  return (restaurant) => {
+    return (
+      restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
+    )
+  }
+}
+const loadAll = () => {
+  return [
+    { game_id: 1, game_name: '龙腾传世' },
+    { game_id: 2, game_name: '龙皇传说' },
+    { game_id: 3, game_name: '龙之国物语' },
+    { game_id: 4, game_name: '黑月' },
+    { game_id: 5, game_name: '麻将来了' },
+    { game_id: 6, game_name: '鸿途归来' },
+    { game_id: 7, game_name: '魔力宝贝归来' },
+  ]
+}
+const handleSelect = (item) => {
+  form.value.game_id = item.game_id
+  console.log(item)
+}
+
+const handleIconClick = (ev) => {
+  console.log(ev)
+}
+
+links.value = loadAll()
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  :deep(.el-tabs__nav-scroll){
+	width:35%;
+	margin:0 auto
+}
+:deep(.el-tabs__nav-scroll)
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 181 - 0
src/view/gameTargetTotal/gameTotal.vue

@@ -0,0 +1,181 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+          <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" :span-method="objectSpanMethod" @sort-change="sortChange" border style="width: 100%">
+          <el-table-column align="left" label="负责人" min-width="150" prop="user" sortable="custom" />
+          <el-table-column align="left" label="游戏端口" min-width="150" prop="game_port" sortable="custom" />
+          <el-table-column align="left" label="数量" min-width="150" prop="total" sortable="custom" />
+          <el-table-column align="left" fixed="right" label="操作" width="200">
+            <template #default="scope">
+              <el-button
+                icon="edit"
+                size="small"
+                type="primary"
+                link
+                @click="selectGameInfoFunc(scope.row)"
+              >查看游戏</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+  
+      </div>
+      <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
+        <el-table :data="tableData1">
+          <el-table-column align="left" label="游戏名称" show-overflow-tooltip min-width="160" prop="game_name" />
+          <el-table-column align="left" label="游戏端口" show-overflow-tooltip min-width="160" prop="game_port" />
+          <el-table-column align="left" label="任务日期" min-width="90" prop="create_date" />
+        </el-table>
+    </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'GameTotal',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    gameStatistics,
+    gameList
+  } from '@/api/task'
+
+  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 tableData1 = ref([])
+  const searchInfo = ref({})
+  
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+  // 关闭弹窗
+  
+  const dialogFormVisible = ref(false)
+  const closeDialog = () => {
+    dialogFormVisible.value = false
+  }
+
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    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 selectGameInfoFunc = async(row) => {
+    const res = await gameList({ user: row.user,game_port_id:row.game_port_id,date:searchInfo.value.create_date })
+    tableData1.value = res.data.list
+    dialogFormVisible.value = true
+  }
+
+  // 查询
+  const getTableData = async() => {
+    const table = await gameStatistics({ 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)
+    }
+  }
+  let spanArr = []
+  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].user === data[i - 1].user) {
+              spanArr[pos] += 1;
+              spanArr.push(0);
+            } else {
+              spanArr.push(1);
+              pos = i;
+            }
+          }
+        }
+        console.log(spanArr)  
+  }
+
+  const objectSpanMethod = (row) => {
+    if (row.columnIndex === 0) {
+          const rowspan = spanArr[row.rowIndex];
+          const colspan = rowspan > 0 ? 1 : 0;
+          return {
+            rowspan: rowspan,
+            colspan: colspan
+          }
+        }
+  }
+  
+  getTableData()
+  
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 120 - 0
src/view/gameTargetTotal/monthTotal.vue

@@ -0,0 +1,120 @@
+<template>
+    
+    <div>
+      <div class="gva-search-box">
+      </div>
+      <div class="gva-table-box">
+        <el-button @click="resetDateFilter">{{year}} 年</el-button>
+        <el-table :data="tableData" @sort-change="sortChange">
+          
+          <el-table-column align="left" label="月份" min-width="150" prop="task_month" sortable="custom" />
+          <el-table-column align="left" label="完成新增" min-width="150" prop="new_complete" />
+          <el-table-column align="left" label="完成活跃" min-width="150" prop="retained_complete"/>
+          <el-table-column align="left" label="完成付费" min-width="150" prop="pay_complete" />
+        </el-table>
+  
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'MonthTotal',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    monthStatistics,
+
+  } from '@/api/task'
+
+  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 year = ref('')
+
+  const onReset = () => {
+    searchInfo.value = {}
+  }
+
+  // 搜索
+  
+  const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    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 monthStatistics({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data.list
+      year.value = table.data.list[0].task_year
+      total.value = table.data.total
+      page.value = table.data.page
+      pageSize.value = table.data.pageSize
+    }
+  }
+  
+  getTableData()
+  
+  const searchStatusOptions = ref([
+ {
+    value: '',
+    label: '总数据',
+  },
+  {
+    value: 'user',
+    label: '按负责人',
+  },
+  {
+    value: 'game_port_id',
+    label: '按游戏端口',
+  }
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 175 - 0
src/view/gameTargetTotal/statistics.vue

@@ -0,0 +1,175 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+            <el-form-item label="分类">
+            <el-select v-model="searchInfo.group_key" 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="日期" prop="date">
+                <el-date-picker
+                    v-model="searchInfo.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
+            type="selection"
+            width="55"
+          />
+          
+          <el-table-column align="left" label="负责人" min-width="150" prop="user" sortable="custom" />
+          <el-table-column align="left" label="游戏端口" min-width="150" prop="game_port" sortable="custom" />
+          <el-table-column align="left" label="任务日期" min-width="150" prop="task_date" sortable="custom" />
+          <el-table-column align="left" label="目标新增" min-width="150" prop="new_target" sortable="custom" />
+          <el-table-column align="left" label="目标活跃" min-width="150" prop="retained_target" sortable="custom" />
+          <el-table-column align="left" label="目标付费" min-width="150" prop="pay_target" sortable="custom" />
+          <el-table-column align="left" label="完成新增" min-width="150" prop="new_complete" sortable="custom" />
+          <el-table-column align="left" label="完成活跃" min-width="150" prop="retained_complete" sortable="custom" />
+          <el-table-column align="left" label="完成付费" min-width="150" prop="pay_complete" sortable="custom" />
+        </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: 'TargetTotal',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    everyDayStatistics,
+
+  } from '@/api/task'
+
+  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 onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    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 everyDayStatistics({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+      tableData.value = table.data.list
+      if(searchInfo.value.group_key != 'user'){
+        table.data.list.forEach((element) => {
+            element.user = '合计'
+        });
+      }
+      if(searchInfo.value.group_key != 'game_port_id'){
+        table.data.list.forEach(element => {
+            element.game_port = '合计'
+        });
+      }
+      total.value = table.data.total
+      page.value = table.data.page
+      pageSize.value = table.data.pageSize
+    }
+  }
+  
+  getTableData()
+  
+  const searchStatusOptions = ref([
+ {
+    value: '',
+    label: '总数据',
+  },
+  {
+    value: 'user',
+    label: '按负责人',
+  },
+  {
+    value: 'game_port_id',
+    label: '按游戏端口',
+  }
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 3 - 3
src/view/gameTask/uploadView.vue

@@ -42,11 +42,11 @@
     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
       <el-form :model="form" :rules="rules" ref="uploadForm" label-width="100px" class="demo-ruleForm">
         <el-form-item label="任务id" prop="task_id">
-          <el-input type="textarea" v-model="form.task_id" style="width:500px;"></el-input>
+          <el-input type="textarea" v-model="form.task_id" style="width:500px;" :disabled="true"></el-input>
         </el-form-item>
         <el-form-item label="负责人">
           <el-select v-model="form.responsible_person" placeholder="负责人">
-            <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" />
+            <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" :disabled="true"/>
           </el-select>
         </el-form-item>
         <el-form-item label="上传文件" prop="file">
@@ -54,7 +54,7 @@
             :on-exceed="handleExceed" :on-remove="handleRemove" :on-change="handleChange" :file-list="fileList.data"
             :http-request="httpRequest" :data="form" :auto-upload="false" name="annexFile" style="width: 500px;">
             <el-button size="small" type="primary">点击上传</el-button>
-            <div slot="tip" class="el-upload__tip">{{ message }}</div>
+            <el-text style="color:red;margin-left: 10px;font-size: larger;" class="mx-1" type="danger">{{ message }}</el-text>
           </el-upload>
         </el-form-item>
 

+ 220 - 0
src/view/ipLogList/gameIpList.vue

@@ -0,0 +1,220 @@
+<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 label="日期" prop="date">
+                    <el-date-picker v-model="searchInfo.date" size="default" type="daterange" unlink-panels
+                        range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :disabled-date="disabledDate"
+                        :shortcuts="shortcuts" />
+                </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-button class="excel-btn" size="small" type="primary" icon="download"
+                        @click="handleExcelExport">导出</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+        <div class="gva-table-box">
+            <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange">
+                <el-table-column type="selection" width="55" />
+                <el-table-column align="left" label="游戏id" min-width="150" prop="game_id" />
+                <!-- <el-table-column align="left" label="ip" min-width="150" prop="ip" /> -->
+                <el-table-column align="left" label="上报ip次数" min-width="150" prop="count_total" sortable="custom" />
+                <el-table-column align="left" label="任务完成" min-width="150" prop="task_count" sortable="custom" />
+                <el-table-column align="left" label="成功ip次数" min-width="150" prop="success_ip" sortable="custom" />
+                <el-table-column align="left" label="ip个数" min-width="150" prop="count_distinct_ip" sortable="custom" />
+                <el-table-column align="left" label="日期" min-width="150" prop="create_date" sortable="custom" />
+                <el-table-column align="left" fixed="right" label="操作" width="200">
+                    <template #default="scope">
+                        <el-button icon="search" size="small" type="primary" link
+                            @click="selectIpFunc(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="dialogTitle" width="40%">
+            <!-- <template #footer>
+                <div class="dialog-footer">
+                    <el-text class="mx-1" type="success">Success</el-text>
+                    <el-button size="small" @click="closeDialog">取 消</el-button> -->
+            <!-- </div>
+            </template> -->
+            <el-table :data="IpTableData" height="500" border>
+                <el-table-column align="center" label="ip" min-width="120" prop="ip" />
+                <el-table-column align="center" label="上报次数" min-width="120" prop="count" />
+            </el-table>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+export default {
+    name: 'GameList',
+}
+</script>
+  
+<script setup>
+import {
+    gameIpList,
+    getGameIp,
+    gameIpExport
+} from '@/api/ipLog'
+import { toSQLLine } from '@/utils/stringFun'
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import warningBar from '@/components/warningBar/warningBar.vue'
+import dayjs from "dayjs";
+const apis = ref([])
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const IpTableData = ref([])
+const searchInfo = ref({})
+
+const onReset = () => {
+    searchInfo.value = {}
+    getTableData()
+}
+
+// 搜索
+const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    if (typeof searchInfo.value.date != "undefined") {
+        searchInfo.value.date[0] = dayjs(searchInfo.value.date[0]).format(
+            "YYYY-MM-DD"
+        );
+        searchInfo.value.date[1] = dayjs(searchInfo.value.date[1]).format(
+            "YYYY-MM-DD"
+        );
+    }
+    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 gameIpList({ 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()
+
+// 查看IP
+const selectIpFunc = async (row) => {
+    const res = await getGameIp({ game_id: row.game_id, create_date: row.create_date })
+    IpTableData.value = res.data.list
+    IpTableData.value.total = res.data.total
+    openDialog('getIp')
+}
+
+//导出列表
+const handleExcelExport = async () => {
+    var fileName = Date.parse(new Date()) + "-ip.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 + "-ip.xlsx"
+    } else {
+        fileName = searchInfo.value.create_date + "-ip.xlsx"
+    }
+    gameIpExport({ page: page.value, pageSize: pageSize.value, ...searchInfo.value }, fileName)
+}
+
+const closeDialog = () => {
+    dialogFormVisible.value = false
+}
+const dialogTitle = ref('')
+const type = ref('')
+const dialogFormVisible = ref(false)
+const openDialog = (key) => {
+    switch (key) {
+        case 'getIp':
+            dialogTitle.value = 'ip个数:' + IpTableData.value.total
+            break
+        default:
+            break
+    }
+    type.value = key
+    dialogFormVisible.value = true
+}
+
+// 批量操作
+const handleSelectionChange = (val) => {
+    apis.value = val
+}
+
+
+
+// 弹窗相关
+// const apiForm = ref(null)
+// const initForm = () => {
+//     apiForm.value.resetFields()
+//     form.value = {
+//         game_name: '',
+//         game_package_name: ''
+//     }
+// }
+
+</script>
+  
+<style scoped lang="scss">
+.button-box {
+    padding: 10px 20px;
+
+    .el-button {
+        float: right;
+    }
+}
+
+.warning {
+    color: #dc143c;
+}
+</style>
+  

+ 203 - 0
src/view/ipLogList/list.vue

@@ -0,0 +1,203 @@
+<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="电脑编号">
+                    <el-input v-model="searchInfo.pc_code" placeholder="电脑编号" />
+                </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 label="日期" prop="date">
+                    <el-date-picker v-model="searchInfo.date" size="default" type="daterange" unlink-panels
+                        range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :disabled-date="disabledDate"
+                        :shortcuts="shortcuts" />
+                </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">
+                <el-table-column type="selection" width="55" />
+                <el-table-column align="left" label="电脑编号" min-width="100" prop="pc_code" />
+                <el-table-column align="left" label="游戏id" min-width="150" prop="game_id" sortable="custom" />
+                <!-- <el-table-column align="left" label="ip" min-width="150" prop="ip" /> -->
+
+                <el-table-column align="left" label="上报ip次数" min-width="150" prop="count_total" sortable="custom" />
+                <el-table-column align="left" label="ip个数" min-width="150" prop="count_distinct_ip" sortable="custom" />
+                <el-table-column align="left" label="日期" min-width="150" prop="create_date" sortable="custom" />
+                <el-table-column align="left" fixed="right" label="操作" width="200">
+                    <template #default="scope">
+                        <el-button icon="search" size="small" type="primary" link
+                            @click="selectIpFunc(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="dialogTitle" width="40%">
+            <!-- <template #footer>
+                <div class="dialog-footer">
+                    <el-text class="mx-1" type="success">Success</el-text>
+                    <el-button size="small" @click="closeDialog">取 消</el-button> -->
+            <!-- </div>
+            </template> -->
+            <el-table :data="IpTableData" height="500" border>
+                <el-table-column align="center" label="ip" min-width="120" prop="ip" />
+                <el-table-column align="center" label="上报次数" min-width="120" prop="count" />
+            </el-table>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+export default {
+    name: 'GameList',
+}
+</script>
+  
+<script setup>
+import {
+    ipLogList,
+    getIp
+} from '@/api/ipLog'
+import { toSQLLine } from '@/utils/stringFun'
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import warningBar from '@/components/warningBar/warningBar.vue'
+import dayjs from "dayjs";
+const apis = ref([])
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const IpTableData = ref([])
+const searchInfo = ref({})
+
+const onReset = () => {
+    searchInfo.value = {}
+    getTableData()
+}
+
+// 搜索
+const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.game_id = Number(searchInfo.value.game_id)
+    if (typeof searchInfo.value.date != "undefined") {
+        searchInfo.value.date[0] = dayjs(searchInfo.value.date[0]).format(
+            "YYYY-MM-DD"
+        );
+        searchInfo.value.date[1] = dayjs(searchInfo.value.date[1]).format(
+            "YYYY-MM-DD"
+        );
+    }
+    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 ipLogList({ 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()
+
+// 查看IP
+const selectIpFunc = async (row) => {
+    const res = await getIp({ game_id: row.game_id, pc_code: row.pc_code, create_date: row.create_date })
+    IpTableData.value = res.data.list
+    IpTableData.value.total = res.data.total
+    openDialog('getIp')
+}
+const closeDialog = () => {
+    dialogFormVisible.value = false
+}
+const dialogTitle = ref('')
+const type = ref('')
+const dialogFormVisible = ref(false)
+const openDialog = (key) => {
+    switch (key) {
+        case 'getIp':
+            dialogTitle.value = 'ip个数:' + IpTableData.value.total
+            break
+        default:
+            break
+    }
+    type.value = key
+    dialogFormVisible.value = true
+}
+
+// 批量操作
+const handleSelectionChange = (val) => {
+    apis.value = val
+}
+
+
+
+// 弹窗相关
+// const apiForm = ref(null)
+// const initForm = () => {
+//     apiForm.value.resetFields()
+//     form.value = {
+//         game_name: '',
+//         game_package_name: ''
+//     }
+// }
+
+</script>
+  
+<style scoped lang="scss">
+.button-box {
+    padding: 10px 20px;
+
+    .el-button {
+        float: right;
+    }
+}
+
+.warning {
+    color: #dc143c;
+}
+</style>
+  

+ 82 - 53
src/view/logComputer/list.vue

@@ -49,13 +49,29 @@
           <el-table-column align="left" label="脚本负责人" min-width="150" prop="operator" sortable="custom"/>
           <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="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-column align="left" label="总任务" min-width="120" prop="target_num" />
+          <el-table-column align="left" label="拉取账号" min-width="120" prop="pull_account_num" />
+          <el-table-column align="left" label="进入主线" min-width="120" prop="enter_main" />
+          <el-table-column align="left" label="主线成功" min-width="120" prop="task_success_num" />
+          <el-table-column align="left" label="半小时内付费" min-width="120" prop="computer_fee_rate" />
+          <el-table-column align="left" label="任务完成效率(/h)" min-width="120" prop="computer_hour_average_rate" />
+          <el-table-column align="left" label="空闲时间" min-width="120" prop="computer_free_time" />
+          <el-table-column
+          fixed="right"
+          label="操作"
+          align="center"
+          header-align="center"
+          min-width="150"
+        >
+          <template #default="scope">
+            <el-button
+              type="primary"
+              plain
+              @click="computerSevenRateTableData(scope.row)"
+              >7天</el-button
+            >
+          </template>
+        </el-table-column>
         </el-table>
         <div class="gva-pagination">
           <el-pagination
@@ -68,52 +84,67 @@
             @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>
+
+      <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle" width="100%">
+        <el-table :data="RateTableData" border >
+          <el-table-column align="left" label="电脑编号" min-width="100" prop="pc_code" sortable="custom"/>
+          <el-table-column align="left" label="脚本负责人" min-width="150" prop="operator" sortable="custom"/>
+          <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="120" prop="target_num" />
+          <el-table-column align="left" label="拉取账号" min-width="120" prop="pull_account_num" />
+          <el-table-column align="left" label="进入主线" min-width="120" prop="enter_main" />
+          <el-table-column align="left" label="主线成功" min-width="120" prop="task_success_num" />
+          <el-table-column align="left" label="半小时内付费" min-width="120" prop="computer_fee_rate" />
+          <el-table-column align="left" label="任务完成效率(/h)" min-width="120" prop="computer_hour_average_rate" />
+          <el-table-column align="left" label="空闲时间" min-width="120" prop="computer_free_time" />
+        </el-table>
         <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: 'GameList',
   }
   </script>
-  
+
   <script setup>
   import {
     logComputerList,
     logComputerNum,
     computerRateExport,
+    computerSevenRate,
   } 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 RateTableData = ref([])
+
+  const computerSevenRateTableData = async(row) => {
+    const table = await computerSevenRate({ pc_code:row.pc_code, ...searchInfo.value })
+    if (table.code === 0) {
+      RateTableData.value = table.data.list
+      dialogTitle.value = "电脑编号: " + row.pc_code
+      dialogFormVisible.value = true
+    }
+  }
+
   const type = ref('')
   const rules = ref({
     game_name: [{ required: true, message: '请输入游戏名称', trigger: 'blur' }],
@@ -121,12 +152,12 @@
       { 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,
@@ -139,24 +170,24 @@
       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 handleExcelExport = async() => {
     var fileName = Date.parse(new Date()) + "-cpc.xlsx"
     if(searchInfo.value.create_date == null){
@@ -183,7 +214,7 @@
       label: '失败',
     },
   ]
-  
+
   const options = [
     {
       value: 45010,
@@ -219,7 +250,7 @@
     },
   ]
   // 搜索
-  
+
   const onSubmit = () => {
     page.value = 1
     pageSize.value = 10
@@ -245,7 +276,7 @@
             }
           }
         }
-        console.log(spanArr)  
+        console.log(spanArr)
   }
 
   const objectSpanMethod = (row) => {
@@ -258,20 +289,20 @@
           }
         }
   }
- 
 
-  
+
+
   // 分页
   const handleSizeChange = (val) => {
     pageSize.value = val
     getTableData()
   }
-  
+
   const handleCurrentChange = (val) => {
     page.value = val
     getTableData()
   }
-  
+
   // 排序
   const sortChange = ({ prop, order }) => {
     if (prop) {
@@ -283,7 +314,7 @@
     }
     getTableData()
   }
-  
+
   // 查询
   const getTableData = async() => {
     const table = await logComputerList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
@@ -307,15 +338,15 @@
     }
   }
   getTableData()
-  
+
   // 批量操作
   const handleSelectionChange = (val) => {
     apis.value = val
   }
-  
+
   const deleteVisible = ref(false)
-  
-  
+
+
   // 弹窗相关
   const apiForm = ref(null)
   const initForm = () => {
@@ -325,8 +356,8 @@
       game_package_name: ''
     }
   }
-  
-  const dialogTitle = ref('新增game')
+
+  const dialogTitle = ref('pc_code')
   const dialogFormVisible = ref(false)
   const openDialog = (key) => {
     switch (key) {
@@ -343,16 +374,15 @@
     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) {
@@ -370,7 +400,7 @@
               getTableData()
               closeDialog()
             }
-  
+
             break
           case 'edit':
             {
@@ -400,10 +430,10 @@
       }
     })
   }
-  
-  
+
+
   </script>
-  
+
   <style scoped lang="scss">
   .button-box {
     padding: 10px 20px;
@@ -415,4 +445,3 @@
     color: #dc143c;
   }
   </style>
-  

+ 59 - 34
src/view/logStatistics/list.vue

@@ -23,11 +23,11 @@
         </el-form>
       </div>
       <div class="gva-table-box">
-        <el-table border 
-        :data="tableData" 
+        <el-table border
+        :data="tableData"
         :span-method="objectSpanMethod"
-        @sort-change="sortChange" 
-        @selection-change="handleSelectionChange" 
+        @sort-change="sortChange"
+        @selection-change="handleSelectionChange"
         header-align="center"
         >
           <el-table-column
@@ -107,6 +107,32 @@
           </el-table-column>
         </el-table-column>
       </el-table-column>
+      <el-table-column label="扫码完成率" align="center"  min-width="100" prop="local_order_success_rate" sortable="custom">
+        <el-table-column label="扫码成功" align="center">
+          <el-table-column prop="target_num,scanning_code_success" label="任务总数" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.scanning_code_success }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.target_num}}
+							<el-divider style="margin:0" />
+							{{ scope.row.scanning_code_success == 0  ? 0 + '%' : Math.round(scope.row.scanning_code_success/scope.row.target_num * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
+      </el-table-column>
+      <el-table-column label="完成扫码率" align="center"  min-width="100" prop="local_order_success_rate" sortable="custom">
+        <el-table-column label="扫码成功" align="center">
+          <el-table-column prop="new_complete,scanning_code_success" label="完成总数" align="center" min-width="100">
+            <template #default="scope">
+							{{ scope.row.scanning_code_success }}
+							<el-divider style="margin:0 5px" direction="vertical" />
+              {{ scope.row.new_complete}}
+							<el-divider style="margin:0" />
+							{{ scope.row.scanning_code_success == 0  ? 0 + '%' : Math.round(scope.row.scanning_code_success/scope.row.new_complete * 10000) / 100 + '%'}}
+						</template>
+          </el-table-column>
+        </el-table-column>
+      </el-table-column>
       <el-table-column label="微信扫码率" align="center"  min-width="100" prop="scanning_success_rate" sortable="custom">
         <el-table-column label="扫码成功" align="center">
           <el-table-column prop="scanning_code_success,enter_scanning_code" label="扫码总数" align="center" min-width="100">
@@ -138,8 +164,8 @@
       <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" />
@@ -156,9 +182,9 @@
             @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
@@ -172,13 +198,13 @@
       </el-dialog>
     </div>
   </template>
-  
+
   <script>
   export default {
     name: 'LogStatisticsList',
   }
   </script>
-  
+
   <script setup>
   import {
     logStatistics,
@@ -187,14 +213,14 @@
   import { createElementBlock, 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' }],
@@ -202,7 +228,7 @@
       { required: true, message: '请输入游戏包名', trigger: 'blur' }
     ]
   })
-  
+
   const page = ref(1)
   const total = ref(0)
   const pageSize = ref(10)
@@ -214,7 +240,7 @@
     searchInfo.value = {}
   }
   // 搜索
-  
+
   const onSubmit = () => {
     page.value = 1
     pageSize.value = 10
@@ -241,7 +267,7 @@
   const target = typeOptions.value.filter(item => item.value === value)[0]
   return target && `${target.label}`
 }
-  
+
 const renderheader = ({ column, $index  }) => {
   console.log(column)
   console.log($index)
@@ -265,12 +291,12 @@ const renderheader = ({ column, $index  }) => {
     pageSize.value = val
     getTableData()
   }
-  
+
   const handleCurrentChange = (val) => {
     page.value = val
     getTableData()
   }
-  
+
   const headerStyle = () => {
     return {
       fontSize:"12px"
@@ -288,7 +314,7 @@ const renderheader = ({ column, $index  }) => {
     getTableData()
   }
 
-  
+
   const getSpanArr = (data) => {
     spanArr = []
     var pos = 0
@@ -306,7 +332,7 @@ const renderheader = ({ column, $index  }) => {
             }
           }
         }
-        console.log(spanArr)  
+        console.log(spanArr)
   }
 
   const objectSpanMethod = (row) => {
@@ -319,7 +345,7 @@ const renderheader = ({ column, $index  }) => {
           }
         }
   }
-  
+
   // 查询
   const getTableData = async() => {
     const table = await logStatistics({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
@@ -331,17 +357,17 @@ const renderheader = ({ column, $index  }) => {
       getSpanArr(table.data.list)
     }
   }
-  
+
   getTableData()
-  
+
   // 批量操作
   const handleSelectionChange = (val) => {
     apis.value = val
   }
-  
+
   const deleteVisible = ref(false)
-  
-  
+
+
   // 弹窗相关
   const apiForm = ref(null)
   const initForm = () => {
@@ -351,7 +377,7 @@ const renderheader = ({ column, $index  }) => {
       game_package_name: ''
     }
   }
-  
+
   const dialogTitle = ref('新增game')
   const dialogFormVisible = ref(false)
   const openDialog = (key) => {
@@ -371,13 +397,13 @@ const renderheader = ({ column, $index  }) => {
   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) {
@@ -395,7 +421,7 @@ const renderheader = ({ column, $index  }) => {
               getTableData()
               closeDialog()
             }
-  
+
             break
           case 'edit':
             {
@@ -425,10 +451,10 @@ const renderheader = ({ column, $index  }) => {
       }
     })
   }
-  
-  
+
+
   </script>
-  
+
   <style scoped lang="scss">
   .el-table .cell {
   white-space: pre-wrap;   /*这是重点。文本换行*/
@@ -443,4 +469,3 @@ const renderheader = ({ column, $index  }) => {
     color: #dc143c;
   }
   </style>
-  

+ 185 - 0
src/view/logStatistics/scanningCode.vue

@@ -0,0 +1,185 @@
+<template>
+    <div>
+      <div class="gva-search-box">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+            <el-form-item label="分类">
+            <el-select v-model="searchInfo.task_type" 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.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="150" prop="game_id" sortable="custom" />
+          <el-table-column align="left" label="日期" min-width="150" prop="create_date" sortable="custom" />
+          <el-table-column align="left" label="订单号" min-width="150" prop="order_num" sortable="custom" />
+          <el-table-column align="left" label="供应商" min-width="150" prop="supplier" sortable="custom" />
+          <el-table-column align="left" label="上报时间" min-width="150" prop="create_time" sortable="custom" />
+          <el-table-column fixed="left" align="left" label="类型" min-width="60" prop="task_type" sortable="custom">
+          <template #default="scope">
+            <div>
+              {{ typeFiletr(scope.row.task_type) }}
+            </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: 'ScanningTotal',
+  }
+  </script>
+  
+  <script setup>
+  import {
+    getLogScanningList,
+
+  } 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 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 getLogScanningList({ 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 searchStatusOptions = ref([
+ {
+    value: 0,
+    label: '总数据',
+  },
+  {
+    value: -1,
+    label: '新增',
+  },
+  {
+    value: 1,
+    label: '留存',
+  }
+])
+
+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: ''
+  }
+])
+  
+  </script>
+  
+  <style scoped lang="scss">
+  .button-box {
+    padding: 10px 20px;
+    .el-button {
+      float: right;
+    }
+  }
+  .warning {
+    color: #dc143c;
+  }
+  </style>
+  

+ 331 - 288
src/view/typeManage/responsiblePerson.vue

@@ -1,49 +1,38 @@
 <template>
   <div>
     <div class="gva-search-box">
-        <el-form ref="searchForm" :inline="true" :model="searchInfo">
-          <el-form-item>
-            <el-select v-model="searchInfo.searchKey"  >
-              <el-option
-                v-for="item in searchOptions"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-input v-model="searchInfo.name" placeholder="请输入关键字"/>
-          </el-form-item>
-          <el-form-item>
-            <el-button size="small" type="primary" icon="search" @click="onSubmit">搜索</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-      <div class="gva-btn-list">
-          <el-button size="small" icon="refresh" @click="onReset">刷新</el-button>
-          <el-button size="small" type="primary" icon="plus" @click="openDialog('addResponsiblePerson')">新增</el-button>
-          <el-popover v-model="deleteVisible" placement="top" width="160">
-            <p>确定要删除吗?</p>
-            <div style="text-align: right; margin-top: 8px;">
-              <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button>
-              <el-button size="small" type="primary" @click="onDelete">确定</el-button>
-            </div>
-            <template #reference>
-              <el-button icon="delete" type="danger" size="small" :disabled="!apis.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>
-            </template>
-          </el-popover>
+      <el-form ref="searchForm" :inline="true" :model="searchInfo">
+        <el-form-item>
+          <el-select v-model="searchInfo.searchKey">
+            <el-option v-for="item in searchOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-input v-model="searchInfo.name" placeholder="请输入关键字" />
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" type="primary" icon="search" @click="onSubmit">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="gva-btn-list">
+      <el-button size="small" icon="refresh" @click="onReset">刷新</el-button>
+      <el-button size="small" type="primary" icon="plus" @click="openDialog('addResponsiblePerson')">新增</el-button>
+      <el-popover v-model="deleteVisible" placement="top" width="160">
+        <p>确定要删除吗?</p>
+        <div style="text-align: right; margin-top: 8px;">
+          <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button>
+          <el-button size="small" type="primary" @click="onDelete">确定</el-button>
         </div>
+        <template #reference>
+          <el-button icon="delete" type="danger" size="small" :disabled="!apis.length" style="margin-left: 10px;"
+            @click="deleteVisible = true">删除</el-button>
+        </template>
+      </el-popover>
+    </div>
     <div class="gva-table-box">
-      <el-table
-        :data="tableData"
-        @sort-change="sortChange" 
-        @selection-change="handleSelectionChange"
-      >
-      <el-table-column
-            type="selection"
-            width="55"
-          />
+      <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" />
         <el-table-column align="center" label="头像" min-width="100">
           <template #default="scope">
             <CustomPic style="margin-top:8px" :pic-src="scope.row.img" />
@@ -54,60 +43,39 @@
         <el-table-column align="left" label="部门名称" min-width="150" prop="department_name" />
         <el-table-column align="left" label="手机号码" min-width="150" prop="mobile_phone_number" />
         <el-table-column align="left" label="游戏数量" min-width="150" prop="game_counts" />
+        <el-table-column align="left" label="托管人" min-width="150" prop="custodians" />
+        <el-table-column align="left" label="开始时间" min-width="150" prop="start_time" />
+        <el-table-column align="left" label="url" min-width="150" prop="url" />
         <el-table-column align="left" label="备注" min-width="150" prop="remark" />
-        <el-table-column align="center" label="状态" min-width="150" prop="state" >
+        <el-table-column align="left" label="状态" min-width="100">
+          <template #default="scope">
+            <el-switch v-model="scope.row.state" inline-prompt :active-value="1" :inactive-value="-1"
+              @change="() => { switchEnable(scope.row) }" />
+          </template>
+        </el-table-column>
+        <el-table-column align="left" label="推送状态" min-width="100">
           <template #default="scope">
-            <el-button size="small"
-            :type="scope.row.state == 2 ? 'danger' : 'success'">
-            {{scope.row.state == 2? '禁用' : '启用'}}
-            </el-button>
+            <el-switch v-model="scope.row.push_status" inline-prompt :active-value="1" :inactive-value="-1"
+              @change="() => { switchPushEnable(scope.row) }" />
           </template>
         </el-table-column>
         <el-table-column align="left" label="创建时间" min-width="200" prop="createTime" sortable="custom" />
-
-
         <el-table-column align="left" fixed="right" label="操作" width="200">
-            <template #default="scope">
-              <el-button
-                icon="edit"
-                size="small"
-                type="primary"
-                link
-                @click="editApiFunc(scope.row)"
-              >编辑</el-button>
-              <el-button
-                icon="delete"
-                size="small"
-                type="primary"
-                link
-                @click="deleteApiFunc(scope.row)"
-              >删除</el-button>
-            </template>
-          </el-table-column>
+          <template #default="scope">
+            <el-button icon="edit" size="small" type="primary" link @click="editApiFunc(scope.row)">编辑</el-button>
+            <el-button icon="delete" size="small" type="primary" link @click="deleteApiFunc(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"
-        />
+        <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"
-      
-      custom-class="user-dialog"
-      :before-close="closeDialog"
-      :title="dialogTitle"
-      :show-close="false"
-      :close-on-press-escape="false"
-      :close-on-click-modal="false"
-    >
+    <el-dialog v-model="dialogFormVisible" custom-class="user-dialog" :before-close="closeDialog" :title="dialogTitle"
+      :show-close="false" :close-on-press-escape="false" :close-on-click-modal="false">
       <div style="height:60vh;overflow:auto;padding:0 12px;">
         <el-form ref="userForm" :rules="rules" :model="userInfo" label-width="80px">
           <el-form-item label="姓名" prop="name">
@@ -122,18 +90,39 @@
           <el-form-item label="手机号码" prop="mobile_phone_number">
             <el-input v-model="userInfo.mobile_phone_number" />
           </el-form-item>
+          <el-form-item label="开始时间" prop="start_time">
+            <el-input-number v-model="userInfo.start_time" :min="0" :max="16" @change="handleChange" placeholder="0" />
+          </el-form-item>
+          <el-form-item label="url" prop="url">
+            <el-input v-model="userInfo.url" />
+          </el-form-item>
+          <el-form-item label="托管状态" prop="managed_status">
+            <el-radio-group v-model="userInfo.managed_status" class="ml-4">
+              <el-radio label="1" size="small">需要托管</el-radio>
+              <el-radio label="-1" size="small">不需要托管</el-radio>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="托管人" prop="custodians" v-if="dialogTitle == '新增' && userInfo.managed_status == '1'">
+            <el-input v-model="userInfo.custodians" />
+          </el-form-item>
+          <el-form-item label="托管人" v-if="dialogTitle == '编辑' && userInfo.managed_status == '1'">
+            <el-select v-model="userInfo.custodians" placeholder="托管人">
+              <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" />
+            </el-select>
+          </el-form-item>
           <el-form-item label="备注" prop="remark">
             <el-input v-model="userInfo.remark" />
           </el-form-item>
-          <el-form-item label="状态" prop="state">
+          <!-- <el-form-item label="状态" prop="state">
             <el-radio-group v-model="userInfo.state" class="ml-4">
-              <el-radio :label="1"  size="large">开启</el-radio>
-              <el-radio :label="2"  size="large">关闭</el-radio>
+              <el-radio :label="1" size="large">开启</el-radio>
+              <el-radio :label="2" size="large">关闭</el-radio>
             </el-radio-group>
-          </el-form-item>
+          </el-form-item> -->
           <el-form-item label="头像" label-width="80px">
             <div style="display:inline-block" @click="openHeaderChange">
-              <img v-if="userInfo.img" class="header-img-box" :src="(userInfo.img && userInfo.img.slice(0, 4) !== 'http')?path+userInfo.img:userInfo.img">
+              <img v-if="userInfo.img" class="header-img-box"
+                :src="(userInfo.img && userInfo.img.slice(0, 4) !== 'http') ? path + userInfo.img : userInfo.img">
               <div v-else class="header-img-box">从媒体库选择</div>
             </div>
           </el-form-item>
@@ -168,6 +157,9 @@ import {
   createApi,
   updateApi,
   deleteApi,
+  statusChange,
+  pushStatusChange,
+  selectResponsiblePerson,
   deleteApisByIds
 } from '@/api/responsiblePerson'
 import { toSQLLine } from '@/utils/stringFun'
@@ -180,100 +172,151 @@ import { ElMessage, ElMessageBox } from 'element-plus'
 import User from '../superAdmin/user/user.vue'
 
 
-  const form = ref({
+const rules = ref({
+  name: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
+  custodians: [{ required: true, message: '托管人不能为空', trigger: 'blur' }],
+})
 
-  })
-  const     searchOptions = ref([
-    {
-      value: 'name',
-      label: '姓名',
-
-    },
-  ])
-  const type = ref('')
-  const page = ref(1)
-  const total = ref(0)
-  const pageSize = ref(10)
-  const tableData = ref([])
-  const searchInfo = ref({
-    searchKey:"name",
-  })
-  
-  const onReset = () => {
-    searchInfo.value = {}
-  }
 
+const form = ref({
 
+})
+const searchOptions = ref([
+  {
+    value: 'name',
+    label: '姓名',
 
- // 搜索
-  
- const onSubmit = () => {
-    page.value = 1
-    pageSize.value = 10
-    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 type = ref('')
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const searchInfo = ref({
+  searchKey: "name",
+})
+
+const onReset = () => {
+  searchInfo.value = {}
+}
+
+const getResponsiblePerson = async () => {
+  const table = await selectResponsiblePerson()
+  if (table.code === 0) {
+    ResponsiblePerson.value = table.data
   }
-  
-  // 查询
-  const getTableData = async() => {
-    const table = await getApiList({ 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
+}
+getResponsiblePerson()
+
+const ResponsiblePerson = ref([{}])
+
+
+
+// 搜索
+const onSubmit = () => {
+  page.value = 1
+  pageSize.value = 10
+  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 handleSelectionChange = (val) => {
-    apis.value = val
+}
+
+// 查询
+const getTableData = async () => {
+  const table = await getApiList({ 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
   }
-  const apis = ref([])
-  const deleteVisible = ref(false)
-  const onDelete = async() => {
-    const ids = apis.value.map(item => item.id)
-    const res = await deleteApisByIds({ ids })
-    if (res.code === 0) {
-      ElMessage({
-        type: 'success',
-        message: res.msg
-      })
-      if (tableData.value.length === ids.length && page.value > 1) {
-        page.value--
-      }
-      deleteVisible.value = false
-      getTableData()
+}
+
+getTableData()
+
+//更改状态
+const switchEnable = async (row) => {
+  const res = await statusChange({ state: row.state, id: row.id })
+  if (res.code === 0) {
+    ElMessage({ type: 'success', message: `${row.state === -1 ? '停止' : '开启'}成功` })
+  }
+}
+
+//更改推送状态
+const switchPushEnable = async (row) => {
+  const res = await pushStatusChange({ state: row.push_status, id: row.id })
+  if (res.code === 0) {
+    ElMessage({ type: 'success', message: `${row.state === -1 ? '停止' : '开启'}成功` })
+  }
+}
+
+
+// 批量操作
+const handleSelectionChange = (val) => {
+  apis.value = val
+}
+const apis = ref([])
+const deleteVisible = ref(false)
+const onDelete = async () => {
+  const ids = apis.value.map(item => item.id)
+  const res = await deleteApisByIds({ ids })
+  if (res.code === 0) {
+    ElMessage({
+      type: 'success',
+      message: res.msg
+    })
+    if (tableData.value.length === ids.length && page.value > 1) {
+      page.value--
     }
+    deleteVisible.value = false
+    getTableData()
+    getResponsiblePerson()
   }
-  
+}
+
+
+// 弹窗相关
+const userInfo = ref({
+  name: '',
+  nickname: '',
+  department_name: '',
+  mobile_phone_number: '',
+  remark: '',
+  state: 0,
+  img: '',
+  custodians: '',
+  push_status: 0,
+})
+const path = ref(import.meta.env.VITE_BASE_API + '/')
+
 
-  // 弹窗相关
-  const userInfo = ref({
+
+const userForm = ref(null)
+const initForm = () => {
+  userForm.value.resetFields()
+  userInfo.value = {
     name: '',
     nickname: '',
     department_name: '',
@@ -281,143 +324,140 @@ import User from '../superAdmin/user/user.vue'
     remark: '',
     state: 0,
     img: '',
-  })
-  const path = ref(import.meta.env.VITE_BASE_API + '/')
+    custodians: '',
+    push_status: 0,
+  }
+}
 
+const dialogTitle = ref('新增Api')
+const dialogFormVisible = ref(false)
+const openDialog = (key) => {
+  switch (key) {
+    case 'addResponsiblePerson':
+      dialogTitle.value = '新增'
+      break
+    case 'editResponsiblePerson':
+      dialogTitle.value = '编辑'
+      break
+    default:
+      break
+  }
 
+  type.value = key
+  dialogFormVisible.value = true
+}
+const closeDialog = () => {
+  initForm()
+  dialogFormVisible.value = false
+  userInfo.value.img = ''
+}
 
-  const userForm = ref(null)
-  const initForm = () => {
-    userForm.value.resetFields()
-    userInfo.value = {
-      name: '',
-      nickname: '',
-      department_name: '',
-      mobile_phone_number: '',
-      remark: '',
-      state: 0,
-      img: '',
-    }
-  }
-  
-  const dialogTitle = ref('新增Api')
-  const dialogFormVisible = ref(false)
-  const openDialog = (key) => {
-    switch (key) {
-      case 'addResponsiblePerson':
-        dialogTitle.value = '新增'
-        break
-      case 'editResponsiblePerson':
-        dialogTitle.value = '编辑'
-        break
-      default:
-        break
-    }
+const editApiFunc = async (row) => {
+  const res = await getApiById({ id: row.id })
+  userInfo.value = res.data.responsible_person
+  openDialog('editResponsiblePerson')
+}
 
-    type.value = key
-    dialogFormVisible.value = true
-  }
-  const closeDialog = () => {
-    initForm()
-    dialogFormVisible.value = false
-    userInfo.value.img = ''
-  }
-  
-  const editApiFunc = async(row) => {
-    const res = await getApiById({ id: row.id })
-    userInfo.value = res.data.responsible_person
-    openDialog('editResponsiblePerson')
-  }
-  
-  const enterDialog = async() => {
-    userForm.value.validate(async valid => {
-      if (valid) {
-        switch (type.value) {
-          case 'addResponsiblePerson':
-            {
-              const res = await createApi(userInfo.value)
-              if (res.code === 0) {
-                ElMessage({
-                  type: 'success',
-                  message: '添加成功',
-                  showClose: true
-                })
-              }
-              getTableData()
-              closeDialog()
+const enterDialog = async () => {
+  userForm.value.validate(async valid => {
+    if (valid) {
+      switch (type.value) {
+        case 'addResponsiblePerson':
+          {
+            userInfo.value.managed_status = Number(userInfo.value.managed_status)
+            const res = await createApi(userInfo.value)
+            if (res.code === 0) {
+              ElMessage({
+                type: 'success',
+                message: '添加成功',
+                showClose: true
+              })
             }
-  
-            break
-          case 'editResponsiblePerson':
-            {
-              const res = await updateApi(userInfo.value)
-              if (res.code === 0) {
-                ElMessage({
-                  type: 'success',
-                  message: '编辑成功',
-                  showClose: true
-                })
-              }
-              getTableData()
-              closeDialog()
+            getTableData()
+            getResponsiblePerson()
+            closeDialog()
+          }
+
+          break
+        case 'editResponsiblePerson':
+          {
+            userInfo.value.managed_status = Number(userInfo.value.managed_status)
+            //如果不需要托管,则将托管人置为空
+            if (userInfo.value.managed_status === -1) {
+              userInfo.value.custodians = ''
             }
-            break
-          default:
-            // eslint-disable-next-line no-lone-blocks
-            {
+            const res = await updateApi(userInfo.value)
+            if (res.code === 0) {
               ElMessage({
-                type: 'error',
-                message: '未知操作',
+                type: 'success',
+                message: '编辑成功',
                 showClose: true
               })
             }
-            break
+            getTableData()
+            getResponsiblePerson()
+            closeDialog()
+          }
+          break
+        default:
+          // eslint-disable-next-line no-lone-blocks
+          {
+            ElMessage({
+              type: 'error',
+              message: '未知操作',
+              showClose: true
+            })
+          }
+          break
+      }
+    }
+  })
+}
+const chooseImg = ref(null)
+const openHeaderChange = () => {
+  chooseImg.value.open()
+}
+
+const deleteApiFunc = async (row) => {
+  ElMessageBox.confirm('此操作将永久删除此负责人, 是否继续?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(async () => {
+      const res = await deleteApi(row)
+      if (res.code === 0) {
+        ElMessage({
+          type: 'success',
+          message: '删除成功!'
+        })
+        if (tableData.value.length === 1 && page.value > 1) {
+          page.value--
         }
+        getTableData()
+        getResponsiblePerson()
       }
     })
-  }
-  const chooseImg = ref(null)
-  const openHeaderChange = () => {
-    chooseImg.value.open()
-  } 
-
-  const deleteApiFunc = async(row) => {
-    ElMessageBox.confirm('此操作将永久删除此负责人, 是否继续?', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
-      .then(async() => {
-        const res = await deleteApi(row)
-        if (res.code === 0) {
-          ElMessage({
-            type: 'success',
-            message: '删除成功!'
-          })
-          if (tableData.value.length === 1 && page.value > 1) {
-            page.value--
-          }
-          getTableData()
-        }
-      })
-  }
+}
 
 </script>
 
 <style lang="scss">
 .user-dialog {
   .header-img-box {
-  width: 200px;
-  height: 200px;
-  border: 1px dashed #ccc;
-  border-radius: 20px;
-  text-align: center;
-  line-height: 200px;
-  cursor: pointer;
-}
+    width: 200px;
+    height: 200px;
+    border: 1px dashed #ccc;
+    border-radius: 20px;
+    text-align: center;
+    line-height: 200px;
+    cursor: pointer;
+  }
+
   .avatar-uploader .el-upload:hover {
     border-color: #409eff;
   }
+
   .avatar-uploader-icon {
     border: 1px dashed #d9d9d9 !important;
     border-radius: 6px;
@@ -428,18 +468,21 @@ import User from '../superAdmin/user/user.vue'
     line-height: 178px;
     text-align: center;
   }
+
   .avatar {
     width: 178px;
     height: 178px;
     display: block;
   }
 }
-.nickName{
+
+.nickName {
   display: flex;
   justify-content: flex-start;
   align-items: center;
 }
-.pointer{
+
+.pointer {
   cursor: pointer;
   font-size: 16px;
   margin-left: 2px;