Browse Source

Merge branch 'wang' into test

# Conflicts:
#	src/views/adManage/sp/campaigns/crud.tsx
#	src/views/adManage/sp/campaigns/index.vue
WanGxC 1 năm trước cách đây
mục cha
commit
8a2881a10d

+ 3 - 3
src/views/adManage/sp/advertisedProducts/crud.tsx

@@ -7,9 +7,9 @@ import {dynBidStrategyEnum} from '/@/views/adManage/utils/enum.js'
 
 export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
     const pageRequest = async (query: UserPageQuery) => {
-        query['profile'] = context['profileId']
-        query['start'] = context['start']
-        query['end'] = context['end']
+        query['profileId'] = context['profileId']
+        query['startDate'] = context['start']
+        query['endDate'] = context['end']
         return await api.GetList(query)
     }
     const editRequest = async ({form, row}: EditReq) => {

+ 3 - 2
src/views/adManage/sp/advertisedProducts/index.vue

@@ -4,7 +4,7 @@
             <template #header-middle>
                 <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
                     <el-tab-pane label="数据趋势" name="dataTendency">
-                        <DataTendencyChart ref="dataTendencyRef"/>
+                        <DataTendencyChart v-if="tabActiveName === 'dataTendency'" :fetchCard="getCardData" :fetchLine="getLineData"></DataTendencyChart>
                     </el-tab-pane>
                     <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
                 </el-tabs>
@@ -18,8 +18,9 @@ import {ref, onMounted, nextTick, inject} from 'vue'
 import {useFs, FsPage} from '@fast-crud/fast-crud'
 import {createCrudOptions} from './crud'
 import {useRoute, useRouter} from 'vue-router'
-import DataTendencyChart from './chartComponents/dataTendency.vue'
+import DataTendencyChart from '/@/views/adManage/sp/chartComponents/dataTendency.vue'
 import {useShopInfo} from '/@/stores/shopInfo'
+import {getCardData, getLineData} from '/@/views/adManage/sp/campaigns/api'
 
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()

+ 8 - 2
src/views/adManage/sp/keywords/chartComponents/adStruct.vue

@@ -22,15 +22,21 @@ import { getAdStructureData } from "/@/views/adManage/sp/keywords/api"
 import { createDisabledOptions } from '../../../utils/dropdowndisable'
 import { barOptionsMap } from "/@/views/adManage/utils/enum"
 import { useShopInfo } from '/@/stores/shopInfo'
+import { usePublicData } from "/@/stores/publicData"
+import {storeToRefs} from 'pinia'
+
 
 
 const shopInfo = useShopInfo()
+const publicData = usePublicData()
+const {dateRange} = storeToRefs(publicData)
+const {profile} = storeToRefs(shopInfo)
 let barChart = ref()
 const pie = ref()
 const bar = ref()
 const loading = ref(true)
 
-const dateRange = inject('dateRange')
+// const dateRange = inject('dateRange')
 
 // 下拉框相关
 const barOptions1 = [
@@ -211,7 +217,7 @@ onMounted(async () => {
 let allData = null
 
 async function setAdStructureData() {
-    allData = await getAdStructureData({ start: dateRange.value[0], end: dateRange.value[1], profile: shopInfo.profile.profile_id })
+    allData = await getAdStructureData({ startDate: dateRange.value[0], endDate: dateRange.value[1], profileId: shopInfo.profile.profile_id })
     return allData.data
 }
 

+ 3 - 3
src/views/adManage/sp/keywords/crud.tsx

@@ -7,9 +7,9 @@ import {dynBidStrategyEnum} from '/@/views/adManage/utils/enum.js'
 
 export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
     const pageRequest = async (query: UserPageQuery) => {
-        query['profile'] = context['profileId']
-        query['start'] = context['start']
-        query['end'] = context['end']
+        query['profileId'] = context.profile.value.profile_id
+        query['startDate'] = context.dateRange.value[0]
+        query['endDate'] = context.dateRange.value[1]
         return await api.GetList(query)
     }
     const editRequest = async ({form, row}: EditReq) => {

+ 33 - 30
src/views/adManage/sp/keywords/index.vue

@@ -1,48 +1,51 @@
 <template>
-	<fs-page class="fs-page-custom">
-		<fs-crud ref="crudRef" v-bind="crudBinding">
-			<template #header-middle>
-				<el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card">
-					<el-tab-pane label="数据趋势" name="dataTendency">
-						<DataTendencyChart v-if="tabActiveName === 'dataTendency'" :fetch-card="getCardData" :fetch-line="getLineData" />
-					</el-tab-pane>
-					<el-tab-pane label="广告结构" name="adStruct">
-						<AdStructChart v-if="tabActiveName === 'adStruct'" />
-					</el-tab-pane>
-					<el-tab-pane label="散点视图" name="scatterView"></el-tab-pane>
-				</el-tabs>
-			</template>
-		</fs-crud>
-	</fs-page>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <template #header-middle>
+        <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card">
+          <el-tab-pane label="数据趋势" name="dataTendency">
+            <DataTendencyChart v-if="tabActiveName === 'dataTendency'" :fetchCard="getCardData" :fetchLine="getLineData"></DataTendencyChart>
+          </el-tab-pane>
+          <el-tab-pane label="广告结构" name="adStruct">
+            <AdStructChart v-if="tabActiveName === 'adStruct'"/>
+          </el-tab-pane>
+          <el-tab-pane label="散点视图" name="scatterView"></el-tab-pane>
+        </el-tabs>
+      </template>
+    </fs-crud>
+  </fs-page>
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted, inject } from 'vue'
-import { useFs, FsPage } from '@fast-crud/fast-crud'
-import { createCrudOptions } from './crud'
+import {ref, onMounted, inject} from 'vue'
+import {useFs, FsPage} from '@fast-crud/fast-crud'
+import {createCrudOptions} from './crud'
 import DataTendencyChart from '/@/views/adManage/sp/chartComponents/dataTendency.vue'
-import { useShopInfo } from '/@/stores/shopInfo'
+import {useShopInfo} from '/@/stores/shopInfo'
 import AdStructChart from './chartComponents/adStruct.vue'
-import { getCardData, getLineData } from './api'
+import {getCardData, getLineData} from './api'
+import {usePublicData} from '/@/stores/publicData'
+import {storeToRefs} from 'pinia'
+
 
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()
-const dateRange = inject('dateRange')
-const start = dateRange.value[0]
-const end = dateRange.value[1]
-const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {profileId: shopInfo.profile.profile_id, start: start, end: end}})
+const publicData = usePublicData()
+const {dateRange} = storeToRefs(publicData)
+const {profile} = storeToRefs(shopInfo)
+const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {profile, dateRange}})
 
