Просмотр исходного кода

Merge branch 'test' into wang

# Conflicts:
#	src/views/adManage/sp/campaigns/index.vue
WanGxC 1 год назад
Родитель
Сommit
c37e742576
27 измененных файлов с 524 добавлено и 235 удалено
  1. 1 0
      src/components/DateRangePicker/index.vue
  2. 31 24
      src/components/dataCompare/index.vue
  3. 6 0
      src/theme/app.scss
  4. 2 1
      src/types/views.d.ts
  5. 55 48
      src/views/adManage/portfolios/api.ts
  6. 0 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/api.ts
  7. 0 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/crud.tsx
  8. 7 7
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/index.vue
  9. 2 2
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/index.vue
  10. 0 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/api.ts
  11. 0 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/crud.tsx
  12. 2 1
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/index.vue
  13. 14 0
      src/views/adManage/sp/campaigns/campaignDetail/api.ts
  14. 20 0
      src/views/adManage/sp/campaigns/campaignDetail/budget/api.ts
  15. 57 0
      src/views/adManage/sp/campaigns/campaignDetail/budget/crud.tsx
  16. 44 0
      src/views/adManage/sp/campaigns/campaignDetail/budget/index.vue
  17. 116 0
      src/views/adManage/sp/campaigns/campaignDetail/budget/lineChart.vue
  18. 19 12
      src/views/adManage/sp/campaigns/campaignDetail/index.vue
  19. 1 1
      src/views/adManage/sp/campaigns/campaignDetail/placement/api.ts
  20. 10 8
      src/views/adManage/sp/campaigns/campaignDetail/placement/crud.tsx
  21. 14 25
      src/views/adManage/sp/campaigns/campaignDetail/placement/index.vue
  22. 70 75
      src/views/adManage/sp/campaigns/index.vue
  23. 3 3
      src/views/adManage/sp/index.vue
  24. 7 14
      src/views/adManage/sp/purchasedOtherProducts/index.vue
  25. 7 14
      src/views/adManage/sp/searchTerm/index.vue
  26. 32 0
      src/views/adManage/utils/enum.ts
  27. 4 0
      src/views/adManage/utils/tools.ts

+ 1 - 0
src/components/DateRangePicker/index.vue

@@ -14,6 +14,7 @@
       :clearable="false"
       :popper-options="{placement: props.popperPlacement}"
       @change="changedValue"
+      style="border-radius: 0;"
     />
   </div>
 </template>

+ 31 - 24
src/components/dataCompare/index.vue

@@ -1,33 +1,40 @@
 <template>
-  <p :class="colorClass" v-show="props.showCompare">
-    <template v-if="props.gapVal">
-      <el-icon>
-        <Top v-if="props.gapVal > 0"/>
-        <Bottom v-if="props.gapVal < 0"/>
-      </el-icon>
+  <p>{{ props.value }}</p>
+  <el-popover
+    effect="dark"
+    :width="260">
+    <template #reference>
+      <p :class="colorClass" v-show="props.showCompare">
+        <template v-if="props.gapVal">
+          <el-icon>
+            <Top v-if="props.gapVal > 0"/>
+            <Bottom v-if="props.gapVal < 0"/>
+          </el-icon>
+        </template>
+        <span>{{ props.gapVal ? (props.gapVal * 100).toFixed(2) + '%' : ''}}</span>
+      </p>
     </template>
-    <span>{{ props.gapVal ? (props.gapVal * 100).toFixed(2) + '%' : ''}}</span>
-  </p>
+    <p>对比周期:{{ compareDate[0] }} ~ {{ compareDate[1] }}</p>
+    <p>对比值:{{ props.prevVal }}</p>
+  </el-popover>
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue'
+import { ref, computed, Prop } from 'vue'
+import { getCompareDate } from '/@/views/adManage/utils/tools.js'
 
