Browse Source

渠道总览

ith5 5 months ago
parent
commit
11d0f342d1

+ 44 - 0
src/components/auth-select/index.vue

@@ -0,0 +1,44 @@
+<template>
+  <a-select
+    @change="onUpdate"
+    :model-value="modelValue"
+    :options="authOptions"
+    placeholder="请选择负责人"
+    allow-search
+    :max-tag-count="1"
+    :multiple="multiple"
+    allow-clear />
+</template>
+<script setup>
+import { ref, onMounted, defineProps, defineEmits } from 'vue'
+import advertCommonApi from '@/views/v1/api/advert/common'
+
+const authOptions = ref([])
+
+const props = defineProps({
+  modelValue: {
+    type: [String, Number, Array],
+    default: '',
+  },
+  multiple: {
+    type: Boolean,
+    default: false,
+  },
+})
+
+const emit = defineEmits(['update:modelValue'])
+const onUpdate = (val) => {
+  emit('update:modelValue', val)
+}
+
+// 获取后台归属人列表
+const getAuthList = async () => {
+  const res = await advertCommonApi.getAuthOptionsApi()
+  if (res.code == 200) {
+    authOptions.value = res.data
+  }
+}
+onMounted(() => {
+  getAuthList()
+})
+</script>

File diff suppressed because it is too large
+ 284 - 451
src/components/sa-table/index.vue


+ 56 - 79
src/views/v1/advert/agenList/index.vue

@@ -1,64 +1,39 @@
 <template>
   <div class="ma-content-block">
-    <sa-table
-      ref="crudRef"
-      :options="options"
-      :columns="columns"
-      :searchForm="searchForm"
-    >
+    <sa-table ref="crudRef" :options="options" :columns="columns" :searchForm="searchForm">
       <!-- 搜索区 tableSearch -->
       <template #tableSearch>
         <a-col :sm="8" :xs="24">
           <a-form-item label="渠道类型" field="media_id">
-            <a-select
-              v-model="searchForm.media_id"
-              placeholder="请选择渠道类型"
-              allow-clear
-            >
+            <a-select v-model="searchForm.media_id" placeholder="请选择渠道类型" allow-clear>
               <a-option
                 v-for="item in mediaOptions"
                 :key="item.id"
                 :value="item.id"
-                :label="`${item.id}:${item.name}`"
-              />
+                :label="`${item.id}:${item.name}`" />
             </a-select>
           </a-form-item>
         </a-col>
         <a-col :sm="8" :xs="24">
           <a-form-item label="渠道名称" field="name">
-            <a-input
-              v-model="searchForm.name"
-              placeholder="请输入渠道名称"
-              allow-clear
-            />
+            <a-input v-model="searchForm.name" placeholder="请输入渠道名称" allow-clear />
           </a-form-item>
         </a-col>
         <a-col :sm="8" :xs="24">
           <a-form-item label="渠道ID" field="id">
-            <a-input
-              v-model="searchForm.id"
-              placeholder="请输入渠道ID"
-              allow-clear
-            />
+            <a-input v-model="searchForm.id" placeholder="请输入渠道ID" allow-clear />
           </a-form-item>
         </a-col>
         <a-col :sm="8" :xs="24">
           <a-form-item label="后台归属人" field="auth_id">
-            <a-select
-              v-model="searchForm.auth_id"
-              :options="authOptions"
-              placeholder="请选择后台归属人"
-              allow-clear
-            />
+            <a-select v-model="searchForm.auth_id" :options="authOptions" placeholder="请选择后台归属人" allow-clear />
           </a-form-item>
         </a-col>
       </template>
 
       <!-- Table 自定义渲染 -->
       <template #operationBeforeExtend="{ record }">
-        <a-button type="text" @click="addAdvert(record)">
-          <icon-plus /> 添加广告位
-        </a-button>
+        <a-button type="text" @click="addAdvert(record)"> <icon-plus /> 添加广告位 </a-button>
       </template>
     </sa-table>
 
