feat(property-marketing): 新增投放指南详情页功能
refactor(property-marketing): 优化评分图标映射逻辑 feat(property-marketing): 实现投放指南历史记录操作功能 perf(property-marketing): 优化图表数据更新逻辑 feat(property-marketing): 添加时间筛选功能 实现保存投放指南功能 - 优化页面样式和布局
This commit is contained in:
@ -20,12 +20,14 @@
|
|||||||
"axios": "^1.3.0",
|
"axios": "^1.3.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mitt": "^3.0.0",
|
"mitt": "^3.0.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.29",
|
"pinia": "^2.0.29",
|
||||||
"sass": "^1.89.2",
|
"sass": "^1.89.2",
|
||||||
"swiper": "^11.2.8",
|
"swiper": "^11.2.8",
|
||||||
|
"update": "^0.7.4",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-cropper": "^1.1.4",
|
"vue-cropper": "^1.1.4",
|
||||||
"vue-draggable-plus": "^0.6.0",
|
"vue-draggable-plus": "^0.6.0",
|
||||||
|
|||||||
@ -295,13 +295,32 @@ export const getPlacementAccountProjectsTrend = (params = {}) => {
|
|||||||
export const getPlacementGuide = (params: {}) => {
|
export const getPlacementGuide = (params: {}) => {
|
||||||
return Http.get(`/v1/placement-account-projects/getGuideList`,params);
|
return Http.get(`/v1/placement-account-projects/getGuideList`,params);
|
||||||
};
|
};
|
||||||
|
//查询投放指南历史
|
||||||
|
export const getPlacementGuideHistory = (params: {}) => {
|
||||||
|
return Http.get(`/v1/placement-account-projects/getGuideListHistory`, params);
|
||||||
|
};
|
||||||
|
|
||||||
// 前端定时轮询获取ai检测结果
|
// 前端定时轮询获取ai检测结果
|
||||||
export const getAiResult = (params: {}) => {
|
export const getAiResult = (params: {}) => {
|
||||||
return Http.get(`/v1/placement-account-projects/getAiResult`, params);
|
return Http.get(`/v1/placement-account-projects/getAiResult`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const savePlacementGuide = (params: {}) => {
|
||||||
|
return Http.post(`/v1/placement-account-projects/saveGuideResult`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPlacementGuideDetail = (id: string) => {
|
||||||
|
return Http.get(`/v1/placement-account-projects/historylog/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
//删除记录
|
||||||
|
export const deleteHistorylog = (id: string) => {
|
||||||
|
return Http.delete(`/v1/placement-account-projects/historylog/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
// 投放账号-列表
|
// 投放账号-列表
|
||||||
export const getPlacementAccountsList = (params = {}) => {
|
export const getPlacementAccountsList = (params = {}) => {
|
||||||
return Http.get('/v1/placement-accounts/list', params);
|
return Http.get('/v1/placement-accounts/list', params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -129,12 +129,23 @@ const COMPONENTS: AppRouteRecordRaw[] = [
|
|||||||
path: 'investmentGuidelines',
|
path: 'investmentGuidelines',
|
||||||
name: 'PutAccountInvestmentGuidelines',
|
name: 'PutAccountInvestmentGuidelines',
|
||||||
meta: {
|
meta: {
|
||||||
locale: '平台投放指南',
|
locale: '投放指南',
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
roles: ['*'],
|
roles: ['*'],
|
||||||
},
|
},
|
||||||
component: () => import('@/views/property-marketing/put-account/investment-guidelines'),
|
component: () => import('@/views/property-marketing/put-account/investment-guidelines'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'detail/:id',
|
||||||
|
name: 'guideDetail',
|
||||||
|
meta: {
|
||||||
|
locale: '投放指南详情',
|
||||||
|
requiresAuth: true,
|
||||||
|
hideInMenu: true,
|
||||||
|
roles: ['*'],
|
||||||
|
},
|
||||||
|
component: () => import('@/views/property-marketing/put-account/investment-guidelines/detail'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
* @Date: 2025-06-27 17:36:31
|
* @Date: 2025-06-27 17:36:31
|
||||||
*/
|
*/
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import lodash from 'lodash';
|
||||||
export function toFixed(num: number | string, n: number): number {
|
export function toFixed(num: number | string, n: number): number {
|
||||||
return parseFloat(parseFloat(num.toString()).toFixed(n));
|
return parseFloat(parseFloat(num.toString()).toFixed(n));
|
||||||
}
|
}
|
||||||
@ -106,3 +106,12 @@ export function downloadByUrl(url: string, filename?: string) {
|
|||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查数据是否为空
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export function isEmpty(data: any): boolean {
|
||||||
|
// 使用 lodash 的 isEmpty 方法检查数据是否为空
|
||||||
|
return lodash.isEmpty(data);
|
||||||
|
}
|
||||||
|
|||||||
@ -43,7 +43,6 @@ let chartInstance: echarts.ECharts | null = null;
|
|||||||
|
|
||||||
const xAxisData = props.xAxisData;
|
const xAxisData = props.xAxisData;
|
||||||
const seriesData = props.seriesData;
|
const seriesData = props.seriesData;
|
||||||
console.log(seriesData, 'seriesData');
|
|
||||||
|
|
||||||
const initChart = () => {
|
const initChart = () => {
|
||||||
if (!chart.value) return;
|
if (!chart.value) return;
|
||||||
@ -53,8 +52,6 @@ const initChart = () => {
|
|||||||
}
|
}
|
||||||
chartInstance = echarts.init(chart.value);
|
chartInstance = echarts.init(chart.value);
|
||||||
|
|
||||||
console.log('init');
|
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
@ -98,9 +95,14 @@ const initChart = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.seriesData,
|
() => [props.xAxisData, props.seriesData],
|
||||||
() => {
|
([newXAxis, newSeries]) => {
|
||||||
initChart(); //重新渲染的方法
|
if (chartInstance) {
|
||||||
|
chartInstance.setOption({
|
||||||
|
xAxis: newXAxis,
|
||||||
|
series: newSeries,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|||||||
@ -45,7 +45,7 @@
|
|||||||
<div class="filter-row-item flex items-center">
|
<div class="filter-row-item flex items-center">
|
||||||
<span class="label">时间筛选</span>
|
<span class="label">时间筛选</span>
|
||||||
<a-space class="w-240px">
|
<a-space class="w-240px">
|
||||||
<a-range-picker size="medium" allow-clear format="YYYY-MM-DD HH:mm" class="w-100%" />
|
<a-range-picker v-model="query.data_time" size="medium" allow-clear format="YYYY-MM-DD" class="w-100%" />
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||||
@ -156,6 +156,7 @@ const query = reactive({
|
|||||||
names: '',
|
names: '',
|
||||||
platform: '',
|
platform: '',
|
||||||
operator_id: '',
|
operator_id: '',
|
||||||
|
data_time: [],
|
||||||
});
|
});
|
||||||
const xhlEcharts = reactive({});
|
const xhlEcharts = reactive({});
|
||||||
const getAccountsTrends = async () => {
|
const getAccountsTrends = async () => {
|
||||||
|
|||||||
@ -25,23 +25,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">人群分析</span>
|
<span class="placement-optimization-title">人群分析</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '人群分析').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '人群分析')"
|
||||||
18-24岁女性,兴趣为“美妆/穿搭”,一线城市,抖音平台 ROI 3.2</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(2)" style="width: 25px; height: 17px" />
|
|
||||||
25-34岁男性,兴趣为“数码产品”,二线城市,巨量引擎 ROI 2.8</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(3)" style="width: 25px; height: 17px" />
|
|
||||||
18-24岁男性,兴趣为“运动/健身”,三线城市,抖音 ROI 2.3</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -50,23 +39,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">投放素材</span>
|
<span class="placement-optimization-title">投放素材</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '投放素材').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '投放素材')"
|
||||||
图文风格 + 明确福利点,CTR 3.2%、CVR 8.5%</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
|
||||||
场景短视频 + 明确人设定位,CTR 2.7%、CVR 7.1%</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
|
||||||
口播讲解类 + 产品对比,CTR 2.1%、CVR 6.0%</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -77,23 +55,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">投放时段</span>
|
<span class="placement-optimization-title">投放时段</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '投放时段').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '投放时段')"
|
||||||
晚高峰时段(19:00–21:00),ROI 3.1</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
|
||||||
中午时段(11:30–13:00),ROI 2.5</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
|
||||||
下午茶时段(15:00–17:00),ROI 2.3</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -103,23 +70,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">平台表现</span>
|
<span class="placement-optimization-title">平台表现</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '平台表现').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PERFORMANCE_ANALYSIS, '平台表现')"
|
||||||
抖音 - ROI 3.2,CVR 8.5%</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(2)" style="width: 25px; height: 17px" />
|
|
||||||
聚光平台 - ROI 2.7,CVR 7.3%</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(3)" style="width: 25px; height: 17px" />
|
|
||||||
B站 - ROI 2.4,CVR 6.8%</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -140,23 +96,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">人群建议</span>
|
<span class="placement-optimization-title">人群建议</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '人群建议').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '人群建议')"
|
||||||
集中在 18–24 岁女性 + 精准兴趣标签(如“护肤”、“口红”)</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(2)" style="width: 25px; height: 17px" />
|
|
||||||
24–30 岁男性 + 实用类内容受众(如“工具控”、“搞机党”)</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(3)" style="width: 25px; height: 17px" />
|
|
||||||
泛娱乐向受众 + 较大地域分布(兴趣“短剧”、“直播带货”)</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -167,23 +112,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">素材建议</span>
|
<span class="placement-optimization-title">素材建议</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '素材建议').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '素材建议')"
|
||||||
福利明确+钩子强的图文短视频,建议加限时优惠提示</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(2)" style="width: 25px; height: 17px" />
|
|
||||||
场景代入型视频,突出客户痛点与产品关联</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(3)" style="width: 25px; height: 17px" />
|
|
||||||
达人口播/测评,搭配标题党封面吸引点击</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -195,23 +129,12 @@
|
|||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">投放策略建议</span>
|
<span class="placement-optimization-title">投放策略建议</span>
|
||||||
<a-space direction="vertical">
|
<a-space direction="vertical">
|
||||||
<a-space class="placement-optimization-str">
|
<a-space
|
||||||
<span>
|
v-if="getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '投放策略建议').length > 0"
|
||||||
<img :src="getStarIcon(1)" style="width: 25px; height: 17px" />
|
v-for="(item, index) in getSubmoduleContent(MODEL_PLACEMENT_SUGGESTION, '投放策略建议')"
|
||||||
预算前置在 ROI 最佳时段和平台,优先抢头部流量</span
|
:key="index"
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(2)" style="width: 25px; height: 17px" />
|
|
||||||
中等预算组合投放 + 高点击素材A/B测试</span
|
|
||||||
>
|
|
||||||
</a-space>
|
|
||||||
<a-space>
|
|
||||||
<span>
|
|
||||||
<img :src="getStarIcon(3)" style="width: 25px; height: 17px" />
|
|
||||||
低预算长周期测试,重点看 CVR,优胜劣汰</span
|
|
||||||
>
|
>
|
||||||
|
<span><img :src="getStarIcon(index)" style="width: 25px; height: 17px" />{{ item }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@ -223,13 +146,37 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
import { IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
||||||
|
import { isEmpty } from '@/utils/tools';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
action_guide: {
|
action_guide: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
|
tmp: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const MODEL_PERFORMANCE_ANALYSIS = '表现分析';
|
||||||
|
const MODEL_PLACEMENT_SUGGESTION = '新投放建议生成';
|
||||||
|
|
||||||
|
// 封装通用方法来获取 submodules 的内容
|
||||||
|
const getSubmoduleContent = (moduleName: string, submoduleName: string) => {
|
||||||
|
console.log(props.action_guide, 'getSubmoduleContent');
|
||||||
|
const module = props.action_guide
|
||||||
|
.find((item) => item.title === moduleName)
|
||||||
|
?.submodules.find((mod) => mod.subtitle === submoduleName);
|
||||||
|
const content = [];
|
||||||
|
if (module) {
|
||||||
|
const content = Object.values(module.content);
|
||||||
|
console.log(content, 'content');
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
import { getStarIcon } from '../../constants';
|
import { getStarIcon } from '../../constants';
|
||||||
import { defineProps } from 'vue';
|
import { defineProps } from 'vue';
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
|
||||||
<div class="part-div">
|
<div class="part-div">
|
||||||
<div class="part-div-header">
|
<div class="part-div-header">
|
||||||
<span class="part-div-header-title">本月摘要</span>
|
<span class="part-div-header-title">本月摘要</span>
|
||||||
@ -12,24 +11,44 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="month-data-div">
|
<div class="month-data-div">
|
||||||
<div style="align-self: stretch">
|
<div style="align-self: stretch">
|
||||||
<span class="month-text-black">总消耗:</span>
|
<a-space direction="vertical" v-for="(item, index) in overview">
|
||||||
<span class="month-text-blue">¥52,382.16</span>
|
<span :style="{ color: getColor(item?.highlight) }">{{ item.text }}</span>
|
||||||
<span class="month-normal-span">,较上周期</span><span class="month-text-red">↑12.6%</span>
|
<br />
|
||||||
<span class="month-normal-span">;<br />整体ROI:</span><span class="month-text-blue">2.84</span>
|
</a-space>
|
||||||
<span class="month-normal-span">,属于</span><span class="month-text-red">中等偏高水平</span>
|
<!-- <span class="month-text-black">总消耗:</span>-->
|
||||||
<span class="month-text-black">,较上周期 </span><span class="month-text-red">+0.45</span>
|
<!-- <span class="month-text-blue">¥52,382.16</span>-->
|
||||||
<span class="month-normal-span">;<br />主要转化来源:</span><span class="month-text-blue">抖音 46.3%</span>
|
<!-- <span class="month-normal-span">,较上周期</span><span class="month-text-red">↑12.6%</span>-->
|
||||||
<span class="month-normal-span">,CTR 2.91%;<br />优质素材表现:</span>
|
<!-- <span class="month-normal-span">;<br />整体ROI:</span><span class="month-text-blue">2.84</span>-->
|
||||||
<span class="month-text-blue">美团酒店爆款横版1号</span>
|
<!-- <span class="month-normal-span">,属于</span><span class="month-text-red">中等偏高水平</span>-->
|
||||||
<span class="month-normal-spanw">。CTR 3.47%,CVR 5.92%。</span>
|
<!-- <span class="month-text-black">,较上周期 </span><span class="month-text-red">+0.45</span>-->
|
||||||
|
<!-- <span class="month-normal-span">;<br />主要转化来源:</span><span class="month-text-blue">抖音 46.3%</span>-->
|
||||||
|
<!-- <span class="month-normal-span">,CTR 2.91%;<br />优质素材表现:</span>-->
|
||||||
|
<!-- <span class="month-text-blue">美团酒店爆款横版1号</span>-->
|
||||||
|
<!-- <span class="month-normal-spanw">。CTR 3.47%,CVR 5.92%。</span>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
import { IconQuestionCircle } from '@arco-design/web-vue/es/icon';
|
||||||
|
import { defineProps } from 'vue';
|
||||||
|
|
||||||
|
const colorMap = {
|
||||||
|
purple: 'purple',
|
||||||
|
orange: 'orange',
|
||||||
|
};
|
||||||
|
const props = defineProps({
|
||||||
|
overview: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const getColor = (highlight?: string) => {
|
||||||
|
return highlight ? colorMap[highlight] : undefined;
|
||||||
|
};
|
||||||
|
console.log(props.overview, 'overvie333');
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import './style.scss';
|
@import './style.scss';
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
//本月摘要数据-div
|
|
||||||
.month-data-div {
|
.month-data-div {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
padding: 16px 30px 16px 16px;
|
padding: 16px 30px 16px 16px;
|
||||||
@ -15,7 +14,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
//本月摘要-蓝色字体
|
|
||||||
.month-text-blue {
|
.month-text-blue {
|
||||||
color: var(--Brand-Brand-6, #6D4CFE);
|
color: var(--Brand-Brand-6, #6D4CFE);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -25,7 +23,6 @@
|
|||||||
word-wrap: break-word
|
word-wrap: break-word
|
||||||
}
|
}
|
||||||
|
|
||||||
//红色字体
|
|
||||||
.month-text-red {
|
.month-text-red {
|
||||||
color: var(--Functional-Danger-6, #F64B31);
|
color: var(--Functional-Danger-6, #F64B31);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -35,7 +32,6 @@
|
|||||||
word-wrap: break-word
|
word-wrap: break-word
|
||||||
}
|
}
|
||||||
|
|
||||||
//黑色字体
|
|
||||||
.month-text-black {
|
.month-text-black {
|
||||||
color: var(--Text-1, #211F24);
|
color: var(--Text-1, #211F24);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|||||||
@ -38,13 +38,13 @@
|
|||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">人群包优化</span>
|
<span class="placement-optimization-title">人群包优化</span>
|
||||||
<span class="placement-optimization-str">{{props.optimization?.[3]?.['content']}}</span>
|
<span class="placement-optimization-str">{{props?.optimization?.[3]?.['content']}}</span>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<div class="overall-strategy">
|
<div class="overall-strategy">
|
||||||
<span class="placement-optimization-title">素材优化</span>
|
<span class="placement-optimization-title">素材优化</span>
|
||||||
<span class="placement-optimization-str">{{props.optimization?.[4]['content']}}</span>
|
<span class="placement-optimization-str">{{props?.optimization?.[4]?.['content']}}</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
@ -65,6 +65,8 @@ const props = defineProps({
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(props.optimization,'optimization')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<a-table
|
<a-table class="account-table" :columns="columns" :data="listData" :pagination="false">
|
||||||
class="account-table"
|
<template #platform="{ record }">
|
||||||
:columns="columns"
|
<span class="mr-5px" v-if="record.platform.length > 0" v-for="(item, index) in record.platform">
|
||||||
:data="listResult.data"
|
<img :src="PLATFORM_LIST[item].icon" width="19" class="mr-4px" />
|
||||||
:filter-icon-align-left="alignLeft"
|
<span>{{ PLATFORM_LIST[item].label }}</span>
|
||||||
:pagination="false"
|
</span>
|
||||||
>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<a-space size="medium">
|
<a-space size="medium">
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -15,14 +15,14 @@
|
|||||||
type="warning"
|
type="warning"
|
||||||
ok-text="确认删除"
|
ok-text="确认删除"
|
||||||
cancel-text="取消"
|
cancel-text="取消"
|
||||||
@ok="deleteBrand(record.id)"
|
@ok="deleteData(record.id)"
|
||||||
>
|
>
|
||||||
<icon-delete></icon-delete>
|
<icon-delete></icon-delete>
|
||||||
</a-popconfirm>
|
</a-popconfirm>
|
||||||
</a-space>
|
</a-space>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="outline" class="operation-btn">下载</a-button>
|
<a-button type="outline" @click="downloadDetailAsImage(record.id)" class="operation-btn">下载</a-button>
|
||||||
<a-button type="outline" class="operation-btn">详情</a-button>
|
<a-button type="outline" @click="goDetail(record.id)" class="operation-btn">详情</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
@ -30,23 +30,15 @@
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import top1 from '@/assets/img/captcha/top1.svg';
|
|
||||||
import top2 from '@/assets/img/captcha/top2.svg';
|
|
||||||
import top3 from '@/assets/img/captcha/top3.svg';
|
|
||||||
import { IconDelete } from '@arco-design/web-vue/es/icon';
|
import { IconDelete } from '@arco-design/web-vue/es/icon';
|
||||||
|
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import html2canvas from 'html2canvas';
|
||||||
|
|
||||||
const listQuery = reactive({
|
|
||||||
project_id: ref(''),
|
|
||||||
platform: ref(''),
|
|
||||||
page: ref(1),
|
|
||||||
name: ref(''),
|
|
||||||
page_size: ref('10'),
|
|
||||||
});
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '生成日期',
|
title: '生成日期',
|
||||||
dataIndex: 'date',
|
dataIndex: 'created_at',
|
||||||
slotName: 'account_name',
|
|
||||||
width: 60,
|
width: 60,
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
},
|
},
|
||||||
@ -57,18 +49,16 @@ const columns = [
|
|||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleSlotName: 'project_name',
|
|
||||||
width: 180,
|
width: 180,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
title: '项目',
|
title: '计划',
|
||||||
dataIndex: 'project_name',
|
dataIndex: 'plan',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '平台',
|
title: '平台',
|
||||||
titleSlotName: 'week_consumption',
|
|
||||||
dataIndex: 'platform',
|
|
||||||
width: 120,
|
width: 120,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
slotName: 'platform',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@ -78,40 +68,54 @@ const columns = [
|
|||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const listResult = reactive({
|
// hotTranslation.vue
|
||||||
data: [
|
import { useRouter } from 'vue-router';
|
||||||
{
|
import { deleteHistorylog } from '@/api/all/propertyMarketing'; // 引入 useRouter
|
||||||
date: '日期',
|
|
||||||
account: '账号',
|
|
||||||
project_name: '项目名称',
|
|
||||||
week_consumption: '本周总消耗',
|
|
||||||
week_consumption_rate: 0.1,
|
|
||||||
roi: '2.6',
|
|
||||||
ctr: '3.1%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
account_name: '全球旅行',
|
|
||||||
platform_name: '平台',
|
|
||||||
project_name: '项目名称',
|
|
||||||
week_consumption: '本周总消耗',
|
|
||||||
week_consumption_rate: -0.1,
|
|
||||||
roi: '2.6',
|
|
||||||
ctr: '3.1%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
account_name: '全球旅行',
|
|
||||||
platform_name: '平台',
|
|
||||||
project_name: '项目名称',
|
|
||||||
week_consumption: '本周总消耗',
|
|
||||||
week_consumption_rate: -0.1,
|
|
||||||
roi: '2.6',
|
|
||||||
ctr: '3.1%',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
total: ref(0),
|
|
||||||
});
|
|
||||||
|
|
||||||
const topImages = [top1, top2, top3];
|
const router = useRouter(); // 创建 router 实例
|
||||||
|
|
||||||
|
// 详情
|
||||||
|
const goDetail = async (id) => {
|
||||||
|
// 使用 router.push 进行编程式导航,并传递话题 ID
|
||||||
|
router.push(`/put-account/detail/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadDetailAsImage = (id) => {
|
||||||
|
const url = `/put-account/detail/${id}`;
|
||||||
|
const win = window.open(url, '_blank');
|
||||||
|
|
||||||
|
win.onload = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
html2canvas(win.document.body, {
|
||||||
|
useCORS: true,
|
||||||
|
scale: 2,
|
||||||
|
}).then((canvas) => {
|
||||||
|
const imgData = canvas.toDataURL('image/png');
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = imgData;
|
||||||
|
link.download = `详情页面_${Date.now()}.png`;
|
||||||
|
link.click();
|
||||||
|
win.close(); // 关闭新窗口
|
||||||
|
});
|
||||||
|
}, 2000); // 等待页面加载
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const deleteData = async (id) => {
|
||||||
|
const { code, data } = await deleteHistorylog(id);
|
||||||
|
|
||||||
|
if (code === 200) {
|
||||||
|
Message.success('删除成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
listData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
data: [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|||||||
@ -1,28 +1,21 @@
|
|||||||
<!--表单搜索组件-->
|
<!--表单搜索组件-->
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<div class="container px-24px">
|
||||||
<a-space size="large" direction="vertical" class="search-form">
|
<div class="filter-row flex mb-20px">
|
||||||
<a-row class="grid-demo" :gutter="{ md: 8, lg: 24, xl: 32 }">
|
<div class="filter-row-item flex items-center">
|
||||||
<a-col :span="8">
|
<span class="label">账户名称</span>
|
||||||
<a-space>
|
<a-space size="medium" class="w-240px">
|
||||||
<span>账户</span>
|
<a-input v-model="query.account_name" placeholder="请搜索..." size="medium" allow-clear>
|
||||||
<a-input
|
|
||||||
class="w-310px"
|
|
||||||
:style="{ width: '320px' }"
|
|
||||||
v-model="query.account_name"
|
|
||||||
placeholder="请搜索..."
|
|
||||||
size="medium"
|
|
||||||
allow-clear
|
|
||||||
>
|
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<icon-search />
|
<icon-search />
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</div>
|
||||||
<a-col :span="8">
|
|
||||||
<a-space>
|
<div class="filter-row-item flex items-center">
|
||||||
<span>计划</span>
|
<span class="label">计划</span>
|
||||||
|
<a-space size="medium" class="w-240px">
|
||||||
<a-input
|
<a-input
|
||||||
class="w-310px"
|
class="w-310px"
|
||||||
:style="{ width: '320px' }"
|
:style="{ width: '320px' }"
|
||||||
@ -36,14 +29,13 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</div>
|
||||||
<a-col :span="8">
|
|
||||||
<a-space>
|
|
||||||
<span>平台</span>
|
|
||||||
|
|
||||||
|
<div class="filter-row-item flex items-center">
|
||||||
|
<span class="label">平台</span>
|
||||||
<a-select
|
<a-select
|
||||||
v-model="query.platform"
|
v-model="query.platform"
|
||||||
class="w-320"
|
class="w-150"
|
||||||
size="medium"
|
size="medium"
|
||||||
placeholder="全部"
|
placeholder="全部"
|
||||||
allow-clear
|
allow-clear
|
||||||
@ -53,43 +45,33 @@
|
|||||||
>{{ item.label }}
|
>{{ item.label }}
|
||||||
</a-option>
|
</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-space>
|
</div>
|
||||||
</a-col>
|
</div>
|
||||||
</a-row>
|
|
||||||
|
|
||||||
<a-row class="grid-demo" :gutter="{ md: 8, lg: 24, xl: 32 }">
|
<div class="filter-row flex mb-20px">
|
||||||
<a-col :span="10">
|
<div class="filter-row-item flex items-center">
|
||||||
<a-space>
|
<span class="label">时间筛选</span>
|
||||||
<span>时间筛选</span>
|
<a-space size="medium" class="w-240px">
|
||||||
<a-range-picker
|
<a-range-picker v-model="query.data_time" size="medium" allow-clear format="YYYY-MM-DD" class="w-310" />
|
||||||
showTime
|
|
||||||
:time-picker-props="{
|
|
||||||
defaultValue: ['00:00:00', '00:00:00'],
|
|
||||||
}"
|
|
||||||
@select="onSelect"
|
|
||||||
style="width: 380px"
|
|
||||||
/>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-col>
|
</div>
|
||||||
<a-col :span="8">
|
|
||||||
<a-space>
|
<div class="filter-row-item flex items-center">
|
||||||
<a-button type="outline" class="search-btn" @click="handleSearch">
|
<a-button class="w-84px search-btn mr-12px" size="medium" @click="handleSearch">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-search />
|
<icon-search />
|
||||||
</template>
|
</template>
|
||||||
<template #default>搜索</template>
|
<template #default>搜索</template>
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="outline" class="reset-btn" @click="handleSearch">
|
<a-button class="w-84px reset-btn" size="medium" @click="handleReset">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-refresh />
|
<icon-refresh />
|
||||||
</template>
|
</template>
|
||||||
<template #default>重置</template>
|
<template #default>重置</template>
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</div>
|
||||||
</a-col>
|
</div>
|
||||||
</a-row>
|
</div>
|
||||||
</a-space>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -103,22 +85,35 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const emits = defineEmits('onSearch', 'onReset', 'update:query');
|
const emits = defineEmits('onSearch', 'onReset', 'update:query');
|
||||||
|
// 获取最近7天的日期
|
||||||
|
const getLast7Days = () => {
|
||||||
|
const today = new Date();
|
||||||
|
const last7Days = new Date(today);
|
||||||
|
last7Days.setDate(today.getDate() - 7);
|
||||||
|
return [last7Days.toISOString().split('T')[0], today.toISOString().split('T')[0]];
|
||||||
|
};
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
emits('onSearch', props.query);
|
emits('onSearch', props.query);
|
||||||
};
|
};
|
||||||
|
// 使用 computed 实现 v-model
|
||||||
|
const localQuery = computed({
|
||||||
|
get: () => props.query,
|
||||||
|
set: (value) => emits('update:query', value),
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
localQuery.value.data_time = getLast7Days();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.container {
|
||||||
|
:deep(.arco-input-wrapper),
|
||||||
:deep(.arco-select-view-single),
|
:deep(.arco-select-view-single),
|
||||||
:deep(.arco-select-view-multiple),
|
:deep(.arco-select-view-multiple),
|
||||||
:deep(.arco-picker),
|
:deep(.arco-picker) {
|
||||||
:deep(.arco-input-wrapper) {
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border-color: #d7d7d9;
|
border-color: #d7d7d9;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
width: 224px;
|
|
||||||
height: 32px;
|
|
||||||
|
|
||||||
&:focus-within,
|
&:focus-within,
|
||||||
&.arco-input-focus {
|
&.arco-input-focus {
|
||||||
@ -128,27 +123,39 @@ const handleSearch = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-btn {
|
:deep(.search-btn) {
|
||||||
// 搜索
|
border-radius: 4px;
|
||||||
color: var(--Brand-6, #6d4cfe);
|
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||||
font-size: 14px;
|
color: #6d4cfe;
|
||||||
font-family: PuHuiTi-Medium;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 22px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 3px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-btn {
|
:deep(.reset-btn) {
|
||||||
// 重置
|
border-radius: 4px;
|
||||||
color: var(--Text-2, #3c4043);
|
border: 1px solid var(--BG-500, #b1b2b5);
|
||||||
|
background: var(--BG-white, #fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
.filter-row-item {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin-right: 8px;
|
||||||
|
color: #211f24;
|
||||||
|
font-family: 'PuHuiTi-Regular';
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-family: PuHuiTi-Medium;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 22px;
|
flex-shrink: 0;
|
||||||
height: 32px;
|
line-height: 22px; /* 157.143% */
|
||||||
border-radius: 3px;
|
}
|
||||||
word-wrap: break-word;
|
|
||||||
|
:deep(.arco-space-item) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -3,9 +3,9 @@
|
|||||||
<a-table
|
<a-table
|
||||||
class="account-table"
|
class="account-table"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="listResult.data"
|
:data="listData"
|
||||||
:filter-icon-align-left="alignLeft"
|
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
|
@sorter-change="handleSorterChange"
|
||||||
>
|
>
|
||||||
<template #week_consumption>
|
<template #week_consumption>
|
||||||
<a-space>
|
<a-space>
|
||||||
@ -53,8 +53,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #platform="{ record }">
|
<template #platform="{ record }">
|
||||||
<img :src="PLATFORM_LIST[record.platform].icon" width="19" class="mr-4px" />
|
<a-space size="medium" v-if="record.platform">
|
||||||
|
<img :src="PLATFORM_LIST[record.platform]?.icon" width="19" class="mr-4px" />
|
||||||
<span>{{ PLATFORM_LIST[record.platform].label }}</span>
|
<span>{{ PLATFORM_LIST[record.platform].label }}</span>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #weekConsumptionRate="{ record }">
|
<template #weekConsumptionRate="{ record }">
|
||||||
@ -73,22 +75,30 @@
|
|||||||
<template #suffix>%</template>
|
<template #suffix>%</template>
|
||||||
</a-statistic>
|
</a-statistic>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
|
||||||
|
|
||||||
|
<template #clickRate="{ record }">
|
||||||
|
<span>{{ `${record.click_rate}%` }}</span>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PLATFORM_LIST } from '../../../common_constants';
|
import { PLATFORM_LIST } from '../../../common_constants';
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
listResult: {
|
listData: {
|
||||||
type: Object,
|
type: Array,
|
||||||
default: () => {
|
default: () => {
|
||||||
total: 0;
|
|
||||||
data: [];
|
data: [];
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['updateQuery']);
|
||||||
|
|
||||||
|
const handleSorterChange = (column, order) => {
|
||||||
|
emit('updateQuery', { column, order });
|
||||||
|
};
|
||||||
const listQuery = reactive({
|
const listQuery = reactive({
|
||||||
project_id: ref(''),
|
project_id: ref(''),
|
||||||
platform: ref(''),
|
platform: ref(''),
|
||||||
@ -122,6 +132,9 @@ const columns = [
|
|||||||
dataIndex: 'total_use_amount',
|
dataIndex: 'total_use_amount',
|
||||||
width: 120,
|
width: 120,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '本周总消耗环比',
|
title: '本周总消耗环比',
|
||||||
@ -130,25 +143,34 @@ const columns = [
|
|||||||
width: 120,
|
width: 120,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
slotName: 'weekConsumptionRate',
|
slotName: 'weekConsumptionRate',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleSlotName: 'roi',
|
titleSlotName: 'roi',
|
||||||
dataIndex: 'roi',
|
dataIndex: 'roi',
|
||||||
width: 120,
|
width: 120,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titleSlotName: 'ctr',
|
titleSlotName: 'ctr',
|
||||||
dataIndex: 'click_rate',
|
dataIndex: 'click_rate',
|
||||||
width: 120,
|
width: 120,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
slotName: 'clickRate',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.table-data {
|
.table-data {
|
||||||
//账户列表-分页
|
|
||||||
.account-page {
|
.account-page {
|
||||||
padding: 10px 24px 20px 24px;
|
padding: 10px 24px 20px 24px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|||||||
@ -9,11 +9,11 @@ import top3 from '@/assets/img/captcha/top3.svg';
|
|||||||
*/
|
*/
|
||||||
export function getStarIcon(score: number): string {
|
export function getStarIcon(score: number): string {
|
||||||
switch (score) {
|
switch (score) {
|
||||||
case 1:
|
case 0:
|
||||||
return top1;
|
return top1;
|
||||||
case 2:
|
case 1:
|
||||||
return top2;
|
return top2;
|
||||||
case 3:
|
case 2:
|
||||||
return top3;
|
return top3;
|
||||||
default:
|
default:
|
||||||
return top1; // 默认返回最高分图标
|
return top1; // 默认返回最高分图标
|
||||||
|
|||||||
@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<div class="guidelines-data-wrap">
|
||||||
|
<div class="filter-wrap bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid">
|
||||||
|
<div class="top flex h-64px px-24px py-10px justify-between items-center">
|
||||||
|
<p class="text-18px font-400 lh-26px color-#211F24 title">投放信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container px-24px pt-12px pb-24px">
|
||||||
|
<a-row class="grid-demo" :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<div class="">
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<span>账户</span>
|
||||||
|
<span>{{ detailData?.account }}</span>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<div class="">
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<span>计划</span>
|
||||||
|
<span>3</span>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row class="grid-demo" :gutter="24" style="margin-top: 30px">
|
||||||
|
<a-col :span="12">
|
||||||
|
<div class="">
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<span>平台</span>
|
||||||
|
<span class="mr-5px" v-if="detailData.platform.length > 0" v-for="(item, index) in detailData.platform">
|
||||||
|
<img :src="PLATFORM_LIST[item].icon" width="19" class="mr-4px" />
|
||||||
|
<span>{{ PLATFORM_LIST[item].label }}</span>
|
||||||
|
</span>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<div class="">
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<span>生成时间</span>
|
||||||
|
<span>{{ detailData.created_at }}</span>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-spin :loading="loading" tip="数据分析中">
|
||||||
|
<div>
|
||||||
|
<!-- 本月摘要-->
|
||||||
|
<MonthData></MonthData>
|
||||||
|
|
||||||
|
<!-- <!– 投放建议–>-->
|
||||||
|
<PlacementSuggestions :optimization="detailData?.ai_result?.optimization?.modules"></PlacementSuggestions>
|
||||||
|
<!-- <!– 投放行动指南–>-->
|
||||||
|
<ActionGuideDistribution :action_guide="detailData?.ai_result.action_guide?.modules"></ActionGuideDistribution>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
|
<div>
|
||||||
|
<a-space class="down-btn">
|
||||||
|
<a-button type="outline" @click="onSearch">
|
||||||
|
<template #icon>
|
||||||
|
<icon-download />
|
||||||
|
</template>
|
||||||
|
<template #default>下载</template>
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="handleSave">
|
||||||
|
<template #icon>
|
||||||
|
<icon-drive-file />
|
||||||
|
</template>
|
||||||
|
<template #default>保存</template>
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
import MonthData from './components/month-data/index.vue';
|
||||||
|
import PlacementSuggestions from './components/placement-suggestions/index.vue';
|
||||||
|
import ActionGuideDistribution from './components/action-guide-distribution';
|
||||||
|
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants.ts';
|
||||||
|
import { getPlacementGuideDetail } from '@/api/all/propertyMarketing';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
const tabData = ref('placement_guide');
|
||||||
|
|
||||||
|
const query = reactive({
|
||||||
|
platform: '',
|
||||||
|
date_time: '',
|
||||||
|
sort_column: '',
|
||||||
|
sort_order: '',
|
||||||
|
page_size: 20,
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleUpdateQuery = (payload) => {
|
||||||
|
payload.order = payload.order === 'ascend' ? 'asc' : 'desc';
|
||||||
|
query.sort_column = payload.column;
|
||||||
|
query.sort_order = payload.order;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const saveForm = reactive({
|
||||||
|
account: [],
|
||||||
|
plan: [],
|
||||||
|
platform: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const detailData = reactive({
|
||||||
|
platform: [],
|
||||||
|
ai_result: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const id = route.params.id;
|
||||||
|
const getDetail = async () => {
|
||||||
|
const { code, data } = await getPlacementGuideDetail(id);
|
||||||
|
console.log(data, 'data');
|
||||||
|
console.log(code, 'code');
|
||||||
|
if (code === 200) {
|
||||||
|
Object.assign(detailData, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDetail();
|
||||||
|
});
|
||||||
|
// 定时任务请求接口
|
||||||
|
// const timer = setInterval(() => {
|
||||||
|
// getSyncAiResult();
|
||||||
|
// }, 5000);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
@ -1,8 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<div class="guidelines-data-wrap">
|
||||||
<div class="part-div">
|
<div class="part-div">
|
||||||
<div>
|
<div>
|
||||||
<a-tabs v-model:activeKey="tabData" class="a-tab-class" default-active-key="placement_guide">
|
<a-tabs
|
||||||
|
v-model:activeKey="tabData"
|
||||||
|
@tab-click="onSearch"
|
||||||
|
class="a-tab-class"
|
||||||
|
default-active-key="placement_guide"
|
||||||
|
>
|
||||||
<a-tab-pane key="placement_guide" title="投放指南"></a-tab-pane>
|
<a-tab-pane key="placement_guide" title="投放指南"></a-tab-pane>
|
||||||
<a-tab-pane key="guide_history">
|
<a-tab-pane key="guide_history">
|
||||||
<template #title>历史投放指南</template>
|
<template #title>历史投放指南</template>
|
||||||
@ -14,30 +19,45 @@
|
|||||||
<!-- 投放指南-->
|
<!-- 投放指南-->
|
||||||
<PlacementGuideList
|
<PlacementGuideList
|
||||||
v-if="tabData === 'placement_guide'"
|
v-if="tabData === 'placement_guide'"
|
||||||
:listResult="{ data: guideListData.data, total: pageInfo.total }"
|
:listData="listData.list"
|
||||||
|
@updateQuery="handleUpdateQuery"
|
||||||
></PlacementGuideList>
|
></PlacementGuideList>
|
||||||
<!-- 历史指南列表-->
|
<!-- 历史指南列表-->
|
||||||
<GuideListHistory v-if="tabData === 'guide_history'"></GuideListHistory>
|
<GuideListHistory v-if="tabData === 'guide_history'" :listData="listData.list"></GuideListHistory>
|
||||||
|
|
||||||
|
<div v-if="listData.total > 0" class="pagination-box flex justify-end">
|
||||||
|
<a-pagination
|
||||||
|
:total="listData.total"
|
||||||
|
size="mini"
|
||||||
|
show-total
|
||||||
|
show-jumper
|
||||||
|
show-page-size
|
||||||
|
:current="query.page"
|
||||||
|
:page-size="query.pageSize"
|
||||||
|
@change="onPageChange"
|
||||||
|
@page-size-change="onPageSizeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-spin :loading="loading" tip="数据分析中">
|
<div v-if="loading === false">
|
||||||
<!-- 本月摘要-->
|
<!-- 本月摘要-->
|
||||||
<MonthData></MonthData>
|
<MonthData :overview="aiResult.overview"></MonthData>
|
||||||
|
|
||||||
<!-- 投放建议-->
|
<!-- 投放建议-->
|
||||||
<PlacementSuggestions :optimization="aiResult.optimization"></PlacementSuggestions>
|
<PlacementSuggestions :optimization="aiResult.optimization"></PlacementSuggestions>
|
||||||
<!-- 投放行动指南-->
|
<!-- 投放行动指南-->
|
||||||
<ActionGuideDistribution :action_guide="aiResult.action_guide"></ActionGuideDistribution>
|
<ActionGuideDistribution :action_guide="aiResult.action_guide" :tmp="tmp"></ActionGuideDistribution>
|
||||||
</a-spin>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a-space class="down-btn">
|
<a-space class="down-btn">
|
||||||
<a-button type="outline" @click="handleSearch">
|
<a-button type="outline" @click="onSearch">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-download />
|
<icon-download />
|
||||||
</template>
|
</template>
|
||||||
<template #default>下载</template>
|
<template #default>下载</template>
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="primary" @click="handleSearch">
|
<a-button type="primary" @click="handleSave">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-drive-file />
|
<icon-drive-file />
|
||||||
</template>
|
</template>
|
||||||
@ -45,7 +65,7 @@
|
|||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</view>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -58,58 +78,112 @@ import PlacementSuggestions from './components/placement-suggestions/index.vue';
|
|||||||
import ActionGuideDistribution from './components/action-guide-distribution';
|
import ActionGuideDistribution from './components/action-guide-distribution';
|
||||||
import {
|
import {
|
||||||
getAiResult,
|
getAiResult,
|
||||||
getPlacementAccountData,
|
|
||||||
getPlacementAccountDataList,
|
|
||||||
getPlacementGuide,
|
getPlacementGuide,
|
||||||
|
getPlacementGuideHistory,
|
||||||
|
savePlacementGuide,
|
||||||
} from '@/api/all/propertyMarketing';
|
} from '@/api/all/propertyMarketing';
|
||||||
|
|
||||||
const tabData = ref('placement_guide');
|
const tabData = ref('placement_guide');
|
||||||
|
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
platform: '',
|
platform: '',
|
||||||
});
|
date_time: '',
|
||||||
|
sort_column: '',
|
||||||
const loading = ref(false);
|
sort_order: '',
|
||||||
|
page_size: 20,
|
||||||
const guideListData = reactive({
|
|
||||||
data: [],
|
|
||||||
});
|
|
||||||
const pageInfo = reactive({
|
|
||||||
total: 0,
|
|
||||||
page_size: 0,
|
|
||||||
page: 1,
|
page: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSearch = async () => {
|
const tmp = ref(0);
|
||||||
const { code, data } = await getPlacementGuide(query);
|
|
||||||
if (code === 200) {
|
const onPageChange = (current) => {
|
||||||
guideListData.data = data.data;
|
query.page = current;
|
||||||
getSyncAiResult();
|
onSearch();
|
||||||
}
|
};
|
||||||
console.log(guideListData, 'guideListData');
|
const onPageSizeChange = (pageSize) => {
|
||||||
|
query.page_size = pageSize;
|
||||||
|
onSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUpdateQuery = (payload) => {
|
||||||
|
payload.order = payload.order === 'ascend' ? 'asc' : 'desc';
|
||||||
|
query.sort_column = payload.column;
|
||||||
|
query.sort_order = payload.order;
|
||||||
|
onSearch();
|
||||||
|
};
|
||||||
|
|
||||||
|
const loading = ref(true);
|
||||||
|
|
||||||
|
const listData = reactive({
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSearch = async () => {
|
||||||
|
let result;
|
||||||
|
if (tabData.value === 'placement_guide') {
|
||||||
|
result = await getPlacementGuide(query);
|
||||||
|
} else {
|
||||||
|
result = await getPlacementGuideHistory(query);
|
||||||
|
}
|
||||||
|
const { code, data } = result;
|
||||||
|
console.log(data, 'data');
|
||||||
|
if (code === 200) {
|
||||||
|
listData.list = data.data;
|
||||||
|
listData.total = data.total;
|
||||||
|
if (tabData.value === 'placement_guide') {
|
||||||
|
getSyncAiResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
const aiResult = reactive({
|
const aiResult = reactive({
|
||||||
optimization: [], //投放建议优化
|
optimization: [], //投放建议优化
|
||||||
action_guide: [], //新投放建议生成
|
action_guide: [], //新投放建议生成
|
||||||
|
overview: [], //新投放建议生成
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const saveForm = reactive({
|
||||||
|
account: [],
|
||||||
|
plan: [],
|
||||||
|
platform: [],
|
||||||
|
aiResult: [],
|
||||||
|
});
|
||||||
|
const timer = ref(null);
|
||||||
const getSyncAiResult = async () => {
|
const getSyncAiResult = async () => {
|
||||||
|
if (listData.list.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const { code, data } = await getAiResult(query);
|
const { code, data } = await getAiResult(query);
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
// 成功或者失败清除定时任务
|
// 成功或者失败清除定时任务
|
||||||
if ((data.status && data.status === 3) || data.status === 2) {
|
if ((data.status && data.status === 3) || data.status === 2) {
|
||||||
// clearInterval(timer);
|
// clearInterval(timer);
|
||||||
loading.value = false;
|
|
||||||
}
|
}
|
||||||
aiResult.optimization = data.result.optimization.modules;
|
aiResult.optimization = data.result.optimization.modules;
|
||||||
aiResult.action_guide = data.result?.action_guide?.modules;
|
aiResult.action_guide = data.result?.action_guide?.modules;
|
||||||
|
aiResult.overview = data.result?.overview?.content_blocks;
|
||||||
|
Object.assign(saveForm, data);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
// 定时任务请求接口
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
getSyncAiResult();
|
||||||
|
}, 5000);
|
||||||
|
console.log(loading.value, 'loading.value');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
const updatedSaveForm = {
|
||||||
|
...saveForm,
|
||||||
|
ai_result: aiResult,
|
||||||
|
};
|
||||||
|
const { code, data } = await savePlacementGuide(updatedSaveForm);
|
||||||
|
if (code === 200) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 定时任务请求接口
|
onMounted(() => {
|
||||||
// const timer = setInterval(() => {
|
onSearch();
|
||||||
// getSyncAiResult();
|
});
|
||||||
// }, 5000);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
margin-top: 15px;
|
||||||
// margin: 10px;
|
// margin: 10px;
|
||||||
|
|
||||||
.arco-tabs {
|
.arco-tabs {
|
||||||
@ -42,7 +43,6 @@
|
|||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
//每块div 标题
|
|
||||||
.part-div-header-title {
|
.part-div-header-title {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -55,13 +55,12 @@
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
//账户指南-搜索div
|
|
||||||
.search-form {
|
.search-form {
|
||||||
padding: 10px 24px 20px 24px;
|
padding: 10px 24px 20px 24px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//账户列表-表格
|
|
||||||
.account-table {
|
.account-table {
|
||||||
padding: 1px 24px 20px 24px;
|
padding: 1px 24px 20px 24px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -85,7 +84,6 @@
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
//本周摘要div
|
|
||||||
.month-body-div {
|
.month-body-div {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
@ -96,7 +94,7 @@
|
|||||||
display: inline-flex
|
display: inline-flex
|
||||||
}
|
}
|
||||||
|
|
||||||
//本月摘要标题
|
|
||||||
.month-data-title {
|
.month-data-title {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -110,7 +108,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//投放建议-总体策略
|
|
||||||
.overall-strategy {
|
.overall-strategy {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
padding: 20px 10px 20px 16px;
|
padding: 20px 10px 20px 16px;
|
||||||
@ -126,9 +123,7 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//投放优化每块div小标题
|
|
||||||
.placement-optimization-title {
|
.placement-optimization-title {
|
||||||
// 总体策略
|
|
||||||
color: var(--Text-1, #211F24);
|
color: var(--Text-1, #211F24);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-family: PuHuiTi-Medium;
|
font-family: PuHuiTi-Medium;
|
||||||
@ -147,10 +142,8 @@
|
|||||||
word-wrap: break-word
|
word-wrap: break-word
|
||||||
}
|
}
|
||||||
|
|
||||||
//表现分析标题
|
|
||||||
.player-title {
|
.player-title {
|
||||||
margin: 10px 0px 15px 20px;
|
margin: 10px 0px 15px 20px;
|
||||||
// 表现分析
|
|
||||||
color: var(--Text-1, #211F24);
|
color: var(--Text-1, #211F24);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-family: PuHuiTi-Medium;
|
font-family: PuHuiTi-Medium;
|
||||||
@ -174,3 +167,103 @@
|
|||||||
margin-bottom: 20px
|
margin-bottom: 20px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.guidelines-data-wrap {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.filter-wrap {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e6e6e8;
|
||||||
|
|
||||||
|
:deep(.arco-tabs) {
|
||||||
|
.arco-tabs-tab {
|
||||||
|
height: 56px;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-btn) {
|
||||||
|
.arco-btn-icon {
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top {
|
||||||
|
.title {
|
||||||
|
font-family: 'PuHuiTi-Medium';
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.overview-row {
|
||||||
|
.overview-item {
|
||||||
|
height: 88px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--BG-100, #f7f8fa);
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-wrap {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.pagination-box {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 24px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-box {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 24px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.arco-pagination {
|
||||||
|
.arco-pagination-list {
|
||||||
|
.arco-pagination-item {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--BG-300, #e6e6e8);
|
||||||
|
|
||||||
|
&.arco-pagination-item-ellipsis {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.arco-pagination-item-active {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid var(--Brand-Brand-6, #6d4cfe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-pagination-jumper-prepend {
|
||||||
|
color: var(--Text-2, #3c4043);
|
||||||
|
text-align: right;
|
||||||
|
font-family: 'PuHuiTi-Medium';
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px; /* 157.143% */
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-select-view-single,
|
||||||
|
.arco-pagination-jumper-input {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--BG-300, #e6e6e8);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user