-const props = defineProps({
-  field: {
-    type: String,
-    reqeuired: true
-  },
-  value: {
-    type: Number,
-  },
-  gapVal: {
-    type: Number,
-  },
-  showCompare: {
-    type: Boolean,
-    default: false
-  }
+interface Props {
+  field: string,
+  value: number,
+  prevVal: number,
+  gapVal: number,
+  dateRange: string[],
+  showCompare: boolean
+}
+
+const props = defineProps<Props>()
+const compareDate = computed(() => {
+  return getCompareDate(props.dateRange)
 })
 
 const colorClass = computed(() => {

+ 6 - 0
src/theme/app.scss

@@ -330,6 +330,10 @@ body,
 
 .fs-page-custom {
 	position: initial !important;
+
+	.fs-search-col >* {
+		margin-left: 0 !important;
+	}
 }
 
 .asj-tabs {
@@ -408,3 +412,5 @@ body,
 		padding-left: 0 !important;
 	}
 }
+
+

+ 2 - 1
src/types/views.d.ts

@@ -369,7 +369,8 @@ declare interface SpCampaign {
 	targetingType?: string,
 	state?: string,
 	dynBidStrategy?: string,
-	portfolio?: Portfolio
+	portfolioName?: string
+	servingStatus?: string
 }
 
 declare type SpAdGroup = {

+ 55 - 48
src/views/adManage/portfolios/api.ts

@@ -1,73 +1,80 @@
-import { request } from '/@/utils/service';
-import { AddReq, DelReq, EditReq, InfoReq, UserPageQuery } from '@fast-crud/fast-crud';
+import { request } from '/@/utils/service'
+import { AddReq, DelReq, EditReq, InfoReq, UserPageQuery } from '@fast-crud/fast-crud'
 
-export const apiPrefix = '/api/ad_manage/portfolios/';
+export const apiPrefix = '/api/ad_manage/portfolios/'
 export function GetList(query: UserPageQuery) {
-    return request({
-        url: apiPrefix,
-        method: 'get',
-        params: query,
-    })
+	return request({
+		url: apiPrefix,
+		method: 'get',
+		params: query,
+	})
+}
+export function GetAllPortfolios() {
+	return request({
+		url: apiPrefix + 'select_list',
+		method: 'get',
+		params: { limit: 999 },
+	})
 }
 export function GetObj(id: InfoReq) {
-    return request({
-        url: apiPrefix + id,
-        method: 'get',
-    });
+	return request({
+		url: apiPrefix + id,
+		method: 'get',
+	})
 }
 
 export function AddObj(obj: AddReq) {
-    return request({
-        url: apiPrefix,
-        method: 'post',
-        data: obj,
-    });
+	return request({
+		url: apiPrefix,
+		method: 'post',
+		data: obj,
+	})
 }
 
 export function UpdateObj(obj: EditReq) {
-    return request({
-        url: apiPrefix + obj.id + '/',
-        method: 'put',
-        data: obj,
-    });
+	return request({
+		url: apiPrefix + obj.id + '/',
+		method: 'put',
+		data: obj,
+	})
 }
 
 export function DelObj(id: DelReq) {
-    return request({
-        url: apiPrefix + id + '/',
-        method: 'delete',
-        data: { id },
-    });
+	return request({
+		url: apiPrefix + id + '/',
+		method: 'delete',
+		data: { id },
+	})
 }
 
 export function getCardData(query: UserPageQuery) {
-    return request({
-        url: apiPrefix + "report/amount",
-        method: 'GET',
-        params: query
-    })
+	return request({
+		url: apiPrefix + 'report/amount',
+		method: 'GET',
+		params: query,
+	})
 }
 
 export function getLineData(query: UserPageQuery) {
-    return request({
-        url: apiPrefix + "report/trend/daily",
-        method: 'GET',
-        params: query
-    })
+	return request({
+		url: apiPrefix + 'report/trend/daily',
+		method: 'GET',
+		params: query,
+	})
 }
 
 export function getLineWeekData(query: UserPageQuery) {
-    return request({
-        url: apiPrefix + "report/trend/weekly",
-        method: 'GET',
-        params: query
-    })
+	return request({
+		url: apiPrefix + 'report/trend/weekly',
+		method: 'GET',
+		params: query,
+	})
 }
 
 export function getLineMonthData(query: UserPageQuery) {
-    return request({
-        url: apiPrefix + "report/trend/monthly",
-        method: 'GET',
-        params: query
-    })
-}
+	return request({
+		url: apiPrefix + 'report/trend/monthly',
+		method: 'GET',
+		params: query,
+	})
+}

+ 0 - 0
src/views/adManage/sp/ads/api.ts → src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/api.ts


+ 0 - 0
src/views/adManage/sp/ads/crud.tsx → src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/crud.tsx


+ 7 - 7
src/views/adManage/sp/ads/index.vue → src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/ads/index.vue

@@ -4,10 +4,10 @@
             <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 ref="dataTendencyRef"/> -->
                     </el-tab-pane>
                     <el-tab-pane label="广告结构" name="adStruct" :lazy="true">
-                        <AdStructChart ref="adStructChartRef"/>
+                        <!-- <AdStructChart ref="adStructChartRef"/> -->
                     </el-tab-pane>
                     <el-tab-pane label="散点视图" name="scatterView" :lazy="true"></el-tab-pane>
                 </el-tabs>
@@ -21,16 +21,16 @@ 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 './chartComponents/dataTendency.vue'
 import {useShopInfo} from '/@/stores/shopInfo'
-import AdStructChart from './chartComponents/adStruct.vue'
+// import AdStructChart from './chartComponents/adStruct.vue'
 
 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 start = dateRange.value[0]
+// const end = dateRange.value[1]
+const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: {}})
 
 const route = useRoute()
 const router = useRouter()

+ 2 - 2
src/views/adManage/sp/adGroups/adGroupDetail/index.vue → src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/index.vue

@@ -13,7 +13,7 @@
     </div>
     <el-tabs type="border-card" class="asj-detail-tabs">
       <el-tab-pane label="商品推广">
-        <Ads />
+        <!-- <Ads /> -->
       </el-tab-pane>
       <el-tab-pane label="定向"></el-tab-pane>
       <el-tab-pane label="否定投放"></el-tab-pane>
@@ -26,7 +26,7 @@
 import { Ref, ref, onMounted } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { GetObj } from '../api'
-import Ads from '/@/views/adManage/sp/ads/index.vue'
+// import Ads from '/@/views/adManage/sp/ads/index.vue'
 
 const router = useRouter()
 const route = useRoute()

+ 0 - 0
src/views/adManage/sp/adGroups/api.ts → src/views/adManage/sp/campaigns/campaignDetail/adGroups/api.ts


+ 0 - 0
src/views/adManage/sp/adGroups/crud.tsx → src/views/adManage/sp/campaigns/campaignDetail/adGroups/crud.tsx


+ 2 - 1
src/views/adManage/sp/adGroups/index.vue → src/views/adManage/sp/campaigns/campaignDetail/adGroups/index.vue

@@ -2,7 +2,7 @@
   <fs-page class="fs-page-custom">
     <fs-crud ref="crudRef" v-bind="crudBinding">
       <template #search-left>
-        <DateRangePicker v-model="dateRange" style="margin-bottom: 5px;"></DateRangePicker>
+        <DateRangePicker v-model="dateRange"></DateRangePicker>
       </template>
       <template #header-middle>
         <DataTendencyChart
@@ -55,6 +55,7 @@ const jumpAds = (row: any) => {
 watch(
   queryParams,
   async () => {
+
     crudExpose.doRefresh() 
   },
   { deep: true }

+ 14 - 0
src/views/adManage/sp/campaigns/campaignDetail/api.ts

@@ -0,0 +1,14 @@
+import { request } from '/@/utils/service'
+import { LocationQueryValue } from 'vue-router'
+// import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
+// import XEUtils from 'xe-utils';
+
+export const apiPrefix = '/api/ad_manage/spcampaigndetail/'
+
+export function GetObj(campaignId: LocationQueryValue | LocationQueryValue[]) {
+	return request({
+		url: apiPrefix + 'head/',
+		method: 'get',
+		params: { campaignId },
+	})
+}

+ 20 - 0
src/views/adManage/sp/campaigns/campaignDetail/budget/api.ts

@@ -0,0 +1,20 @@
+import { request } from '/@/utils/service';
+import { UserPageQuery } from '@fast-crud/fast-crud';
+
+
+export const apiPrefix = '/api/ad_manage/spcampaigndetail/budget/'
+export function GetList(query: UserPageQuery) {
+    return request({
+        url: apiPrefix,
+        method: 'get',
+        params: query,
+    })
+}
+
+export function GetLineList(query: UserPageQuery) {
+    return request({
+        url: apiPrefix,
+        method: 'get',
+        params: query,
+    })
+}

+ 57 - 0
src/views/adManage/sp/campaigns/campaignDetail/budget/crud.tsx

@@ -0,0 +1,57 @@
+import * as api from './api'
+import { dict, UserPageQuery, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'
+import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
+import { parseQueryParams } from '/@/views/adManage/utils/tools.js'
+import XEUtils from 'xe-utils'
+
+export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+	const pageRequest = async (query: UserPageQuery) => {
+		const params = parseQueryParams(context.value)
+		XEUtils.assign(query, params)
+		return await api.GetList(query)
+	}
+
+	return {
+		crudOptions: {
+			table: {
+				// height: 800,
+			},
+			container: {
+				fixedHeight: false,
+			},
+			actionbar: {
+				show: false,
+			},
+			search: {
+				show: true,
+				buttons: {
+					search: {
+						show: false
+					},
+					reset: {
+						show: false
+					}
+				}
+			},
+			toolbar: {
+				buttons: {
+					search: {
+						show: true,
+					},
+					compact: {
+						show: false,
+					},
+				},
+			},
+			request: {
+				pageRequest,
+			},
+			rowHandle: {
+				show: false,
+			},
+			columns: {
+				
+			},
+		},
+	}
+}

+ 44 - 0
src/views/adManage/sp/campaigns/campaignDetail/budget/index.vue

@@ -0,0 +1,44 @@
+<template>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <template #search-left>
+        <DateRangePicker v-model="dateRange"></DateRangePicker>
+      </template>
+      <template #header-middle>
+        <LineChart :query="queryParams"/>
+      </template>
+    </fs-crud>
+  </fs-page>
+</template>
+
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue'
+import { useFs, FsPage } from '@fast-crud/fast-crud'
+import { LocationQueryValue } from 'vue-router'
+import { usePublicData } from '/@/stores/publicData'
+import { storeToRefs } from 'pinia'
+import { createCrudOptions } from './crud'
+import LineChart from './lineChart.vue'
+import DateRangePicker from '/@/components/DateRangePicker/index.vue'
+
+const publicData = usePublicData()
+const { dateRange } = storeToRefs(publicData)
+interface Props {
+  campaignId: LocationQueryValue | LocationQueryValue[]
+}
+const props = defineProps<Props>()
+const queryParams = ref({
+  campaignId: props.campaignId,
+  dateRange
+})
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams })
+
+// onMounted(async () => {
+// 	crudExpose.doRefresh()
+// })
+
+</script>
+
+<style scoped>
+
+</style>

+ 116 - 0
src/views/adManage/sp/campaigns/campaignDetail/budget/lineChart.vue

@@ -0,0 +1,116 @@
+<template>
+  <el-card v-loading="loading" shadow="never" style="margin-bottom: 5px; border-radius:0;">
+    <div style="height: 350px;" ref="chartRef"></div>
+  </el-card>
+</template>
+
+<script lang="ts" setup>
+import { ref,onMounted, onBeforeUnmount, watch, computed } from 'vue'
+import * as echarts from 'echarts'
+import { GetLineList } from './api'
+import { parseQueryParams } from '/@/views/adManage/utils/tools.js'
+
+interface Props {
+  query: any
+}
+const props = defineProps<Props>()
+const chartRef = ref()
+let chartObj:any
+const loading = ref(true)
+const queryParams = computed(() => parseQueryParams(props.query))
+
+const resizeChart = () => { chartObj.resize() }
+const addResize = () => { window.addEventListener('resize', resizeChart) }
+const removeResize = () => { window.removeEventListener('resize', resizeChart) }
+onMounted(() => {
+  addResize()
+  setTimeout(() => { initLine() }, 0)
+})
+onBeforeUnmount(() => {
+	if(chartObj) {
+		chartObj.dispose()
+    chartObj = null
+	}
+  removeResize()
+})
+
+const initLine = async () => {
+  chartObj = echarts.init(chartRef.value)
+  const option = {
+    dataset: {
+      source: []
+    },
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        label: {
+          backgroundColor: '#6a7985'
+        }
+      }
+    },
+    grid: { top: 30, bottom: 30, left: 30, right: 30 },
+    xAxis: {
+      type: 'category'
+    },
+    yAxis: {
+      type: 'value',
+      name: '预算',
+      axisLine: {
+        show: true,
+				lineStyle: { color: '#0085ff' }
+      },
+    },
+    series: [
+      {
+        type: 'line',
+        encode: {
+          x: 'date',
+          y: 'campaignBudgetAmount'
+        },
+        smooth: true,
+        symbol: 'circle',
+        symbolSize: 4,
+        lineStyle: { width: 2 },
+        itemStyle: {
+          color: '#0085ff',
+          borderColor: '#0085ff'
+        },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#0085ff93' },
+            { offset: 1, color: '#0085ff03' },
+          ]),
+        },
+      }
+    ]
+  }
+  const items = await getDataset()
+  option.dataset.source = items
+  chartObj.setOption(option)
+  loading.value = false
+}
+const getDataset = async () => {
+  const resp = await GetLineList(queryParams.value)
+  return resp.data
+}
+watch(
+  props.query,
+  async () => {
+    loading.value = true
+
+    const dataset = await getDataset()
+    chartObj.setOption({
+      dataset: {
+        source: dataset
+      }
+    })
+
+    loading.value = false
+  },
+  { deep: true }
+)
+</script>
+
+<style scoped>
+
+</style>