@@ -71,32 +46,32 @@
 </template>
 
 <script setup>
-import { onMounted, ref, reactive } from "vue";
-import { Message } from "@arco-design/web-vue";
-import EditForm from "./edit.vue";
-import addSiteForm from "./addSite.vue";
-import api from "../../api/advert/agenList";
-import advertCommonApi from "../../api/advert/common";
+import { onMounted, ref, reactive } from 'vue'
+import { Message } from '@arco-design/web-vue'
+import EditForm from './edit.vue'
+import addSiteForm from './addSite.vue'
+import api from '../../api/advert/agenList'
+import advertCommonApi from '../../api/advert/common'
 
 // 引用定义
-const crudRef = ref();
-const editRef = ref();
-const viewRef = ref();
-const addSiteRef = ref();
+const crudRef = ref()
+const editRef = ref()
+const viewRef = ref()
+const addSiteRef = ref()
 
-const authOptions = ref([]);
-const mediaOptions = ref([]);
+const authOptions = ref([])
+const mediaOptions = ref([])
 // 搜索表单
 const searchForm = ref({
-  auth_id: "",
-  name: "",
-});
+  auth_id: '',
+  name: '',
+})
 
 // 添加广告位
 const addAdvert = (record) => {
-  addSiteRef.value?.open();
-  addSiteRef.value?.setFormData(record);
-};
+  addSiteRef.value?.open()
+  addSiteRef.value?.setFormData(record)
+}
 
 // SaTable 基础配置
 const options = reactive({
@@ -104,69 +79,71 @@ const options = reactive({
   rowSelection: { showCheckedAll: true },
   add: {
     show: true,
-    auth: ["/v1/advert/AgentList/save"],
+    auth: ['/v1/advert/AgentList/save'],
     func: async () => {
-      editRef.value?.open();
+      editRef.value?.open()
     },
   },
   edit: {
     show: true,
-    auth: ["/v1/advert/AgentList/update"],
+    auth: ['/v1/advert/AgentList/update'],
     func: async (record) => {
-      editRef.value?.open("edit");
-      editRef.value?.setFormData(record);
+      editRef.value?.open('edit')
+      editRef.value?.setFormData(record)
     },
   },
   delete: {
     show: true,
-    auth: ["/v1/advert/AgentList/destroy"],
+    auth: ['/v1/advert/AgentList/destroy'],
     func: async (params) => {
-      const resp = await api.destroy(params);
+      const resp = await api.destroy(params)
       if (resp.code === 200) {
-        Message.success(`删除成功!`);
-        crudRef.value?.refresh();
+        Message.success(`删除成功!`)
+        crudRef.value?.refresh()
       }
     },
   },
-});
+})
 
 // SaTable 列配置
 const columns = reactive([
-  { title: "媒体ID", dataIndex: "media_id", width: 120 },
-  { title: "媒体", dataIndex: "media_name", width: 180 },
-  { title: "渠道名称", dataIndex: "name", width: 180 },
-  { title: "后台归属人", dataIndex: "auth_name", width: 180 },
-]);
+  { title: 'ID', dataIndex: 'id', width: 80 },
+
+  { title: '渠道名称', dataIndex: 'name', width: 120 },
+  { title: '媒体ID', dataIndex: 'media_id', width: 80 },
+  { title: '媒体', dataIndex: 'media_name', width: 120 },
+  { title: '后台归属人', dataIndex: 'auth_name', width: 120 },
+])
 
 // 页面数据初始化
 const initPage = async () => {
-  await getAuthOptions();
-  await getMediaOptions();
-};
+  await getAuthOptions()
+  await getMediaOptions()
+}
 
 const getAuthOptions = async () => {
-  const resp = await advertCommonApi.getAuthOptionsApi();
+  const resp = await advertCommonApi.getAuthOptionsApi()
   if (resp.code === 200) {
-    authOptions.value = resp.data;
+    authOptions.value = resp.data
   }
-};
+}
 
 // 获取媒体列表Options
 const getMediaOptions = async () => {
-  const res = await advertCommonApi.getMediaOptionsApi();
+  const res = await advertCommonApi.getMediaOptionsApi()
   if (res.code == 200) {
-    mediaOptions.value = res.data;
+    mediaOptions.value = res.data
   }
-};
+}
 
 // SaTable 数据请求
 const refresh = async () => {
-  crudRef.value?.refresh();
-};
+  crudRef.value?.refresh()
+}
 
 // 页面加载完成执行
 onMounted(async () => {
-  initPage();
-  refresh();
-});
+  initPage()
+  refresh()
+})
 </script>