-onMounted(() => {
-	crudExpose.doRefresh()
+onMounted(async () => {
+  crudExpose.doRefresh()
 })
 </script>
 
 <style lang="scss">
 .chart-tabs {
-	margin: 5px 0;
+  margin: 5px 0;
 
-	.el-tabs__nav {
-		padding-left: 0 !important;
-	}
+  .el-tabs__nav {
+    padding-left: 0 !important;
+  }
 }
 </style>

+ 3 - 3
src/views/adManage/sp/placement/api.ts

@@ -1,7 +1,7 @@
 import {request} from '/@/utils/service'
 import {AddReq, DelReq, EditReq, UserPageQuery} from '@fast-crud/fast-crud'
 
-export const apiPrefix = '/api/ad_manage/sptargets/';
+export const apiPrefix = '/api/ad_manage/spplacement/';
 export function GetList(query: UserPageQuery) {
     return request({
         url: apiPrefix,
@@ -42,7 +42,7 @@ export function DelObj(id: DelReq) {
 
 export function getCardData(query: UserPageQuery) {
     return request({
-        url: apiPrefix + "total/",
+        url: "/api/ad_manage/spcampaigns/total/",
         method: 'GET',
         params: query
     })
@@ -50,7 +50,7 @@ export function getCardData(query: UserPageQuery) {
 
 export function getLineData(query: UserPageQuery) {
     return request({
-        url: apiPrefix + "daily/",
+        url: "/api/ad_manage/spcampaigns/daily/",
         method: 'GET',
         params: query
     })

+ 309 - 302
src/views/adManage/sp/placement/chartComponents/adStruct.vue

@@ -1,218 +1,221 @@
 <template>
-    <div v-loading="loading">
-        <el-row :gutter="5">
-            <el-col :span="24">
-                <div style="margin-left: 45%">
-                    <span style="background: #3a83f7; width: 18px; height: 10px; margin-top: 8px; display: inline-block; border-radius: 3px;"></span>
-                    <TextSelector v-model="barModelValue1" :options="computedBarOptions1" @change="changeBarOne" style="margin-top: 5px; margin-left: 8px;"/>
-                    <span style="background: #f19a37; width: 18px; height: 10px; margin-top: 8px; margin-left: 20px; display: inline-block; border-radius: 3px;"></span>
-                    <TextSelector v-model="barModelValue2" :options="computedBarOptions2" @change="changeBarTwo" style="margin-top: 5px; margin-left: 8px;"/>
-                </div>
-                <div ref="bar" style="height: 400px;"></div>
-            </el-col>
-        </el-row>
-    </div>
+  <div v-loading="loading">
+    <el-row :gutter="5">
+      <el-col :span="24">
+        <div style="margin-left: 45%">
+          <span style="background: #3a83f7; width: 18px; height: 10px; margin-top: 8px; display: inline-block; border-radius: 3px;"></span>
+          <TextSelector v-model="barModelValue1" :options="computedBarOptions1" @change="changeBarOne" style="margin-top: 5px; margin-left: 8px;"/>
+          <span
+              style="background: #f19a37; width: 18px; height: 10px; margin-top: 8px; margin-left: 20px; display: inline-block; border-radius: 3px;"></span>
+          <TextSelector v-model="barModelValue2" :options="computedBarOptions2" @change="changeBarTwo" style="margin-top: 5px; margin-left: 8px;"/>
+        </div>
+        <div ref="bar" style="height: 400px;"></div>
+      </el-col>
+    </el-row>
+  </div>
 </template>
 
 <script setup>
 import { onMounted, ref, inject, computed, watch } from "vue"
 import * as echarts from "echarts"
 import TextSelector from '/@/components/TextSelector/index.vue'
-import { getAdStructureData } from "/@/views/adManage/sp/targets/api"
+import { getAdStructureData } from "/@/views/adManage/sp/placement/api"
 import { createDisabledOptions } from '../../../utils/dropdowndisable'
 import { barOptionsMap } from "/@/views/adManage/utils/enum"
 import { useShopInfo } from '/@/stores/shopInfo'
-
+import { usePublicData } from "/@/stores/publicData"
+import { storeToRefs } from 'pinia'
 
 const shopInfo = useShopInfo()
+const publicData = usePublicData()
+const { dateRange } = storeToRefs(publicData)
+const { profile } = storeToRefs(shopInfo)
 let barChart = ref()
 const pie = ref()
 const bar = ref()
 const loading = ref(true)
 
-const dateRange = inject('dateRange')
-
 // 下拉框相关
 const barOptions1 = [
-    {
-        value: 'ACOS',
-        label: 'ACOS',
-    },
-    {
-        value: 'ROAS',
-        label: 'ROAS',
-    },
-    {
-        value: 'Spend',
-        label: '花费',
-        units: '$',
-    },
-    {
-        value: 'TotalSales',
-        label: '销售额',
-    },
-    {
-        value: 'TotalPurchases',
-        label: '订单数',
-    },
-    {
-        value: 'TotalUnitOrdered',
-        label: '销量',
-    },
-    {
-        value: 'CPC',
-        label: '点击成本'
-    },
-    {
-        value: 'CPA',
-        label: '订单成本'
-    },
-    {
-        value: 'Impression',
-        label: '曝光量',
-    },
-    {
-        value: 'Click',
-        label: '点击量',
-    },
-    {
-        value: 'qwe',
-        label: '点击率'
-    },
-    {
-        value: '转化率',
-        label: '转化率'
-    },
-    {
-        value: 'TotalSalesSameSKU',
-        label: '推广商品销售额'
-    },
-    {
-        value: 'TotalSalesOtherSKU',
-        label: '其他商品销售额'
-    },
-    {
-        value: 'TotalPurchasesSameSKU',
-        label: '推广商品订单数'
-    },
-    {
-        value: 'TotalPurchasesOtherSKU',
-        label: '其他商品订单数'
-    },
-    {
-        value: 'TotalUnitOrderedSameSKU',
-        label: '推广商品销量'
-    },
-    {
-        value: 'TotalUnitOrderedOtherSKU',
-        label: '其他商品销量'
-    },
-    {
-        value: 'TopOfSearchImpressionShare',
-        label: '搜索结果顶部展示份额'
-    },
+  {
+    value: 'ACOS',
+    label: 'ACOS',
+  },
+  {
+    value: 'ROAS',
+    label: 'ROAS',
+  },
+  {
+    value: 'Spend',
+    label: '花费',
+    units: '$',
+  },
+  {
+    value: 'TotalSales',
+    label: '销售额',
+  },
+  {
+    value: 'TotalPurchases',
+    label: '订单数',
+  },
+  {
+    value: 'TotalUnitOrdered',
+    label: '销量',
+  },
+  {
+    value: 'CPC',
+    label: '点击成本'
+  },
+  {
+    value: 'CPA',
+    label: '订单成本'
+  },
+  {
+    value: 'Impression',
+    label: '曝光量',
+  },
+  {
+    value: 'Click',
+    label: '点击量',
+  },
+  {
+    value: 'qwe',
+    label: '点击率'
+  },
+  {
+    value: '转化率',
+    label: '转化率'
+  },
+  {
+    value: 'TotalSalesSameSKU',
+    label: '推广商品销售额'
+  },
+  {
+    value: 'TotalSalesOtherSKU',
+    label: '其他商品销售额'
+  },
+  {
+    value: 'TotalPurchasesSameSKU',
+    label: '推广商品订单数'
+  },
+  {
+    value: 'TotalPurchasesOtherSKU',
+    label: '其他商品订单数'
+  },
+  {
+    value: 'TotalUnitOrderedSameSKU',
+    label: '推广商品销量'
+  },
+  {
+    value: 'TotalUnitOrderedOtherSKU',
+    label: '其他商品销量'
+  },
+  {
+    value: 'TopOfSearchImpressionShare',
+    label: '搜索结果顶部展示份额'
+  },
 ]
 let barModelValue1 = ref(barOptions1[0].value)
 
 const barOptions2 = [
-    {
-        value: 'ACOS',
-        label: 'ACOS',
-    },
-    {
-        value: 'ROAS',
-        label: 'ROAS',
-    },
-    {
-        value: 'Spend',
-        label: '花费',
-        units: '$',
-    },
-    {
-        value: 'TotalSales',
-        label: '销售额',
-    },
-    {
-        value: 'TotalPurchases',
-        label: '订单数',
-    },
-    {
-        value: 'TotalUnitOrdered',
-        label: '销量',
-    },
-    {
-        value: 'CPC',
-        label: '点击成本'
-    },
-    {
-        value: 'CPA',
-        label: '订单成本'
-    },
-    {
-        value: 'Impression',
-        label: '曝光量',
-    },
-    {
-        value: 'Click',
-        label: '点击量',
-    },
-    {
-        value: 'qwe',
-        label: '点击率'
-    },
-    {
-        value: '转化率',
-        label: '转化率'
-    },
-    {
-        value: 'TotalSalesSameSKU',
-        label: '推广商品销售额'
-    },
-    {
-        value: 'TotalSalesOtherSKU',
-        label: '其他商品销售额'
-    },
-    {
-        value: 'TotalPurchasesSameSKU',
-        label: '推广商品订单数'
-    },
-    {
-        value: 'TotalPurchasesOtherSKU',
-        label: '其他商品订单数'
-    },
-    {
-        value: 'TotalUnitOrderedSameSKU',
-        label: '推广商品销量'
-    },
-    {
-        value: 'TotalUnitOrderedOtherSKU',
-        label: '其他商品销量'
-    },
-    {
-        value: 'TopOfSearchImpressionShare',
-        label: '搜索结果顶部展示份额'
-    },
+  {
+    value: 'ACOS',
+    label: 'ACOS',
+  },
+  {
+    value: 'ROAS',
+    label: 'ROAS',
+  },
+  {
+    value: 'Spend',
+    label: '花费',
+    units: '$',
+  },
+  {
+    value: 'TotalSales',
+    label: '销售额',
+  },
+  {
+    value: 'TotalPurchases',
+    label: '订单数',
+  },
+  {
+    value: 'TotalUnitOrdered',
+    label: '销量',
+  },
+  {
+    value: 'CPC',
+    label: '点击成本'
+  },
+  {
+    value: 'CPA',
+    label: '订单成本'
+  },
+  {
+    value: 'Impression',
+    label: '曝光量',
+  },
+  {
+    value: 'Click',
+    label: '点击量',
+  },
+  {
+    value: 'qwe',
+    label: '点击率'
+  },
+  {
+    value: '转化率',
+    label: '转化率'
+  },
+  {
+    value: 'TotalSalesSameSKU',
+    label: '推广商品销售额'
+  },
+  {
+    value: 'TotalSalesOtherSKU',
+    label: '其他商品销售额'
+  },
+  {
+    value: 'TotalPurchasesSameSKU',
+    label: '推广商品订单数'
+  },
+  {
+    value: 'TotalPurchasesOtherSKU',
+    label: '其他商品订单数'
+  },
+  {
+    value: 'TotalUnitOrderedSameSKU',
+    label: '推广商品销量'
+  },
+  {
+    value: 'TotalUnitOrderedOtherSKU',
+    label: '其他商品销量'
+  },
+  {
+    value: 'TopOfSearchImpressionShare',
+    label: '搜索结果顶部展示份额'
+  },
 ]
 let barModelValue2 = ref(barOptions2[2].value)
 
 onMounted(async () => {
-    barChart = echarts.init(bar.value)
+  barChart = echarts.init(bar.value)
 
-    window.addEventListener('resize', resizeChart)  // 监听窗口大小变化,调整图表大小
-    setTimeout(() => {
-        resizeChart()
-    }, 0)
+  window.addEventListener('resize', resizeChart)  // 监听窗口大小变化,调整图表大小
+  setTimeout(() => {
+    resizeChart()
+  }, 0)
 
-    await initBarData()
-    initChart()
+  await initBarData()
+  initChart()
 })
 
 // 获取总数据
 let allData = null
 
 async function setAdStructureData() {
-    allData = await getAdStructureData({ start: dateRange.value[0], end: dateRange.value[1], profile: shopInfo.profile.profile_id })
-    return allData.data
+  allData = await getAdStructureData({ startDate: dateRange.value[0], endDate: dateRange.value[1], profileId: shopInfo.profile.profile_id })
+  return allData.data
 }
 
 // 柱状图总数据
@@ -225,26 +228,29 @@ let xAxisList
 let xAxisMapList
 
 async function initBarData() {
-    responseData = await setAdStructureData()
-    barData = responseData
-    // 柱状图初始化数据
-    ACOSList = barData.map(item => item.ACOS)
-    SpendList = barData.map(item => item.Spend)
-    // 将x轴映射为中文
-    xAxisList = barData.map(item => item.Classification)
-    const classificationMap = {
-        'BROAD': '关键词-广泛',
-        'category': '品类',
-        'EXACT': '关键词-精准',
-        'asin': '商品',
-        'PHRASE': '关键词-词组',
-        'close-match': '紧密匹配',
-        'loose-match': '广泛匹配',
-        'substitutes': '同类商品',
-        'complements': '关联商品'
-    }
-    xAxisMapList = xAxisList.map(item => classificationMap[item])
-    loading.value = false
+  responseData = await setAdStructureData()
+  barData = responseData
+  // 柱状图初始化数据
+  ACOSList = barData.map(item => item.ACOS)
+  SpendList = barData.map(item => item.Spend)
+  // 将x轴映射为中文
+  xAxisList = barData.map(item => item.placement)
+  const classificationMap = {
+    'BROAD': '关键词-广泛',
+    'category': '品类',
+    'EXACT': '关键词-精准',
+    'asin': '商品',
+    'PHRASE': '关键词-词组',
+    'close-match': '紧密匹配',
+    'loose-match': '广泛匹配',
+    'substitutes': '同类商品',
+    'complements': '关联商品',
+    'top': '搜索结果顶部(首页)',
+    'rest_of_search': '搜索结果的其余位置',
+    'product_page': '商品页面'
+  }
+  xAxisMapList = xAxisList.map(item => classificationMap[item])
+  loading.value = false
 }
 
 // 重置图像
@@ -254,42 +260,42 @@ let option2
 
 // 点击下拉框后重新渲染柱状图
 function changeBarOne(newValue) {
-    barModelValue1.value = newValue
-    updateBarChart()
+  barModelValue1.value = newValue
+  updateBarChart()
 }
 
 function changeBarTwo(newValue) {
-    barModelValue2.value = newValue
-    updateBarChart()
+  barModelValue2.value = newValue
+  updateBarChart()
 }
 
 function updateBarChart() {
-    const barValues1 = barData.map(item => item[barModelValue1.value])
-    const barValues2 = barData.map(item => item[barModelValue2.value])
+  const barValues1 = barData.map(item => item[barModelValue1.value])
+  const barValues2 = barData.map(item => item[barModelValue2.value])
 
-    option.series[0].data = barValues1
-    option.series[1].data = barValues2
-    barChart.setOption(option)
+  option.series[0].data = barValues1
+  option.series[1].data = barValues2
+  barChart.setOption(option)
 }
 
 // 监听时间变化重新渲染表格
 watch(dateRange, async () => {
-    if (dateRange.value) {
-        loading.value = true
-        const resp = await setAdStructureData()
-        updateBarChartData(resp)
-        loading.value = false
-    }
+  if (dateRange.value) {
+    loading.value = true
+    const resp = await setAdStructureData()
+    updateBarChartData(resp)
+    loading.value = false
+  }
 })
 
 // 根据新数据和当前下拉框选择更新 柱状图数据
 function updateBarChartData(resp) {
-    const barValues1 = resp.map(item => item[barModelValue1.value])
-    const barValues2 = resp.map(item => item[barModelValue2.value])
+  const barValues1 = resp.map(item => item[barModelValue1.value])
+  const barValues2 = resp.map(item => item[barModelValue2.value])
 
-    option.series[0].data = barValues1
-    option.series[1].data = barValues2
-    barChart.setOption(option)
+  option.series[0].data = barValues1
+  option.series[1].data = barValues2
+  barChart.setOption(option)
 }
 
 const computedBarOptions1 = computed(() => createDisabledOptions(barOptions1, barModelValue2.value, barModelValue1.value))
@@ -297,94 +303,95 @@ const computedBarOptions2 = computed(() => createDisabledOptions(barOptions2, ba
 
 // 初始化图表
 function initChart() {
-    // 柱状图配置
-    option = {
-        tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-                type: 'shadow',
-                label: {
-                    backgroundColor: '#6a7985'
-                }
-            }
+  // 柱状图配置
+  option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow',
+        label: {
+          backgroundColor: '#6a7985'
+        }
+      }
+    },
+    // legend: {data: ['数据1', '数据2'],},
+    toolbox: {
+      feature: {
+        saveAsImage: { yAxisIndex: 'none' }
+      }
+    },
+    grid: { top: 50, right: 60, bottom: 50, left: 60 },
+    xAxis: [
+      {
+        type: 'category',
+        boundaryGap: true,
+        data: xAxisMapList,
+      },
+    ],
+    yAxis: [
+      {
+        type: 'value',
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: '#3a83f7' // 第一个 Y 轴的颜色
+          }
+        }
+      },
+      {
+        type: 'value',
+        splitLine: {
+          show: false
         },
-        // legend: {data: ['数据1', '数据2'],},
-        toolbox: {
-            feature: {
-                saveAsImage: { yAxisIndex: 'none' }
-            }
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: '#f19a37' // 第一个 Y 轴的颜色
+          }
+        }
+      }
+    ],
+    series: [
+      {
+        name: barOptionsMap[barModelValue1.value],
+        type: 'bar',
+        barWidth: '3%',
+        data: ACOSList,
+        yAxisIndex: 0,
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#3a83f7' },
+            { offset: 1, color: 'rgb(111, 209, 206)' },
+          ]),
+          // 柱状图圆角
+          borderRadius: [6, 6, 6, 6],
         },
-        grid: { top: 50, right: 60, bottom: 50, left: 60 },
-        xAxis: [
-            {
-                type: 'category',
-                boundaryGap: true,
-                data: xAxisMapList,
-            },
-        ],
-        yAxis: [
-            {
-                type: 'value',
-                axisLine: {
-                    show: true,
-                    lineStyle: {
-                        color: '#3a83f7' // 第一个 Y 轴的颜色
-                    }
-                }
-            },
-            {
-                type: 'value',
-                splitLine: {
-                    show: false
-                },
-                axisLine: {
-                    show: true,
-                    lineStyle: {
-                        color: '#f19a37' // 第一个 Y 轴的颜色
-                    }
-                }
-            }
-        ],
-        series: [
-            {
-                name: barOptionsMap[barModelValue1.value],
-                type: 'bar',
-                barWidth: '3%',
-                data: ACOSList,
-                yAxisIndex: 0,
-                itemStyle: {
-                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-                        { offset: 0, color: '#3a83f7' },
-                        { offset: 1, color: 'rgb(111, 209, 206)' },
-                    ]),
-                    // 柱状图圆角
-                    borderRadius: [6, 6, 6, 6],
-                },
-            },
-            {
-                name: barOptionsMap[barModelValue2.value],
-                type: 'bar',
-                barWidth: '3%',
-                data: SpendList,
-                yAxisIndex: 1,
-                itemStyle: {
-                    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-                        { offset: 0, color: '#f19a37' },
-                        { offset: 1, color: 'rgb(234,207,135)' },
-                    ]),
-                    // 柱状图圆角
-                    borderRadius: [6, 6, 6, 6],
-                },
-            },
-        ],
-    }
-    barChart.setOption(option)
-    resizeChart()
+      },
+      {
+        name: barOptionsMap[barModelValue2.value],
+        type: 'bar',
+        barWidth: '3%',
+        data: SpendList,
+        yAxisIndex: 1,
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#f19a37' },
+            { offset: 1, color: 'rgb(234,207,135)' },
+          ]),
+          // 柱状图圆角
+          borderRadius: [6, 6, 6, 6],
+        },
+      },
+    ],
+  }
+  barChart.setOption(option)
+  resizeChart()
 }
 
 function resizeChart() {
-    barChart.resize()
+  barChart.resize()
 }
