Bladeren bron

分时数据

ith5 5 maanden geleden
bovenliggende
commit
132d5702e3

+ 15 - 38
src/components/game-select/index.vue

@@ -9,39 +9,36 @@
     :fieldNames="{ title: 'name', key: 'id' }"
     allow-search
     allow-clear
-    placeholder="请选择游戏"
-  />
+    placeholder="请选择游戏" />
 </template>
 
 <script setup>
-import { ref, onMounted, defineProps, defineEmits } from "vue";
-import commonApi from "../../views/v1/api/common";
+import { ref, onMounted, defineProps, defineEmits } from 'vue'
+import commonApi from '../../views/v1/api/common'
 
 const props = defineProps({
   modelValue: {
     type: [String, Number, Array],
-    default: "",
+    default: '',
   },
   multiple: {
     type: Boolean,
     default: false,
   },
-});
-
-const emit = defineEmits(["update:modelValue"]);
-
-const gameListTree = ref([]);
+})
 
+const emit = defineEmits(['update:modelValue'])
 const onUpdate = (val) => {
-  emit("update:modelValue", val);
-};
+  emit('update:modelValue', val)
+}
+const gameListTree = ref([])
 
 const fetchGameList = async () => {
   // 这里替换为你的实际API请求
   // const response = await api.getGameList()
   // gameListTree.value = response.data
-  const response = await commonApi.getGameOptionsApi();
-  gameListTree.value = response.data;
+  const response = await commonApi.getGameOptionsApi()
+  gameListTree.value = response.data
 
   if (!props.multiple) {
     gameListTree.value = response.data.map((item) => {
@@ -49,30 +46,10 @@ const fetchGameList = async () => {
         ...item,
         disabled: true,
         children: item.children || [],
-      };
-    });
+      }
+    })
   }
+}
 
-  // // 示例数据
-  // gameListTree.value = [
-  //   {
-  //     id: 1,
-  //     name: "游戏分类1",
-  //     children: [
-  //       { id: 11, name: "游戏1" },
-  //       { id: 12, name: "游戏2" },
-  //     ],
-  //   },
-  //   {
-  //     id: 2,
-  //     name: "游戏分类2",
-  //     children: [
-  //       { id: 21, name: "游戏3" },
-  //       { id: 22, name: "游戏4" },
-  //     ],
-  //   },
-  // ];
-};
-
-onMounted(fetchGameList);
+onMounted(fetchGameList)
 </script>

+ 35 - 0
src/components/media-select/index.vue

@@ -0,0 +1,35 @@
+<template>
+  <a-select :model-value="modelValue" @change="onUpdate" placeholder="请选择媒体类型" :multiple="multiple" allow-clear>
+    <a-option :maxTagCount="1" v-for="item in mediaOptions" :key="item.id" :value="item.id" :label="`${item.name}`" />
+  </a-select>
+</template>
+<script setup>
+import { ref, onMounted, defineProps, defineEmits } from 'vue'
+import advertCommonApi from '@/views/v1/api/advert/common'
+
+const props = defineProps({
+  modelValue: {
+    type: [String, Number, Array],
+    default: '',
+  },
+  multiple: {
+    type: Boolean,
+    default: false,
+  },
+})
+const mediaOptions = ref([])
+const emit = defineEmits(['update:modelValue'])
+const onUpdate = (val) => {
+  emit('update:modelValue', val)
+}
+onMounted(() => {
+  getMediaOptions()
+})
+// 获取媒体列表
+const getMediaOptions = async () => {
+  const resp = await advertCommonApi.getMediaOptionsApi()
+  if (resp.code === 200) {
+    mediaOptions.value = resp.data
+  }
+}
+</script>

+ 160 - 155
src/layout/components/ma-tags.vue

@@ -2,11 +2,22 @@
   <div class="flex justify-between tags-container" ref="containerDom" v-if="appStore.tag">
     <div class="menu-tags-wrapper" ref="scrollbarDom" :class="{ 'tag-pn': tagShowPrevNext }">
       <div class="tags" ref="tags">
-        <div v-for="tag in tagStore.tags" :key="tag.path" @contextmenu.prevent="openContextMenu($event, tag)"
+        <div
+          v-for="tag in tagStore.tags"
+          :key="tag.path"
+          @contextmenu.prevent="openContextMenu($event, tag)"
           :class="route.fullPath == tag.path ? 'active' : ''"
           @click="tagJump(tag)">
           <span>