+ 20 - 0
src/views/v1/api/gameLog/channelAnalysis.js

@@ -14,5 +14,25 @@ export default {
       method: 'get',
       params
     })
+  },
+  /**
+   * 留存按日
+   */
+  getActiveList(params = {}) {
+    return request({
+      url: '/v1/gameLog/channelAnalysis/getActiveDataList',
+      method: 'get',
+      params
+    })
+  },
+  /**
+   * 渠道总览
+   */
+  getAgentDataList(params = {}) {
+    return request({
+      url: '/v1/gameLog/channelAnalysis/getAgentDataList',
+      method: 'get',
+      params
+    })
   }
 }

+ 133 - 0
src/views/v1/gameLog/active/index.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table ref="crudRef" :options="options" :columns="columns" :searchForm="searchForm">
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="游戏" field="game_id">
+            <game-select v-model="searchForm.game_id" multiple />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="注册日期" field="reg_date">
+            <a-range-picker class="w-full" v-model="searchForm.reg_date" :show-time="false" mode="date" />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="媒体类型" field="media_id">
+            <media-select v-model="searchForm.media_id" />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="渠道ID" field="agent_id">
+            <a-input v-model="searchForm.agent_id" placeholder="请输入渠道ID" allow-clear />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="广告位ID" field="site_id">
+            <a-input v-model="searchForm.site_id" placeholder="请输入广告位ID" allow-clear />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="负责人" field="auth_id">
+            <auth-select v-model="searchForm.auth_id" />
+          </a-form-item>
+        </a-col>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+    </sa-table>
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from 'vue'
+import api from '../../api/gameLog/channelAnalysis'
+import dayjs from 'dayjs'
+import GameSelect from '@/components/game-select/index.vue'
+import MediaSelect from '@/components/media-select/index.vue'
+
+import AuthSelect from '@/components/auth-select/index.vue'
+
+// 引用定义
+const crudRef = ref()
+const gameList = ref([])
+
+// 搜索表单
+const searchForm = ref({
+  game_id: '',
+  media_id: '',
+  auth_id: '',
+  agent_id: '',
+  site_id: '',
+  reg_date: [],
+})
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getActiveList,
+  pk: 'id',
+  rowSelection: { showCheckedAll: true },
+  showSort: false,
+
+  operationColumn: false,
+})
+
+// SaTable 列配置
+const columns = reactive([
+  { title: '日期', dataIndex: 'tdate', width: 120, fixed: 'left' },
+  { title: '注册数', dataIndex: 'reg', width: 120, fixed: 'left' },
+  { title: '1', dataIndex: 'd1', width: 120 },
+  { title: '2', dataIndex: 'd2', width: 120 },
+  { title: '3', dataIndex: 'd3', width: 120 },
+  { title: '4', dataIndex: 'd4', width: 120 },
+  { title: '5', dataIndex: 'd5', width: 120 },
+  { title: '6', dataIndex: 'd6', width: 120 },
+  { title: '7', dataIndex: 'd7', width: 120 },
+  { title: '8', dataIndex: 'd8', width: 120 },
+  { title: '9', dataIndex: 'd9', width: 120 },
+  { title: '10', dataIndex: 'd10', width: 120 },
+  { title: '11', dataIndex: 'd11', width: 120 },
+  { title: '12', dataIndex: 'd12', width: 120 },
+  { title: '13', dataIndex: 'd13', width: 120 },
+  { title: '14', dataIndex: 'd14', width: 120 },
+  { title: '15', dataIndex: 'd15', width: 120 },
+  { title: '16', dataIndex: 'd16', width: 120 },
+  { title: '17', dataIndex: 'd17', width: 120 },
+  { title: '18', dataIndex: 'd18', width: 120 },
+  { title: '19', dataIndex: 'd19', width: 120 },
+  { title: '20', dataIndex: 'd20', width: 120 },
+  { title: '21', dataIndex: 'd21', width: 120 },
+  { title: '22', dataIndex: 'd22', width: 120 },
+  { title: '23', dataIndex: 'd23', width: 120 },
+  { title: '24', dataIndex: 'd24', width: 120 },
+  { title: '25', dataIndex: 'd25', width: 120 },
+  { title: '26', dataIndex: 'd26', width: 120 },
+  { title: '27', dataIndex: 'd27', width: 120 },
+  { title: '28', dataIndex: 'd28', width: 120 },
+  { title: '29', dataIndex: 'd29', width: 120 },
+  { title: '30', dataIndex: 'd30', width: 120 },
+  { title: '45', dataIndex: 'd45', width: 120 },
+  { title: '60', dataIndex: 'd60', width: 120 },
+  { title: '90', dataIndex: 'd90', width: 120 },
+  { title: '120', dataIndex: 'd120', width: 120 },
+])
+
+// 页面数据初始化
+const initPage = async () => {
+  searchForm.value.reg_date[0] = dayjs().subtract(8, 'day').format('YYYY-MM-DD')
+  searchForm.value.reg_date[1] = dayjs().subtract(1, 'day').format('YYYY-MM-DD')
+  await getGameList()
+}
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh()
+}
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage()
+  refresh()
+})
+</script>