+
 defineExpose({ resizeChart })
 </script>
 

+ 180 - 147
src/views/adManage/sp/placement/crud.tsx

@@ -1,160 +1,193 @@
 import * as api from './api'
-import {AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery} from '@fast-crud/fast-crud'
+import {dict, AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, EditReq, UserPageQuery} from '@fast-crud/fast-crud'
 import {inject} from 'vue'
 import {BaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
 
 
 export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
-    const pageRequest = async (query: UserPageQuery) => {
-        query['profile'] = context['profileId']
-        query['start'] = context['start']
-        query['end'] = context['end']
-        return await api.GetList(query)
-    }
-    const editRequest = async ({form, row}: EditReq) => {
-        form.id = row.id
-        return await api.UpdateObj(form)
-    }
-    const delRequest = async ({row}: DelReq) => {
-        return await api.DelObj(row.id)
-    }
-    const addRequest = async ({form}: AddReq) => {
-        return await api.AddObj(form)
-    }
+  const pageRequest = async (query: UserPageQuery) => {
+    query['profileId'] = context['profileId']
+    query['startDate'] = context['start']
+    query['endDate'] = context['end']
+    return await api.GetList(query)
+  }
+  const editRequest = async ({form, row}: EditReq) => {
+    form.id = row.id
+    return await api.UpdateObj(form)
+  }
+  const delRequest = async ({row}: DelReq) => {
+    return await api.DelObj(row.id)
+  }
+  const addRequest = async ({form}: AddReq) => {
+    return await api.AddObj(form)
+  }
 
-    //权限判定
-    const hasPermissions = inject('$hasPermissions')
+  //权限判定
+  const hasPermissions = inject('$hasPermissions')
 
-    return {
-        crudOptions: {
-            table: {
-                height: 800
-            },
-            container: {
-                fixedHeight: false
-            },
-            actionbar: {
-                show: true,
-                buttons: {
-                    add: {
-                        show: false
-                    },
-                    create: {
-                        text: '新建广告活动',
-                        type: 'primary',
-                        show: true,
-                        click() {
+  return {
+    crudOptions: {
+      table: {
+        height: 800,
+        border: false
+      },
+      container: {
+        fixedHeight: false
+      },
+      actionbar: {
+        show: true,
+        buttons: {
+          add: {
+            show: false
+          },
+          create: {
+            text: '新建广告活动',
+            type: 'primary',
+            show: true,
+            click() {
 
-                        }
-                    }
-                }
-            },
-            search: {
-                show: false
-            },
-            toolbar: {
-                buttons: {
-                    search: {
-                        show: true
-                    },
-                    compact: {
-                        show: false
-                    }
-                }
-            },
-            request: {
-                pageRequest,
-                addRequest,
-                editRequest,
-                delRequest,
-            },
-            rowHandle: {
-                fixed: 'right',
-                width: 80,
-                buttons: {
-                    view: {
-                        show: false,
-                    },
-                    edit: {
-                        iconRight: 'Edit',
-                        type: 'text',
-                        text: null
-                        // show: hasPermissions('dictionary:Update'),
-                    },
-                    remove: {
-                        iconRight: 'Delete',
-                        type: 'text',
-                        text: null
-                        // show: hasPermissions('dictionary:Delete'),
-                    },
-                },
-            },
-            columns: {
-                id: {
-                    title: 'ID',
-                    column: {
-                        show: false
-                    },
-                    form: {
-                        show: false
-                    }
-                },
-                campaignName: {
-                    title: '广告活动',
-                    column: {
-                        width: '200px',
-                        fixed: 'left',
-                        align: 'center',
-                    },
-                    search: {
-                        show: true,
-                        component: {
-                            props: {
-                                clearable: true
-                            }
-                        }
-                    },
-                    form: {
-                        rules: [{required: true, message: '必填项'}]
-                    }
-                },
-                placementClassification: {
-                    title: '广告位',
-                    column: {
-                        align: 'center',
-                    },
-                },
-                dynBidStrategy: {
-                    title: '竞价策略',
-                    column: {
-                        align: 'center',
-                    },
-                },
-                '竞价调整': {},
-                Impression: {
-                    title: '曝光量',
-                    column: {
-                        align: 'center',
-                    },
-                },
-                Click: {
-                    title: '点击量',
-                    column: {
-                        align: 'center',
-                    },
-                },
-                CTR: {title: '点击率', column: {align: 'center'}},
-                Spend: {title: '花费', column: {align: 'center'}},
-                CPC: {title: '点击成本', column: {align: 'center'}},
-                TotalPurchases: {title: '订单数', column: {align: 'center'}},
-                TotalSales: {title: '销售额', column: {align: 'center'}},
-                TotalUnitOrdered: {title: '销量', column: {align: 'center'}},
-                PurchasesRate: {title: '转化率', column: {align: 'center'}},
-                ACOS: {title: 'ACOS', column: {align: 'center'}},
-                ROAS: {title: 'ROAS', column: {align: 'center'}},
-                CPA: {title: '订单成本', column: {align: 'center'}},
-                ...BaseColumn
             }
+          }
         }
+      },
+      search: {
+        show: false
+      },
+      toolbar: {
+        buttons: {
+          search: {
+            show: true
+          },
+          compact: {
+            show: false
+          }
+        }
+      },
+      request: {
+        pageRequest,
+        addRequest,
+        editRequest,
+        delRequest,
+      },
+      rowHandle: {
+        fixed: 'right',
+        width: 80,
+        buttons: {
+          view: {
+            show: false,
+          },
+          edit: {
+            iconRight: 'Edit',
+            type: 'text',
+            text: null
+            // show: hasPermissions('dictionary:Update'),
+          },
+          remove: {
+            iconRight: 'Delete',
+            type: 'text',
+            text: null
+            // show: hasPermissions('dictionary:Delete'),
+          },
+        },
+      },
+      columns: {
+        id: {
+          title: 'ID',
+          column: {
+            show: false
+          },
+          form: {
+            show: false
+          }
+        },
+        campaignName: {
+          title: '广告活动',
+          column: {
+            width: '210px',
+            fixed: 'left',
+            align: 'center',
+          },
+          search: {
+            show: true,
+            component: {
+              props: {
+                clearable: true
+              }
+            }
+          },
+          form: {
+            rules: [{required: true, message: '必填项'}]
+          }
+        },
+        placement: {
+          title: '广告位',
+          column: {
+            align: 'center',
+            width: '160px',
+            formatter: (row) => {
+              switch (row.value) {
+                case 'top':
+                  return '搜索结果顶部(首页)'
+                case 'rest_of_search':
+                  return '搜索结果的其余位置'
+                case 'product_page':
+                  return '商品页面'
+                default:
+                  return '暂无数据'
+              }
+            }
+          }
+        },
+        dynBidStrategy: {
+          title: '竞价策略',
+          column: {
+            align: 'center',
+            width: '160px',
+            formatter: (row) => {
+              switch (row.value) {
+                case 'MANUAL':
+                  return '固定竞价'
+                case 'AUTO_FOR_SALES':
+                  return '动态竞价-提高和降低'
+                case 'LEGACY_FOR_SALES':
+                  return '动态竞价-仅降低'
+                default:
+                  return '暂无数据'
+              }
+            }
+          }
+        },
+        bidAdjustment: {
+          title: '竞价调整',
+          column: {
+            align: 'center',
+            width: '100px',
+          }
+        },
+        Impression: {
+          title: '曝光量',
+          column: {
+            align: 'center',
+          },
+        },
+        Click: {
+          title: '点击量',
+          column: {
+            align: 'center',
+          },
+        },
+        CTR: {title: '点击率', column: {align: 'center'}},
+        Spend: {title: '花费', column: {align: 'center'}},
+        CPC: {title: '点击成本', column: {align: 'center'}},
+        TotalPurchases: {title: '订单数', column: {align: 'center'}},
+        TotalSales: {title: '销售额', column: {align: 'center'}},
+        TotalUnitOrdered: {title: '销量', column: {align: 'center'}},
+        PurchasesRate: {title: '转化率', column: {align: 'center'}},
+        ACOS: {title: 'ACOS', column: {align: 'center'}},
+        ROAS: {title: 'ROAS', column: {align: 'center'}},
+        CPA: {title: '订单成本', column: {align: 'center'}},
+        ...BaseColumn
+      }
     }
+  }
 }

+ 46 - 45
src/views/adManage/sp/placement/index.vue

@@ -1,31 +1,31 @@
 <template>
-    <fs-page class="fs-page-custom">
-        <fs-crud ref="crudRef" v-bind="crudBinding">
-            <template #header-middle>
-                <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
-                    <el-tab-pane label="数据趋势" name="dataTendency">
-                        <DataTendencyChart ref="dataTendencyRef"/>
-                    </el-tab-pane>
-                    <el-tab-pane label="广告结构" name="adStruct" :lazy="true">
-                        <AdStructChart ref="adStructChartRef"/>
-                    </el-tab-pane>
-                    <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
-                </el-tabs>
-            </template>
-            <template #cell_campaignName="scope">
-                <el-link type="primary" :underline="false" @click="jumpGroup(scope.row)">{{ scope.row.campaignName }}</el-link>
-            </template>
-            <template #cell_MissedImpressions="scope">
-                {{ scope.row.MissedImpressionsLower ?? '0' }} ~ {{ scope.row.MissedImpressionsUpper ?? '0' }}
-            </template>
-            <template #cell_MissedClicks="scope">
-                {{ scope.row.MissedClicksLower ?? '0' }} ~ {{ scope.row.MissedClicksUpper ?? '0' }}
-            </template>
-            <template #cell_MissedSales="scope">
-                {{ scope.row.MissedSalesLower ?? '0' }} ~ {{ scope.row.MissedSalesUpper ?? '0' }}
-            </template>
-        </fs-crud>
-    </fs-page>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <template #header-middle>
+        <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
+          <el-tab-pane label="数据趋势" name="dataTendency">
+            <DataTendencyChart v-if="tabActiveName === 'dataTendency'" :fetchCard="getCardData" :fetchLine="getLineData"></DataTendencyChart>
+          </el-tab-pane>
+          <el-tab-pane label="广告结构" name="adStruct" :lazy="true">
+            <AdStructChart ref="adStructChartRef"/>
+          </el-tab-pane>
+          <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
+        </el-tabs>
+      </template>
+      <template #cell_campaignName="scope">
+        <el-link type="primary" :underline="false" @click="jumpGroup(scope.row)">{{ scope.row.campaignName }}</el-link>
+      </template>
+      <template #cell_MissedImpressions="scope">
+        {{ scope.row.MissedImpressionsLower ?? '0' }} ~ {{ scope.row.MissedImpressionsUpper ?? '0' }}
+      </template>
+      <template #cell_MissedClicks="scope">
+        {{ scope.row.MissedClicksLower ?? '0' }} ~ {{ scope.row.MissedClicksUpper ?? '0' }}
+      </template>
+      <template #cell_MissedSales="scope">
+        {{ scope.row.MissedSalesLower ?? '0' }} ~ {{ scope.row.MissedSalesUpper ?? '0' }}
+      </template>
+    </fs-crud>
+  </fs-page>
 </template>
 
 <script lang="ts" setup>
@@ -33,9 +33,10 @@ import {inject, nextTick, onMounted, ref} from 'vue'
 import {FsPage, useFs} from '@fast-crud/fast-crud'
 import {createCrudOptions} from './crud'
 import {useRoute, useRouter} from 'vue-router'
-import DataTendencyChart from './chartComponents/dataTendency.vue'
+import DataTendencyChart from '/@/views/adManage/sp/chartComponents/dataTendency.vue'
 import {useShopInfo} from '/@/stores/shopInfo'
 import AdStructChart from './chartComponents/adStruct.vue'
+import {getCardData, getLineData} from '/@/views/adManage/sp/campaigns/api'
 
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()
@@ -51,39 +52,39 @@ const dataTendencyRef = ref()
 
 
 onMounted(() => {
-    crudExpose.doRefresh()
+  crudExpose.doRefresh()
 })
 
 const resizeTabChart = () => {
-    if (tabActiveName.value === 'dataTendency') {
-        dataTendencyRef.value.resizeChart()
-    } else if (tabActiveName.value === 'adStruct') {
-        adStructChartRef.value.resizeChart()
-    }
+  if (tabActiveName.value === 'dataTendency') {
+    dataTendencyRef.value.resizeChart()
+  } else if (tabActiveName.value === 'adStruct') {
+    adStructChartRef.value.resizeChart()
+  }
 }
 const changeTab = () => {
-    nextTick(() => {
-        resizeTabChart()
-    })
+  nextTick(() => {
+    resizeTabChart()
+  })
 }
 defineExpose({resizeTabChart})
 
 const jumpGroup = (row: any) => {
-    router.push({
-        name: 'CampaignDetail',
-        query: {id: row.id, campaignId: row.campaignId, tagsViewName: row.campaignName},
-    })
+  router.push({
+    name: 'CampaignDetail',
+    query: {id: row.id, campaignId: row.campaignId, tagsViewName: row.campaignName},
+  })
 }
 
 </script>
 
 <style lang="scss">
 .chart-tabs {
-    margin: 5px 0;
+  margin: 5px 0;
 
-    .el-tabs__nav {
-        padding-left: 0 !important;
-    }
+  .el-tabs__nav {
+    padding-left: 0 !important;
+  }
 }
 
 </style>

+ 1 - 1
src/views/adManage/sp/targets/chartComponents/adStruct.vue

@@ -211,7 +211,7 @@ onMounted(async () => {
 let allData = null
 
 async function setAdStructureData() {
-    allData = await getAdStructureData({ start: dateRange.value[0], end: dateRange.value[1], profile: shopInfo.profile.profile_id })
+    allData = await getAdStructureData({ startDate: dateRange.value[0], endDate: dateRange.value[1], profileId: shopInfo.profile.profile_id })
     return allData.data
 }
 

+ 3 - 3
src/views/adManage/sp/targets/crud.tsx

@@ -7,9 +7,9 @@ import {dynBidStrategyEnum} from '/@/views/adManage/utils/enum.js'
 
 export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
     const pageRequest = async (query: UserPageQuery) => {
-        query['profile'] = context['profileId']
-        query['start'] = context['start']
-        query['end'] = context['end']
+        query['profileId'] = context['profileId']
+        query['startDate'] = context['start']
+        query['endDate'] = context['end']
         return await api.GetList(query)
     }
     const editRequest = async ({form, row}: EditReq) => {

+ 37 - 33
src/views/adManage/sp/targets/index.vue

@@ -1,19 +1,19 @@
 <template>
-    <fs-page class="fs-page-custom">
-        <fs-crud ref="crudRef" v-bind="crudBinding">
-            <template #header-middle>
-                <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
-                    <el-tab-pane label="数据趋势" name="dataTendency">
-                        <DataTendencyChart ref="dataTendencyRef"/>
-                    </el-tab-pane>
-                    <el-tab-pane label="广告结构" name="adStruct" :lazy="true">
-                        <AdStructChart ref="adStructChartRef"/>
-                    </el-tab-pane>
-                    <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
-                </el-tabs>
-            </template>
-        </fs-crud>
-    </fs-page>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <template #header-middle>
+        <el-tabs v-model="tabActiveName" class="chart-tabs" type="border-card" @tab-change="changeTab">
+          <el-tab-pane label="数据趋势" name="dataTendency">
+            <DataTendencyChart v-if="tabActiveName === 'dataTendency'" :fetchCard="getCardData" :fetchLine="getLineData"></DataTendencyChart>
+          </el-tab-pane>
+          <el-tab-pane label="广告结构" name="adStruct" :lazy="true">
+            <AdStructChart ref="adStructChartRef"/>
+          </el-tab-pane>
+          <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
+        </el-tabs>
+      </template>
+    </fs-crud>
+  </fs-page>
 </template>
 
 <script lang="ts" setup>
@@ -21,16 +21,20 @@ import {ref, onMounted, nextTick, inject} from 'vue'
 import {useFs, FsPage} from '@fast-crud/fast-crud'
 import {createCrudOptions} from './crud'
 import {useRoute, useRouter} from 'vue-router'
-import DataTendencyChart from './chartComponents/dataTendency.vue'
+import DataTendencyChart from '/@/views/adManage/sp/chartComponents/dataTendency.vue'
 import {useShopInfo} from '/@/stores/shopInfo'
+import {usePublicData} from '/@/stores/publicData'
 import AdStructChart from './chartComponents/adStruct.vue'
+import {getCardData, getLineData} from '/@/views/adManage/sp/campaigns/api'
+import {storeToRefs} from 'pinia'
+
 
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()
-const dateRange = inject('dateRange')
-const start = dateRange.value[0]
-const end = dateRange.value[1]
-const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {profileId: shopInfo.profile.profile_id, start: start, end: end}})
+const publicData = usePublicData()
+const {dateRange} = storeToRefs(publicData)
+const {profile} = storeToRefs(shopInfo)
+const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {profile, dateRange}})
 
 const route = useRoute()
 const router = useRouter()
@@ -39,31 +43,31 @@ const dataTendencyRef = ref()
 
 
 onMounted(() => {
-    crudExpose.doRefresh()
+  crudExpose.doRefresh()
 })
 
 const resizeTabChart = () => {
-    if (tabActiveName.value === 'dataTendency') {
-        dataTendencyRef.value.resizeChart()
-    } else if (tabActiveName.value === 'adStruct') {
-        adStructChartRef.value.resizeChart()
-    }
+  if (tabActiveName.value === 'dataTendency') {
+    dataTendencyRef.value.resizeChart()
+  } else if (tabActiveName.value === 'adStruct') {
+    adStructChartRef.value.resizeChart()
+  }
 }
 const changeTab = () => {
-    nextTick(() => {
-        resizeTabChart()
-    })
+  nextTick(() => {
+    resizeTabChart()
+  })
 }
 defineExpose({resizeTabChart})
 </script>
 
 <style lang="scss">
 .chart-tabs {
-    margin: 5px 0;
+  margin: 5px 0;
 
-    .el-tabs__nav {
-        padding-left: 0 !important;
-    }
+  .el-tabs__nav {
+    padding-left: 0 !important;
+  }
 }
 
 </style>