+ 19 - 12
src/views/adManage/sp/campaigns/campaignDetail/index.vue

@@ -5,28 +5,28 @@
         <span> {{ campaignInfo.campaignName }}</span>
       </span>
       <div class="asj-detail-info">
-        <span>状态:{{ campaignInfo.state }}</span>
-        <span>预算:${{ campaignInfo.budget }}</span>
+        <span>状态:{{ campaignInfo.state }} ({{ campaignInfo.servingStatus }})</span>
+        <span>预算:{{ profile.currency_symbol + campaignInfo.budget }} | {{ campaignInfo.budgetType }}</span>
         <span>投放类型:{{ campaignInfo.targetingType }}</span>
         <span>投放日期:{{ campaignInfo.startDate }} ~ {{ campaignInfo.endDate ?? '无结束日期' }}</span>
-        <span>广告组合:{{ campaignInfo?.portfolio?.name }}</span>
-        <span>竞价策略:{{ campaignInfo.dynBidStrategy }}</span>
+        <span>广告组合:{{ campaignInfo?.portfolioName }}</span>
+        <span>竞价策略:{{ getEnumLabel(dynBidStrategyEnum, campaignInfo.dynBidStrategy) }}</span>
       </div>
     </div>
     <el-tabs type="border-card" class="asj-detail-tabs" v-model="tabActiveName">
       <el-tab-pane label="广告组" name="adGroup">
         <AdGroups :campaignId="route.query.campaignId" v-if="tabActiveName==='adGroup'"></AdGroups>
       </el-tab-pane>