+ 161 - 0
src/views/v1/gameLog/agent/index.vue

@@ -0,0 +1,161 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table ref="crudRef" :options="options" :columns="columns" :searchForm="searchForm" @search="handleRequestData">
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="游戏" field="game_id">
+            <game-select v-model="searchForm.game_id" multiple />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="注册日期" field="reg_date">
+            <a-range-picker class="w-full" v-model="searchForm.reg_date" :show-time="false" mode="date" />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="媒体类型" field="media_id">
+            <media-select v-model="searchForm.media_id" />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="渠道ID" field="agent_id">
+            <a-input v-model="searchForm.agent_id" placeholder="请输入渠道ID" allow-clear />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="广告位ID" field="site_id">
+            <a-input v-model="searchForm.site_id" placeholder="请输入广告位ID" allow-clear />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="负责人" field="auth_id">
+            <auth-select v-model="searchForm.auth_id" />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="分组" field="group">
+            <a-select v-model="searchForm.group" placeholder="请选择分组" allow-clear>
+              <a-option value="">按渠道ID</a-option>
+              <a-option :value="1">按游戏ID</a-option>
+              <!-- <a-option :value="4">按游戏组</a-option> -->
+              <a-option :value="2">按负责人</a-option>
+              <a-option :value="3">按渠道组</a-option>
+            </a-select>
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="忽略" field="filter">
+            <a-checkbox-group v-model="searchForm.filter">
+              <a-checkbox value="igz">忽略0投入</a-checkbox>
+              <a-checkbox value="fak">忽略后台录入</a-checkbox>
+            </a-checkbox-group>
+          </a-form-item>
+        </a-col>
+      </template>
+      <template #tableSearchExtend>
+        <div>
+          大盘数据:注册成本 {{ total.reg_cost }}, roi {{ total.roi }}, 付费成本 {{ total.p_cost }}, 付费率
+          {{ total.p_per }}
+        </div>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+    </sa-table>
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from 'vue'
+import api from '../../api/gameLog/channelAnalysis'
+import dayjs from 'dayjs'
+import GameSelect from '@/components/game-select/index.vue'
+import MediaSelect from '@/components/media-select/index.vue'
+
+import AuthSelect from '@/components/auth-select/index.vue'
+
+// 引用定义
+const crudRef = ref()
+const gameList = ref([])
+
+const total = ref({
+  reg_cost: 0,
+  roi: 0,
+  p_cost: 0,
+  p_per: 0,
+})
+
+// 搜索表单
+const searchForm = ref({
+  game_id: '',
+  media_id: '',
+  auth_id: '',
+  agent_id: '',
+  site_id: '',
+  reg_date: [],
+  group: '',
+  filter: [],
+})
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getAgentDataList,
+  pk: 'id',
+  rowSelection: { showCheckedAll: true },
+  showSort: false,
+
+  operationColumn: false,
+})
+
+// SaTable 列配置
+const columns = reactive([
+  { title: 'ID', dataIndex: 'akey', width: 100, fixed: 'left' },
+  { title: '支出', dataIndex: 'cost', width: 100 },
+  { title: '激活', dataIndex: 'install', width: 100 },
+  { title: '注册设备', dataIndex: 'reg_dev', width: 100 },
+  { title: '注册数', dataIndex: 'reg_total', width: 100 },
+  { title: '注册成本', dataIndex: 'reg_cost', width: 100 },
+  { title: '创角数', dataIndex: 'role_total', width: 100 },
+  { title: '创角率', dataIndex: 'role_per', width: 100 },
+  { title: '次留数', dataIndex: 'active', width: 100 },
+  { title: '次留成本', dataIndex: 'a_cost', width: 100 },
+  { title: '次留率', dataIndex: 'a_per', width: 100 },
+  { title: '总付费人数', dataIndex: 'reg_pay_num', width: 100 },
+  { title: '总付费金额', dataIndex: 'reg_pay_total', width: 100 },
+  { title: '付费率', dataIndex: 'p_per', width: 100 },
+  { title: '当天回本率', dataIndex: 'da_per', width: 100 },
+  { title: '累计回本率', dataIndex: 're_per', width: 100 },
+  { title: '实际回本率', dataIndex: 're_amount_per', width: 100 },
+  { title: '7天实际回本率', dataIndex: 're_amount_per_7', width: 100 },
+  { title: '付费成本', dataIndex: 'p_cost', width: 100 },
+  { title: 'ARPU', dataIndex: 'arpu', width: 100 },
+  { title: '注册ARPU', dataIndex: 'r_arpu', width: 100 },
+
+  { title: '老用户数', dataIndex: 'old_login_total', width: 100 },
+
+  { title: '分组名称', dataIndex: 'name', width: 100 },
+  { title: '负责人', dataIndex: 'auth_name', width: 100 },
+])
+
+// 页面数据初始化
+const initPage = () => {
+  searchForm.value.reg_date = [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
+}
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh()
+}
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage()
+  refresh()
+})
+
+const handleRequestData = () => {
+  const res = crudRef.value.getResponseData()
+  console.log('res====>', res)
+  total.value = res.totalData
+}
+</script>

+ 3 - 2
src/views/v1/gameLog/hour/index.vue

@@ -30,7 +30,7 @@
         </a-col>
         <a-col :sm="8" :xs="24">
           <a-form-item label="负责人" field="auth_id">
-            <a-select v-model="searchForm.auth_id" :options="[]" placeholder="请选择负责人" allow-clear />
+            <auth-select v-model="searchForm.auth_id" />
           </a-form-item>
         </a-col>
       </template>
@@ -94,7 +94,8 @@ import dayjs from 'dayjs'
 import commonApi from '../../api/common'
 import GameSelect from '@/components/game-select/index.vue'
 import MediaSelect from '@/components/media-select/index.vue'
-import { Tag } from '@arco-design/web-vue'
+
+import AuthSelect from '@/components/auth-select/index.vue'
 
 // 引用定义
 const crudRef = ref()

Some files were not shown because too many files changed in this diff