|
@@ -0,0 +1,221 @@
|
|
|
+<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
|
|
|
+ :query="queryParams"
|
|
|
+ v-if="tabActiveName === 'dataTendency'"
|
|
|
+ :fetchCard="getCardData"
|
|
|
+ :fetch-line-month="getLineMonthData"
|
|
|
+ :fetch-line-week="getLineWeekData"
|
|
|
+ :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>
|
|
|
+ <template #cell_percentTimeInBudget="scope">
|
|
|
+ <el-progress :percentage="scope.row.percentTimeInBudget > 0 ? scope.row.percentTimeInBudget * 100 : 0"/>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #cell_resolvedExpression_value="scope">
|
|
|
+ <el-tooltip effect="dark" placement="top">
|
|
|
+ <template #content>
|
|
|
+ <p>{{ scope.row.resolvedExpression_value }}</p>
|
|
|
+ {{ scope.row.ASIN }}
|
|
|
+ </template>
|
|
|
+ <div>
|
|
|
+ <el-link :underline="false" class="ellipsis-inline" style="color: rgb(30, 33, 40); display: inline-block; max-width: 100%;">
|
|
|
+ {{ scope.row.resolvedExpression_value }}
|
|
|
+ </el-link>
|
|
|
+ <br>
|
|
|
+ <span class="ellipsis">
|
|
|
+ <span style="color: rgb(109, 119, 132)">ASIN: </span>
|
|
|
+ <span style="color: rgb(30, 33, 40)">{{ scope.row.ASIN }}</span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #cell_campaignName="scope">
|
|
|
+ <el-tooltip effect="dark" :content="scope.row.campaignName" placement="top">
|
|
|
+ <el-link type="primary" :underline="false" @click="jumpGroup(scope.row)">
|
|
|
+ <div class="en-text">{{ scope.row.campaignName }}</div>
|
|
|
+ </el-link>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ <template #cell_adGroupName="scope">
|
|
|
+ <el-tooltip effect="dark" :content="scope.row.adGroupName" placement="top">
|
|
|
+ <el-link type="primary" :underline="false" @click="jumpGroup(scope.row)">
|
|
|
+ <div class="en-text">{{ scope.row.adGroupName }}</div>
|
|
|
+ </el-link>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ <template #cell_suggestedBid="scope">
|
|
|
+ <div>{{ scope.row.suggestedBid ? `$${scope.row.suggestedBid}` : '--' }}</div>
|
|
|
+ <div class="text-range">
|
|
|
+ {{ scope.row.suggestedBid_lower ? `$${scope.row.suggestedBid_lower}` : '--' }} ~
|
|
|
+ {{ scope.row.suggestedBid_upper ? `$${scope.row.suggestedBid_upper}` : '--' }}
|
|
|
+ </div>
|
|
|
+ </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(SbBaseColumn)" #[`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 {nextTick, onMounted, ref, watch} from 'vue'
|
|
|
+import {FsPage, useFs} from '@fast-crud/fast-crud'
|
|
|
+import {createCrudOptions} from './crud'
|
|
|
+import {useRoute, useRouter} from 'vue-router'
|
|
|
+import DataTendencyChart from '/@/views/adManage/sb/chartComponents/dataTendency.vue'
|
|
|
+import {useShopInfo} from '/@/stores/shopInfo'
|
|
|
+import {usePublicData} from '/@/stores/publicData'
|
|
|
+import AdStructChart from './chartComponents/adStruct.vue'
|
|
|
+import {getCardData, getLineData, getLineMonthData, getLineWeekData} from './api'
|
|
|
+import {storeToRefs} from 'pinia'
|
|
|
+import {SbBaseColumn} from '/@/views/adManage/utils/commonTabColumn'
|
|
|
+import DataCompare from '/@/components/dataCompare/index.vue'
|
|
|
+
|
|
|
+
|
|
|
+const tabActiveName = ref('dataTendency')
|
|
|
+const shopInfo = useShopInfo()
|
|
|
+const publicData = usePublicData()
|
|
|
+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 route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+const adStructChartRef = ref()
|
|
|
+const dataTendencyRef = ref()
|
|
|
+const showCompare = ref(false)
|
|
|
+
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ crudExpose.doRefresh()
|
|
|
+})
|
|
|
+
|
|
|
+const jumpGroup = (row: any) => {
|
|
|
+ router.push({
|
|
|
+ name: 'CampaignDetail',
|
|
|
+ query: {campaignId: row.campaignId, tagsViewName: row.campaignName},
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const resizeTabChart = () => {
|
|
|
+ if (tabActiveName.value === 'dataTendency') {
|
|
|
+ dataTendencyRef.value.resizeChart()
|
|
|
+ } else if (tabActiveName.value === 'adStruct') {
|
|
|
+ adStructChartRef.value.resizeChart()
|
|
|
+ }
|
|
|
+}
|
|
|
+const changeTab = () => {
|
|
|
+ nextTick(() => {
|
|
|
+ resizeTabChart()
|
|
|
+ })
|
|
|
+}
|
|
|
+defineExpose({resizeTabChart})
|
|
|
+
|
|
|
+watch(queryParams, async () => {
|
|
|
+ crudExpose.doRefresh()
|
|
|
+}, {deep: true})
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.campare-switch {
|
|
|
+ flex: none;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep(.el-table__footer-wrapper td.el-table__cell:nth-child(n+3):nth-child(-n+6) .cell) {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+.en-text {
|
|
|
+ max-width: 100%;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 420;
|
|
|
+ word-break: break-word;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: normal;
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-line-clamp: 1;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep(.el-table__footer-wrapper) {
|
|
|
+ border: 0;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep(.el-table .el-table__footer-wrapper .cell) {
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.text-range {
|
|
|
+ color: #808184;
|
|
|
+}
|
|
|
+
|
|
|
+.ellipsis {
|
|
|
+ max-width: 100%;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 420;
|
|
|
+ word-break: break-word;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: normal;
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-line-clamp: 1;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+}
|
|
|
+
|
|
|
+.ellipsis-inline {
|
|
|
+ max-width: 100%;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 420;
|
|
|
+ word-break: break-word;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: normal;
|
|
|
+ display: inline;
|
|
|
+ -webkit-line-clamp: 1;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep(span.el-link__inner) {
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ display: inline;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|