-      <el-tab-pane label="预算" :lazy="true">
-        预算
+      <el-tab-pane label="预算" name="budget">
+        <Budget :campaignId="route.query.campaignId" v-if="tabActiveName==='budget'"></Budget>
       </el-tab-pane>
-      <el-tab-pane label="自动化" :lazy="true">
+      <el-tab-pane label="自动化" name="automation">
         自动化
       </el-tab-pane>
       <el-tab-pane label="广告位" name="placement">
         <Placement :campaignId="route.query.campaignId" v-if="tabActiveName==='placement'"/>
       </el-tab-pane>
-      <el-tab-pane label="否定投放" :lazy="true">
+      <el-tab-pane label="否定投放" name="negative">
         否定投放
       </el-tab-pane>
       <!-- <el-tab-pane label="操作日志" :lazy="true"></el-tab-pane> -->
@@ -36,19 +36,26 @@
 
 <script lang="ts" setup>
 import { ref, onMounted, onBeforeMount, Ref } from 'vue'
-import AdGroups from '/@/views/adManage/sp/adGroups/index.vue'
 import { useRoute, useRouter } from 'vue-router'
+import AdGroups from './adGroups/index.vue'
 import Placement from './placement/index.vue'
+import Budget from './budget/index.vue'
+import { getEnumLabel } from '/@/views/adManage/utils/tools.js'
+import { dynBidStrategyEnum, spCampaignServingStatusEnum } from '/@/views/adManage/utils/enum.js'
+import { useShopInfo } from '/@/stores/shopInfo'
+// import { usePublicData } from '/@/stores/publicData'
+import { storeToRefs } from 'pinia'
 