-            {{ tag.customTitle ? tag.customTitle : appStore.i18n ? ($t('menus.' + tag.name).indexOf('.') > 0 ? tag.title : $t('menus.' + tag.name)) : tag.title }}
+            {{
+              tag.customTitle
+                ? tag.customTitle
+                : appStore.i18n
+                ? $t('menus.' + tag.name).indexOf('.') > 0
+                  ? tag.title
+                  : $t('menus.' + tag.name)
+                : tag.title
+            }}
           </span>
           <icon-close class="tag-icon" v-if="!tag.affix" @click.stop="closeTag(tag)" />
         </div>
@@ -29,6 +40,7 @@
         <ul class="ma-tags-more-contextmenu">
           <li @click="tagToolRefreshTag">
             <icon-refresh />
+
             {{ $t('sys.tags.refresh') }}
           </li>
           <a-divider class="dropdown-divider" />
@@ -78,7 +90,7 @@ import { ref, watch, onMounted, nextTick } from 'vue'
 import { useAppStore, useTagStore } from '@/store'
 import { useRoute, useRouter } from 'vue-router'
 import { addTag, closeTag, refreshTag } from '@/utils/common'
-import Sortable from "sortablejs"
+import Sortable from 'sortablejs'
 import { Message } from '@arco-design/web-vue'
 import { IconFaceFrownFill } from '@arco-design/web-vue/dist/arco-vue-icon'
 import tool from '@/utils/tool'
@@ -93,12 +105,12 @@ const contextMenuVisible = ref(false)
 const contextMenuItem = ref(null)
 const left = ref(0)
 const top = ref(0)