-import { GetObj } from '../api'
+import { GetObj } from './api'
 
-const router = useRouter()
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
 const route = useRoute()
 const campaignInfo: Ref<SpCampaign> = ref({})
 const tabActiveName = ref('adGroup')
 
 onMounted(async () => {
-  const resp = await GetObj(route.query.id)
+  const resp = await GetObj(route.query.campaignId)
   campaignInfo.value = resp.data
 })
 

+ 1 - 1
src/views/adManage/sp/campaigns/campaignDetail/placement/api.ts

@@ -2,7 +2,7 @@ import { request } from '/@/utils/service';
 import { UserPageQuery } from '@fast-crud/fast-crud';
 
 
-export const apiPrefix = '/api/ad_manage/spcampaigns/stat_placement/'
+export const apiPrefix = '/api/ad_manage/spcampaigndetail/placement/'
 export function GetList(query: UserPageQuery) {
     return request({
         url: apiPrefix,

+ 10 - 8
src/views/adManage/sp/campaigns/campaignDetail/placement/crud.tsx

@@ -1,16 +1,12 @@
-import * as api from './api'
-import { UserPageQuery, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'
-import { inject } from 'vue'
+import { CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'
 import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
+import { spCampaignPlacementEnum } from '/@/views/adManage/utils/enum'
 import XEUtils from 'xe-utils'
 
 
 export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
 	const { fetchData } = context
 
-	//权限判定
-	const hasPermissions = inject('$hasPermissions');
-
 	return {
 		crudOptions: {
 			table: {
@@ -57,13 +53,19 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
         show: false
       },
 			columns: {
-        placementClassification: {
+        placement: {
           title: '广告位',
           column: {
             width: '200px',
-						fixed: 'left'
+						fixed: 'left',
+						formatter({ value, row, index }){
+								return XEUtils.find(spCampaignPlacementEnum, (item) => item.value === value).label
+						}
           }
         },
+				bidAdjustment: {
+					title: '竞价调整'
+				},
         ...BaseColumn
 			}
 		}

+ 14 - 25
src/views/adManage/sp/campaigns/campaignDetail/placement/index.vue

@@ -2,25 +2,16 @@
   <fs-page class="fs-page-custom" v-loading='loading'>
     <fs-crud ref="crudRef" v-bind="crudBinding">
       <template #search-left>
-        <DateRangePicker v-model="dateRange" :timezone="shopInfo.profile.time_zone" style="margin-bottom: 5px;"></DateRangePicker>
+        <DateRangePicker v-model="dateRange"></DateRangePicker>
       </template>
       <template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">
-        <p>{{ scope.row[field] }}</p>
-        <el-popover
-          effect="dark"
-          :width="260">
-          <template #reference>
-            <p :class="scope.row[`gap${field}`] > 0 ? 'green' : 'red'" v-show="showCompare">
-              <el-icon v-show="scope.row[field]">
-                <Top v-if="scope.row[`gap${field}`] > 0"/>
-                <Bottom v-else/>
-              </el-icon>
-              <span>{{ scope.row[`gap${field}`] }}%</span>
-            </p>
-          </template>
-          <p>对比周期:{{ placementData.compare_date[0] }} ~ {{ placementData.compare_date[1] }}</p>
-          <p>对比值:{{ scope.row[`prev${field}`] }}</p>
-        </el-popover>
+        <DataCompare
+          :field="field" 
+          :value="scope.row[field]"
+          :prev-val="scope.row[`prev${field}`]"
+          :gap-val="scope.row[`gap${field}`]" 
+          :date-range="dateRange"
+          :show-compare="showCompare"/>
       </template>
       <template #toolbar-left>
         <div>
@@ -37,35 +28,33 @@ import { ref, onMounted, Ref, watch } from 'vue'
 import { useFs, FsPage } from '@fast-crud/fast-crud'
 import { createCrudOptions } from './crud'
 import { usePublicData } from '/@/stores/publicData'
-import { useShopInfo } from '/@/stores/shopInfo'
+import { storeToRefs } from 'pinia'
 import DateRangePicker from '/@/components/DateRangePicker/index.vue'
 import { GetList } from './api'
 import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
 import { LocationQueryValue } from 'vue-router'
+import DataCompare from '/@/components/dataCompare/index.vue'
 
 defineOptions({
   name: "Placement"
 })
 const publicData = usePublicData()
-const shopInfo = useShopInfo()
-const dateRange: Ref<string[]> = ref(publicData.dateRange)
+const { dateRange } = storeToRefs(publicData)
 interface Props {
   campaignId: LocationQueryValue | LocationQueryValue[]
 }
 const props = defineProps<Props>()
 const loading = ref(true)
-const placementData = ref({items: [], compare_date: []})
 
 const showCompare = ref(false)
 const fetchData = async () => {
   loading.value = true
   const resp = await GetList({ 
     campaignId: props.campaignId,
-    date__gte: dateRange.value[0],
-    date__lte: dateRange.value[1]
+    startDate: dateRange.value[0],
+    endDate: dateRange.value[1]
   })
-  placementData.value = resp.data
-  crudExpose.setTableData(placementData.value.items)
+  crudExpose.setTableData(resp.data)
   loading.value = false
 }
 

+ 70 - 75
src/views/adManage/sp/campaigns/index.vue

@@ -1,106 +1,101 @@
 <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'"
-                :query="queryParams"
-                :fetchCard="getCardData"
-                :fetchLine="getLineData"
-                :fetch-line-month="getLineMonthData"
-                :fetch-line-week="getLineWeekData">
-            </DataTendencyChart>
-          </el-tab-pane>
-          <el-tab-pane label="广告结构" name="adStruct">
-            <AdStructChart v-if="tabActiveName === 'adStruct'"/>
-          </el-tab-pane>
-          <el-tab-pane label="散点视图" name="scatterView">
-            <div v-if="tabActiveName === 'scatterView'">散点视图</div>
-          </el-tab-pane>
-        </el-tabs>
-      </template>
-      <template #cell_percentTimeInBudget="scope">
-        <el-progress :percentage="scope.row.percentTimeInBudget > 0 ? scope.row.percentTimeInBudget * 100 : 0"/>
-      </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-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'"
+							:query="queryParams"
+							:fetchCard="getCardData"
+							:fetchLine="getLineData"
+							:fetch-line-month="getLineMonthData"
+							:fetch-line-week="getLineWeekData">
+						</DataTendencyChart>
+					</el-tab-pane>
+					<el-tab-pane label="广告结构" name="adStruct">
+						<AdStructChart v-if="tabActiveName === 'adStruct'" />
+					</el-tab-pane>
+					<el-tab-pane label="散点视图" name="scatterView">
+						<div v-if="tabActiveName === 'scatterView'">散点视图</div>
+					</el-tab-pane>
+				</el-tabs>
+			</template>
+			<template #cell_percentTimeInBudget="scope">
+				<el-progress :percentage="scope.row.percentTimeInBudget > 0 ? scope.row.percentTimeInBudget * 100 : 0" />
+			</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>
 
-      <template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">
-        <p>{{ scope.row[field] }}</p>
-        <el-popover effect="dark" :width="260">
-          <template #reference>
-            <DataCompare :field="field" :value="scope.row[field]" :gapVal="scope.row[`gap${field}`]" :showCompare="showCompare"/>
-          </template>
-          <p>对比周期:{{ compareDate[0] }} ~ {{ compareDate[1] }}</p>
-          <p>对比值:{{ scope.row[`prev${field}`] }}</p>
-        </el-popover>
-      </template>
-      <template #toolbar-left>
-        <div class="campare-switch">
-          <span>数据对比 </span>
-          <el-switch v-model="showCompare" size="small"/>
-        </div>
-      </template>
-    </fs-crud>
-  </fs-page>
+			<template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">
+				<DataCompare
+          :field="field"
+          :value="scope.row[field]"
+          :prev-val="scope.row[`prev${field}`]"
+          :gap-val="scope.row[`gap${field}`]"
+          :date-range="dateRange"
+          :show-compare="showCompare"/>
+			</template>
+			<template #toolbar-left>
+				<div class="campare-switch">
+					<span>数据对比 </span>
+					<el-switch v-model="showCompare" size="small" />
+				</div>
+			</template>
+		</fs-crud>
+	</fs-page>
 </template>
 
 <script lang="ts" setup>
-import {computed, onMounted, ref, watch} from 'vue'
-import {FsPage, useFs} from '@fast-crud/fast-crud'
-import {createCrudOptions} from './crud'
-import {useShopInfo} from '/@/stores/shopInfo'
-import {usePublicData} from '/@/stores/publicData'
-import {storeToRefs} from 'pinia'
-import {useRouter} from 'vue-router'
+import { ref, onMounted, computed, watch, onBeforeMount } from 'vue'
+import { useFs, FsPage } from '@fast-crud/fast-crud'
+import { createCrudOptions } from './crud'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { usePublicData } from '/@/stores/publicData'
+import { storeToRefs } from 'pinia'
+import { useRoute, useRouter } from 'vue-router'
 import AdStructChart from './chartComponents/adStruct.vue'
 import DataTendencyChart from '/@/views/adManage/sp/chartComponents/dataTendency.vue'
-import {getCardData, getLineData, getLineMonthData, getLineWeekData} from './api'
-import {BaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
+import { getCardData, getLineData, getLineMonthData, getLineWeekData } from './api'
+import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
 import DataCompare from '/@/components/dataCompare/index.vue'
-import {getCompareDate} from '/@/views/adManage/utils/tools.js'
 
 const tabActiveName = ref('dataTendency')
 const shopInfo = useShopInfo()
 const publicData = usePublicData()
-const {dateRange} = storeToRefs(publicData)
-const {profile} = storeToRefs(shopInfo)
+const { dateRange } = storeToRefs(publicData)
+const { profile } = storeToRefs(shopInfo)
 const queryParams = ref({
   profileId: profile.value.profile_id,
   dateRange
 })
-const {crudBinding, crudRef, crudExpose} = useFs({createCrudOptions, context: queryParams})
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams })
 const router = useRouter()
 const showCompare = ref(false)
 
 onMounted(async () => {
-  crudExpose.doRefresh()
-})
-const compareDate = computed(() => {
-  return getCompareDate(dateRange.value)
+	crudExpose.doRefresh()
 })
 const jumpGroup = (row: any) => {
-  router.push({
-    name: 'CampaignDetail',
-    query: {id: row.id, campaignId: row.campaignId, tagsViewName: row.campaignName},
-  })
+	router.push({
+		name: 'CampaignDetail',
+		query: { campaignId: row.campaignId, tagsViewName: row.campaignName },
+	})
 }
 
 watch(queryParams, async () => {
-  crudExpose.doRefresh()
-}, {deep: true})
+	crudExpose.doRefresh()
+}, { deep: true })
 </script>
 
 <style lang="scss" scoped>
 .campare-switch {
-  flex: none;
+	flex: none;
 }
 </style>

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

@@ -30,7 +30,7 @@ import { ref, onBeforeMount, Ref, watch, provide } from 'vue'
 import { useShopInfo } from '/@/stores/shopInfo'
 import { usePublicData } from '/@/stores/publicData'
 import { storeToRefs } from 'pinia'
-import { GetList } from '/@/views/adManage/portfolios/api'
+import { GetAllPortfolios } from '/@/views/adManage/portfolios/api'
 import DateRangePicker from '/@/components/DateRangePicker/index.vue'
 import Campaigns from './campaigns/index.vue'
 import Keywords from './keywords/index.vue'
@@ -40,7 +40,7 @@ import AdvertisedProducts from './advertisedProducts/index.vue'
 import PurchasedOtherProducts from './purchasedOtherProducts/index.vue'
 import Placement from './placement/index.vue'
 
-const shopInfo = useShopInfo()
+// const shopInfo = useShopInfo()
 const publicData = usePublicData()
 const selectedPortfolios: Ref<string[]> = ref([])
 const portfolios: Ref<Portfolio[]> = ref([])
@@ -68,7 +68,7 @@ const tabsComponents: any = {
 provide('dateRange', dateRange)
 
 onBeforeMount(async () => {
-	const resp: APIResponseData = await GetList({ limit: 999 })
+	const resp: APIResponseData = await GetAllPortfolios()
 	portfolios.value = resp.data
 })
 

+ 7 - 14
src/views/adManage/sp/purchasedOtherProducts/index.vue

@@ -25,16 +25,13 @@
       </template>
 
       <template v-for="field of Object.keys(SpCampaignPuchasedOtherProductsColumn)" #[`cell_${field}`]="scope">
-        <p>{{ scope.row[field] }}</p>
-        <el-popover
-          effect="dark"
-          :width="260">
-          <template #reference>
-            <DataCompare :field="field" :value="scope.row[field]" :gapVal="scope.row[`gap${field}`]" :showCompare="showCompare"/>
-          </template>
-          <p>对比周期:{{ compareDate[0] }} ~ {{ compareDate[1] }}</p>
-          <p>对比值:{{ scope.row[`prev${field}`] }}</p>
-        </el-popover>
+        <DataCompare
+          :field="field" 
+          :value="scope.row[field]"
+          :prev-val="scope.row[`prev${field}`]"
+          :gap-val="scope.row[`gap${field}`]" 
+          :date-range="dateRange"
+          :show-compare="showCompare"/>
       </template>
       <template #toolbar-left>
         <div class="campare-switch">
@@ -57,7 +54,6 @@ import { usePublicData } from '/@/stores/publicData'
 import { storeToRefs } from 'pinia'
 import { spCampaignPuchasedOtherProductsMetricsEnum } from '/@/views/adManage/utils/enum.js'
 import { SpCampaignPuchasedOtherProductsColumn } from '/@/views/adManage/utils/commonTabColumn.js'
-import { getCompareDate } from '/@/views/adManage/utils/tools.js'
 import DataCompare from '/@/components/dataCompare/index.vue'
 
 const tabActiveName = ref("dataTendency")
@@ -76,9 +72,6 @@ const queryParams = ref({
   dateRange
 })
 const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams })
-const compareDate = computed(() => {
-  return getCompareDate(dateRange.value)
-})
 
 onMounted(async () => {
 	crudExpose.doRefresh()

+ 7 - 14
src/views/adManage/sp/searchTerm/index.vue

@@ -20,16 +20,13 @@
         
       </template>
       <template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">
-        <p>{{ scope.row[field] }}</p>
-        <el-popover
-          effect="dark"
-          :width="260">
-          <template #reference>
-            <DataCompare :field="field" :value="scope.row[field]" :gapVal="scope.row[`gap${field}`]" :showCompare="showCompare"/>
-          </template>
-          <p>对比周期:{{ compareDate[0] }} ~ {{ compareDate[1] }}</p>
-          <p>对比值:{{ scope.row[`prev${field}`] }}</p>
-        </el-popover>
+        <DataCompare
+          :field="field" 
+          :value="scope.row[field]"
+          :prev-val="scope.row[`prev${field}`]"
+          :gap-val="scope.row[`gap${field}`]" 
+          :date-range="dateRange"
+          :show-compare="showCompare"/>
       </template>
       <template #toolbar-left>
         <div class="campare-switch">
@@ -51,7 +48,6 @@ import { useShopInfo } from '/@/stores/shopInfo'
 import { usePublicData } from '/@/stores/publicData'
 import { storeToRefs } from 'pinia'
 import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn.js'
-import { getCompareDate } from '/@/views/adManage/utils/tools.js'
 import DataCompare from '/@/components/dataCompare/index.vue'
 
 const tabActiveName = ref("dataTendency")
@@ -66,9 +62,6 @@ const queryParams = ref({
 })
 const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams })
 
-const compareDate = computed(() => {
-  return getCompareDate(dateRange.value)
-})
 onMounted(async () => {
 	crudExpose.doRefresh()
 })

+ 32 - 0
src/views/adManage/utils/enum.ts

@@ -34,6 +34,38 @@ export const dynBidStrategyEnum = [
     {label: '固定竞价', value: 'MANUAL', color: 'warning'}
 ]
 
+export const spCampaignPlacementEnum = [
+  { label: '搜索结果顶部', value: 'top' },
+  { label: '商品页面', value: 'product_page' },
+  { label: '搜索结果的其余位置', value: 'rest_of_search' },
+]
+
+export const spCampaignStateEnum = [
+  { label: '投放中', value: 'ENABLE' },
+  { label: '已暂停', value: 'PAUSED' },
+  { label: '已归档', value: 'ARCHIVED' },
+  // { label: '', value: 'ENABLING' },
+  // { label: '', value: 'USER_DELETED' },
+  { label: '其它', value: 'OTHER' },
+]
+
+export const spCampaignServingStatusEnum = [
+  { label: '投放中', value: 'CAMPAIGN_STATUS_ENABLED' },
+  { label: '已暂停', value: 'CAMPAIGN_PAUSED' },
+  { label: '已归档', value: 'CAMPAIGN_ARCHIVED' },
+  { label: '超出预算', value: 'CAMPAIGN_OUT_OF_BUDGET' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' },
+  // { label: '', value: '' }
+]
+
 export const metricMap = {
   'Spend': '花费',
   'TotalSales': '销售额',

+ 4 - 0
src/views/adManage/utils/tools.ts

@@ -63,3 +63,7 @@ export function parseQueryParams(body: any) {
     }
     return ret
 }
+
+export function getEnumLabel(enumObj: {label:string, value:string}[], value: any) {
+    return enumObj.find(item => item.value === value)?.label
+}