-const notAddTagList = [ 'login' ]
+const notAddTagList = ['login']
 watch(
   () => appStore.tag,
-  r => {
+  (r) => {
     nextTick(() => {
-      if ( (tags.value.scrollWidth ?? false) && tags.value.offsetWidth ) {
+      if ((tags.value.scrollWidth ?? false) && tags.value.offsetWidth) {
         tagShowPrevNext.value = tags.value.scrollWidth > tags.value.offsetWidth
       }
     })
@@ -107,9 +119,9 @@ watch(
 )
 watch(
   () => tagStore.tags,
-  r => {
+  (r) => {
     nextTick(() => {
-      if ( (tags.value.scrollWidth ?? false) && tags.value.offsetWidth ) {
+      if ((tags.value.scrollWidth ?? false) && tags.value.offsetWidth) {
         tagShowPrevNext.value = tags.value.scrollWidth > tags.value.offsetWidth
       }
     })
@@ -118,43 +130,40 @@ watch(
 )
 watch(
   () => route,
-  r => {
+  (r) => {
     if (!notAddTagList.includes(r.name)) {
       addTag({
         name: r.name,
         path: r.fullPath,
         affix: r.meta.affix,
-        title: r.meta.title
+        title: r.meta.title,
       })
     }
 
     nextTick(() => {
-      if ( tags.value && tags.value.scrollWidth > tags.value.clientWidth ) {
+      if (tags.value && tags.value.scrollWidth > tags.value.clientWidth) {
         //确保当前标签在可视范围内
         tags.value.querySelector('.active').scrollIntoView()
       }
     })
-  }, { deep: true }
+  },
+  { deep: true }
 )
 
-watch(
-  contextMenuVisible,
-  value => {
-
-    const handler = (e) => {
-      const dom = document.querySelector('.tags-contextmenu')
-      if (dom && !dom.contains(e.target)) {
-        closeContextMenu()
-      }
+watch(contextMenuVisible, (value) => {
+  const handler = (e) => {
+    const dom = document.querySelector('.tags-contextmenu')
+    if (dom && !dom.contains(e.target)) {
+      closeContextMenu()
     }
-
-    value
-      ? document.body.addEventListener("click", e => handler(e))
-      : document.body.removeEventListener("click", e => handler(e))
   }
-)
 
-const tagJump = tag => {
+  value
+    ? document.body.addEventListener('click', (e) => handler(e))
+    : document.body.removeEventListener('click', (e) => handler(e))
+})
+
+const tagJump = (tag) => {
   router.push({ path: tag.path, query: tool.getRequestParams(tag.path) })
 }
 
@@ -167,8 +176,8 @@ const openContextMenu = (e, tag) => {
   nextTick(() => {
     const dom = document.querySelector('.tags-contextmenu')
     if (document.body.offsetWidth - e.clientX < dom.offsetWidth) {
-      left.value = document.body.offsetWidth - dom.offsetWidth + 1;
-      top.value = e.clientY + 1;
+      left.value = document.body.offsetWidth - dom.offsetWidth + 1
+      top.value = e.clientY + 1
     }
   })
 }
@@ -201,7 +210,7 @@ const tagToolRefreshTag = () => {
 }
 const tagToolCloseCurrentTag = () => {
   const list = [...tagStore.tags]
-  list.forEach(tag => {
+  list.forEach((tag) => {
     if (tag.affix || route.path == tag.path) {
       closeTag(tag)
     }
@@ -262,7 +271,7 @@ const contextMenuCloseLeftTag = () => {
 
 const tagToolCloseOtherTag = () => {
   const list = [...tagStore.tags]
-  list.forEach(tag => {
+  list.forEach((tag) => {
     if (tag.affix || route.path == tag.path) {
       return true
     } else {
@@ -277,7 +286,7 @@ const contextMenuCloseOtherTag = () => {
     router.push({ path: currentTag.path })
   }
   const list = [...tagStore.tags]
-  list.forEach(tag => {
+  list.forEach((tag) => {
     if (tag.affix || currentTag.path == tag.path) {
       return true
     } else {
@@ -287,26 +296,25 @@ const contextMenuCloseOtherTag = () => {
   contextMenuVisible.value = false
 }
 
-const scrollHandler = event => {
-  const detail = event.wheelDelta || event.detail;
-  const moveForwardStep = 1;
-  const moveBackStep = -1;
-  let step = 0;
+const scrollHandler = (event) => {
+  const detail = event.wheelDelta || event.detail
+  const moveForwardStep = 1
+  const moveBackStep = -1
+  let step = 0
   if (detail == 3 || (detail < 0 && detail != -3)) {
-    step = moveForwardStep * 50;
+    step = moveForwardStep * 50
   } else {
-    step = moveBackStep * 50;
+    step = moveBackStep * 50
   }
-  tags.value.scrollLeft += step;
+  tags.value.scrollLeft += step
 }
 const handleScroll = (offset) => {
   const distance = tags.value.scrollLeft
   const total = distance + offset
   const step = offset / 50
   moveSlow(distance, total, step)
-};
+}
 const moveSlow = (distance, total, step) => {
-
   if (step > 0) {
     //往左滚
     if (distance < total) {
@@ -316,7 +324,7 @@ const moveSlow = (distance, total, step) => {
         moveSlow(distance, total, step)
       })
     } else {
-      tags.value.scrollLeft = total;
+      tags.value.scrollLeft = total
     }
   } else {
     //往右滚
@@ -327,15 +335,15 @@ const moveSlow = (distance, total, step) => {
         moveSlow(distance, total, step)
       })
     } else {
-      tags.value.scrollLeft = total;
+      tags.value.scrollLeft = total
     }
   }
 }
 onMounted(() => {
   if (tags.value) {
     Sortable.create(tags.value, { draggable: 'a', animation: 300 })
-    tags.value.addEventListener("mousewheel", scrollHandler, { passive: true }) ||
-      tags.value.addEventListener("DOMMouseScroll", scrollHandler, { passive: true })
+    tags.value.addEventListener('mousewheel', scrollHandler, { passive: true }) ||
+      tags.value.addEventListener('DOMMouseScroll', scrollHandler, { passive: true })
     nextTick(() => {
       tagShowPrevNext.value = tags.value.scrollWidth > tags.value.offsetWidth
     })
@@ -344,135 +352,132 @@ onMounted(() => {
 </script>
 
 <style scoped lang="less">
-  .tag-pn {
-    padding: 0 15px;
-    margin: 0 5px;
-  }
-
-  .menu-tags-wrapper {
-
-    box-sizing: border-box;
-    overflow: hidden;
-    position: relative;
-    display: inline-flex;
+.tag-pn {
+  padding: 0 15px;
+  margin: 0 5px;
+}
 
-    .ma-tag-next,
-    .ma-tag-prev {
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      position: absolute;
-      height: 40px;
+.menu-tags-wrapper {
+  box-sizing: border-box;
+  overflow: hidden;
+  position: relative;
+  display: inline-flex;
 
-      .tag-scroll-icon {
-        cursor: pointer;
-        color: var(--color-text-3);
-        ;
-      }
-
-      .tag-scroll-icon:hover {
-        color: rgb(var(--primary-6));
-      }
-    }
+  .ma-tag-next,
+  .ma-tag-prev {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    position: absolute;
+    height: 40px;
 
-    .ma-tag-prev {
-      left: -4px;
+    .tag-scroll-icon {
+      cursor: pointer;
+      color: var(--color-text-3);
     }
 
-    .ma-tag-next {
-      right: -4px;
+    .tag-scroll-icon:hover {
+      color: rgb(var(--primary-6));
     }
-
   }
 
-  .ma-tags-more {
-    position: relative;
-    box-sizing: border-box;
-    display: flex;
-    text-align: left;
-    justify-content: center;
-    align-items: center;
-    margin-right: 15px;
-    margin-left: 5px;
-    top: -1px;
-
-    .ma-tags-more-icon {
-      display: inline-block;
-      color: var(--color-text-2);
-      cursor: pointer;
-      transition: transform .3s ease-out;
+  .ma-tag-prev {
+    left: -4px;
+  }
 
-      .ma-box {
-        position: relative;
-        display: block;
-        width: 14px;
-        height: 8px;
+  .ma-tag-next {
+    right: -4px;
+  }
+}
 
-        .ma-box-t:before {
-          transition: transform .3s ease-out .3s;
-        }
+.ma-tags-more {
+  position: relative;
+  box-sizing: border-box;
+  display: flex;
+  text-align: left;
+  justify-content: center;
+  align-items: center;
+  margin-right: 15px;
+  margin-left: 5px;
+  top: -1px;
+
+  .ma-tags-more-icon {
+    display: inline-block;
+    color: var(--color-text-2);
+    cursor: pointer;
+    transition: transform 0.3s ease-out;
+
+    .ma-box {
+      position: relative;
+      display: block;
+      width: 14px;
+      height: 8px;
+
+      .ma-box-t:before {
+        transition: transform 0.3s ease-out 0.3s;
       }
+    }
 
-      .ma-box:before {
-        position: absolute;
-        top: 2px;
-        left: 0;
-        width: 6px;
-        height: 6px;
-        content: "";
-        background: var(--color-text-3);
-      }
+    .ma-box:before {
+      position: absolute;
+      top: 2px;
+      left: 0;
+      width: 6px;
+      height: 6px;
+      content: '';
+      background: var(--color-text-3);
+    }
 
-      .ma-box:after {
-        position: absolute;
-        top: 2px;
-        left: 8px;
-        width: 6px;
-        height: 6px;
-        content: "";
-        background: var(--color-text-3);
-      }
+    .ma-box:after {
+      position: absolute;
+      top: 2px;
+      left: 8px;
+      width: 6px;
+      height: 6px;
+      content: '';
+      background: var(--color-text-3);
     }
   }
+}
 
-  .ma-tags-more:hover .ma-tags-more-icon .ma-box:before {
-    background: rgb(var(--primary-6));
-    transform: rotate(45deg);
-  }
+.ma-tags-more:hover .ma-tags-more-icon .ma-box:before {
+  background: rgb(var(--primary-6));
+  transform: rotate(45deg);
+}
 
-  .ma-tags-more:hover .ma-tags-more-icon .ma-box:after {
-    background: rgb(var(--primary-6));
-  }
+.ma-tags-more:hover .ma-tags-more-icon .ma-box:after {
+  background: rgb(var(--primary-6));
+}
 
-  .ma-tags-more:hover .ma-tags-more-icon {
-    transform: rotate(90deg);
-  }
+.ma-tags-more:hover .ma-tags-more-icon {
+  transform: rotate(90deg);
+}
 
-  .dropdown-divider {
-    margin: 0;
-  }
+.dropdown-divider {
+  margin: 0;
+}
 
-  .ma-tags-more-contextmenu {
-    border: 1px solid var(--color-border-2);
-    padding: 5px 0;
-    z-index: 100;
-    width: 170px;
-    background-color: var(--color-bg-5);
-    border-radius: 4px;
-
-    li {
-      padding: 7px 15px;
-      color: var(--color-text-2);
-      font-size: 13px;
-    }
+.ma-tags-more-contextmenu {
+  border: 1px solid var(--color-border-2);
+  padding: 5px 0;
+  z-index: 100;
+  width: 170px;
+  background-color: var(--color-bg-5);
+  border-radius: 4px;
+
+  li {
+    padding: 7px 15px;
+    color: var(--color-text-2);
+    font-size: 13px;
+  }
 
-    li:hover {
-      background-color: rgb(var(--primary-1));
-      cursor: pointer;
-    }
+  li:hover {
+    background-color: rgb(var(--primary-1));
+    cursor: pointer;
+  }
 
-    .arco-divider-horizontal {
-      margin: 5px 0;
-    }
+  .arco-divider-horizontal {
+    margin: 5px 0;
   }
-</style>
+}
+</style>

+ 1 - 0
src/utils/common.js

@@ -11,6 +11,7 @@ import tool from '@/utils/tool'
 
 export const refreshTag = () => {
   const route = router.currentRoute.value
+  console.log('route', route)
   const keepStore = useKeepAliveStore()
   NProgress.start()
   keepStore.removeKeepAlive(route)

+ 26 - 26
src/views/v1/api/customer/sdkOrder.js

@@ -1,4 +1,4 @@
-import { request } from "@/utils/request.js";
+import { request } from '@/utils/request.js'
 
 /**
  * 用户订单记录 API接口
@@ -10,10 +10,10 @@ export default {
    */
   getPageList(params = {}) {
     return request({
-      url: "/v1/customer/SdkOrder/index",
-      method: "get",
-      params,
-    });
+      url: '/v1/customer/SdkOrder/index',
+      method: 'get',
+      params
+    })
   },
 
   /**
@@ -22,10 +22,10 @@ export default {
    */
   save(params = {}) {
     return request({
-      url: "/v1/customer/SdkOrder/save",
-      method: "post",
-      data: params,
-    });
+      url: '/v1/customer/SdkOrder/save',
+      method: 'post',
+      data: params
+    })
   },
 
   /**
@@ -34,10 +34,10 @@ export default {
    */
   update(id, data = {}) {
     return request({
-      url: "/v1/customer/SdkOrder/update?id=" + id,
-      method: "put",
-      data,
-    });
+      url: '/v1/customer/SdkOrder/update?id=' + id,
+      method: 'put',
+      data
+    })
   },
 
   /**
@@ -46,9 +46,9 @@ export default {
    */
   read(id) {
     return request({
-      url: "/v1/customer/SdkOrder/read?id=" + id,
-      method: "get",
-    });
+      url: '/v1/customer/SdkOrder/read?id=' + id,
+      method: 'get'
+    })
   },
 
   /**
@@ -57,20 +57,20 @@ export default {
    */
   destroy(data) {
     return request({
-      url: "/v1/customer/SdkOrder/destroy",
-      method: "delete",
-      data,
-    });
+      url: '/v1/customer/SdkOrder/destroy',
+      method: 'delete',
+      data
+    })
   },
 
   /**
    * 补发
    * @returns
    */
-  send(orderid) {
+  send(order_id) {
     return request({
-      url: "/v1/customer/SdkOrder/send?orderid=" + orderid,
-      method: "post",
-    });
-  },
-};
+      url: '/v1/customer/SdkOrder/send?order_id=' + order_id,
+      method: 'post'
+    })
+  }
+}

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

@@ -0,0 +1,18 @@
+import { request } from '@/utils/request.js'
+
+/**
+ * 渠道分析 API接口
+ */
+export default {
+  /**
+   * 数据列表
+   * @returns
+   */
+  getHourList(params = {}) {
+    return request({
+      url: '/v1/gameLog/channelAnalysis/getHourDataList',
+      method: 'get',
+      params
+    })
+  }
+}

+ 1 - 2
src/views/v1/center/gamePayChannel/index.vue

@@ -10,7 +10,7 @@
         </a-col>
       </template>
 
-      <template #game_id="{ record }"> {{ record.game_id }}:{{ record.game_name }} </template>
+      <template #game_id="{ record }"> [{{ record.game_id }}]:{{ record.game_name }} </template>
 
       <!-- Table 自定义渲染 -->
     </sa-table>
@@ -22,7 +22,6 @@
 
 <script setup>
 import { onMounted, ref, reactive } from 'vue'
-import { Message } from '@arco-design/web-vue'
 import EditForm from './edit.vue'
 import api from '../../api/center/gamePayChannel'
 import GameSelect from '@/components/game-select/index.vue'

+ 0 - 2
src/views/v1/customer/reconciliation/payChannelIncome/index.vue

@@ -82,8 +82,6 @@ import GameSelect from '@/components/game-select/index.vue'
 
 // 引用定义
 const crudRef = ref()
-const editRef = ref()
-const viewRef = ref()
 const data = ref([])
 const allGameOptions = ref([])
 const payChannelOptions = ref([])

+ 3 - 4
src/views/v1/customer/sdkOrder/edit.vue

@@ -9,8 +9,7 @@
     @cancel="close"
     @before-ok="submit">
     <!-- 表单信息 start -->
-    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true">
-    </a-form>
+    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true"> </a-form>
     <!-- 表单信息 end -->
   </component>
 </template>
@@ -42,8 +41,8 @@ const formData = reactive({ ...initialFormData })
 
 // 验证规则
 const rules = {
-  orderid: [{ required: true, message: '订单号必需填写' }],
-  cp_orderid: [{ required: true, message: '研发订单号必需填写' }],
+  order_id: [{ required: true, message: '订单号必需填写' }],
+  cp_order_id: [{ required: true, message: '研发订单号必需填写' }],
   pay_channel: [{ required: true, message: '充值方式必需填写' }],
   money: [{ required: true, message: '金额必需填写' }],
   paid_amount: [{ required: true, message: '净额必需填写' }],

+ 10 - 10
src/views/v1/customer/sdkOrder/index.vue

@@ -49,13 +49,13 @@
           </a-form-item>
         </a-col>
         <a-col :sm="8" :xs="24">
-          <a-form-item label="订单号" field="orderid">
-            <a-input v-model="searchForm.orderid" placeholder="请输入订单号" allow-clear />
+          <a-form-item label="订单号" field="order_id">
+            <a-input v-model="searchForm.order_id" placeholder="请输入订单号" allow-clear />
           </a-form-item>
         </a-col>
         <a-col :sm="8" :xs="24">
-          <a-form-item label="交易订单号" field="tradeid">
-            <a-input v-model="searchForm.tradeid" placeholder="请输入交易订单号" allow-clear />
+          <a-form-item label="交易订单号" field="trade_id">
+            <a-input v-model="searchForm.trade_id" placeholder="请输入交易订单号" allow-clear />
           </a-form-item>
         </a-col>
       </template>
@@ -104,8 +104,8 @@ const allGameOptions = ref([])
 
 // 搜索表单
 const searchForm = ref({
-  orderid: '',
-  tradeid: '',
+  order_id: '',
+  trade_id: '',
   game_id: '',
   user_name: '',
   role_id: '',
@@ -158,9 +158,9 @@ const options = reactive({
 const columns = reactive([
   { title: '充值账号', dataIndex: 'user_name', width: 180 },
   { title: '充值IP', dataIndex: 'user_ip', width: 180 },
-  { title: '订单号', dataIndex: 'orderid', width: 180 },
-  { title: '交易订单号', dataIndex: 'tradeid', width: 180 },
-  { title: '研发订单号', dataIndex: 'cp_orderid', width: 180 },
+  { title: '订单号', dataIndex: 'order_id', width: 180 },
+  { title: '交易订单号', dataIndex: 'trade_id', width: 180 },
+  { title: '研发订单号', dataIndex: 'cp_order_id', width: 180 },
   { title: '支付时间', dataIndex: 'pay_date', width: 180 },
   {
     title: '金额',
@@ -209,7 +209,7 @@ const handleSend = async (record) => {
     okText: '确定',
     cancelText: '取消',
     onOk: async () => {
-      const resp = await api.send(record.orderid)
+      const resp = await api.send(record.order_id)
       if (resp.code === 200) {
         Message.success(`操作成功,请稍后刷新`)
         crudRef.value?.refresh()

+ 175 - 0
src/views/v1/gameLog/hour/index.vue

@@ -0,0 +1,175 @@
+<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">
+            <a-select v-model="searchForm.auth_id" :options="[]" placeholder="请选择负责人" allow-clear />
+          </a-form-item>
+        </a-col>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+      <template #agent_name="{ record }">
+        <div v-if="!record.agent_name">
+          <div style="color: purple">消耗</div>
+          <div>注册</div>
+          <div style="color: blue">注册成本</div>
+          <div style="color: green">付费率</div>
+          <div style="color: red">回本率</div>
+        </div>
+      </template>
+      <template #total_raw="{ record }">
+        <div>
+          <div style="color: purple">
+            {{ record.total_raw?.cost }}
+          </div>
+          <div>
+            {{ record.total_raw?.reg_total }}
+          </div>
+          <div style="color: blue">
+            {{ record.total_raw?.reg_cost }}
+          </div>
+          <div style="color: green">
+            {{ record.total_raw?.pay_rate }}
+          </div>
+          <div style="color: red">
+            {{ record.total_raw?.roi }}
+          </div>
+        </div>
+      </template>
+      <template v-for="i in 23" :key="i" #[`h${i}`]="{ record }">
+        <div>
+          <div style="color: purple">
+            {{ record[`h${i}`]?.cost }}
+          </div>
+          <div>
+            {{ record[`h${i}`]?.reg_total }}
+          </div>
+          <div style="color: blue">
+            {{ record[`h${i}`]?.reg_cost }}
+          </div>
+          <div style="color: green">
+            {{ record[`h${i}`]?.pay_rate }}
+          </div>
+          <div style="color: red">
+            {{ record[`h${i}`]?.roi }}
+          </div>
+        </div>
+      </template>
+    </sa-table>
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from 'vue'
+import api from '../../api/gameLog/channelAnalysis'
+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'
+
+// 引用定义
+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.getHourList,
+  pk: 'id',
+  rowSelection: { showCheckedAll: true },
+
+  operationColumn: false,
+})
+
+// SaTable 列配置
+const columns = reactive([
+  { title: '渠道ID', dataIndex: 'agent_id', width: 120 },
+  { title: '渠道名', dataIndex: 'agent_name', width: 120 },
+  { title: '合计', dataIndex: 'total_raw', width: 120 },
+  { title: 'h1', dataIndex: 'h1', width: 120 },
+  { title: 'h2', dataIndex: 'h2', width: 120 },
+  { title: 'h3', dataIndex: 'h3', width: 120 },
+  { title: 'h4', dataIndex: 'h4', width: 120 },
+  { title: 'h5', dataIndex: 'h5', width: 120 },
+  { title: 'h6', dataIndex: 'h6', width: 120 },
+  { title: 'h7', dataIndex: 'h7', width: 120 },
+  { title: 'h8', dataIndex: 'h8', width: 120 },
+  { title: 'h9', dataIndex: 'h9', width: 120 },
+  { title: 'h10', dataIndex: 'h10', width: 120 },
+  { title: 'h11', dataIndex: 'h11', width: 120 },
+  { title: 'h12', dataIndex: 'h12', width: 120 },
+  { title: 'h13', dataIndex: 'h13', width: 120 },
+  { title: 'h14', dataIndex: 'h14', width: 120 },
+  { title: 'h15', dataIndex: 'h15', width: 120 },
+  { title: 'h16', dataIndex: 'h16', width: 120 },
+  { title: 'h17', dataIndex: 'h17', width: 120 },
+  { title: 'h18', dataIndex: 'h18', width: 120 },
+  { title: 'h19', dataIndex: 'h19', width: 120 },
+  { title: 'h20', dataIndex: 'h20', width: 120 },
+  { title: 'h21', dataIndex: 'h21', width: 120 },
+  { title: 'h22', dataIndex: 'h22', width: 120 },
+  { title: 'h23', dataIndex: 'h23', width: 120 },
+])
+
+// 页面数据初始化
+const initPage = async () => {
+  searchForm.value.reg_date = [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
+  await getGameList()
+}
+
+// 获取游戏列表
+const getGameList = async () => {
+  const res = await commonApi.getGameListTreeApi()
+  if (res.code === 200) {
+    gameList.value = res.data
+  }
+}
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh()
+}
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage()
+  refresh()
+})
+</script>

+ 5 - 7
src/views/v1/gameLog/sdkOrderRank/edit.vue

@@ -9,8 +9,7 @@
     @cancel="close"
     @before-ok="submit">
     <!-- 表单信息 start -->
-    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true">
-    </a-form>
+    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true"> </a-form>
     <!-- 表单信息 end -->
   </component>
 </template>
@@ -34,15 +33,14 @@ let title = computed(() => {
 
 // 表单初始值
 const initialFormData = {
-  orderid: null,
+  order_id: null,
 }
 
 // 表单信息
 const formData = reactive({ ...initialFormData })
 
 // 验证规则
-const rules = {
-}
+const rules = {}
 
 // 打开弹框
 const open = async (type = 'add') => {
@@ -75,11 +73,11 @@ const submit = async (done) => {
     let result = {}
     if (mode.value === 'add') {
       // 添加数据
-      data.orderid = undefined
+      data.order_id = undefined
       result = await api.save(data)
     } else {
       // 修改数据
-      result = await api.update(data.orderid, data)
+      result = await api.update(data.order_id, data)
     }
     if (result.code === 200) {
       Message.success('操作成功')

+ 1 - 1
src/views/v1/gameLog/sdkOrderRank/index.vue

@@ -123,7 +123,7 @@ const searchForm = ref({
 // SaTable 基础配置
 const options = reactive({
   api: api.getPageList,
-  pk: 'orderid',
+  pk: 'order_id',
   rowSelection: { showCheckedAll: true },
   operationColumn: false,
 })

+ 5 - 7
src/views/v1/gameLog/sdkOrderSuccess/edit.vue

@@ -9,8 +9,7 @@
     @cancel="close"
     @before-ok="submit">
     <!-- 表单信息 start -->
-    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true">
-    </a-form>
+    <a-form ref="formRef" :model="formData" :rules="rules" :auto-label-width="true"> </a-form>
     <!-- 表单信息 end -->
   </component>
 </template>
@@ -34,15 +33,14 @@ let title = computed(() => {
 
 // 表单初始值
 const initialFormData = {
-  orderid: null,
+  order_id: null,
 }
 
 // 表单信息
 const formData = reactive({ ...initialFormData })
 
 // 验证规则
-const rules = {
-}
+const rules = {}
 
 // 打开弹框
 const open = async (type = 'add') => {
@@ -75,11 +73,11 @@ const submit = async (done) => {
     let result = {}
     if (mode.value === 'add') {
       // 添加数据
-      data.orderid = undefined
+      data.order_id = undefined
       result = await api.save(data)
     } else {
       // 修改数据
-      result = await api.update(data.orderid, data)
+      result = await api.update(data.order_id, data)
     }
     if (result.code === 200) {
       Message.success('操作成功')

+ 2 - 13
src/views/v1/gameLog/sdkOrderSuccess/index.vue

@@ -5,17 +5,6 @@
       <template #tableSearch>
         <a-col :sm="8" :xs="24">
           <a-form-item label="游戏" field="game_id">
-            <!-- <a-tree-select
-              v-model="searchForm.game_id"
-              :data="gameList"
-              placeholder="请选择游戏"
-              allow-clear
-              :field-names="{ title: 'name', key: 'id' }"
-              allow-search
-              tree-checked-strategy="child"
-              :tree-checkable="true"
-              :max-tag-count="1"
-            /> -->
             <game-select v-model="searchForm.game_id" multiple />
           </a-form-item>
         </a-col>
@@ -111,7 +100,7 @@ const searchForm = ref({
 // SaTable 基础配置
 const options = reactive({
   api: api.getPageList,
-  pk: 'orderid',
+  pk: 'order_id',
   rowSelection: { showCheckedAll: true },
   export: {
     // // 导出url
@@ -129,7 +118,7 @@ const options = reactive({
 
 // SaTable 列配置
 const columns = reactive([
-  { title: '订单号', dataIndex: 'orderid', width: 180 },
+  { title: '订单号', dataIndex: 'order_id', width: 180 },
   { title: '用户名', dataIndex: 'user_name', width: 120 },
   { title: '渠道ID', dataIndex: 'agent_id', width: 120 },
   { title: '广告位ID', dataIndex: 'site_id', width: 120 },