Files
lingji-work-fe/src/views/property-marketing/put-account/investment-guidelines/index.vue

282 lines
7.8 KiB
Vue
Raw Normal View History

<template>
<div class="guidelines-data-wrap">
<div class="part-div">
<div>
<a-tabs
v-model:activeKey="tabData"
@tab-click="onSearch"
class="a-tab-class ignore-export"
default-active-key="placement_guide"
>
<a-tab-pane key="placement_guide" title="投放指南"></a-tab-pane>
<a-tab-pane key="guide_history">
<template #title>历史指南列表</template>
</a-tab-pane>
</a-tabs>
</div>
<!--表单组件搜索-->
<listSearchForm
class="ignore-export"
@onReset="handleReset"
v-model:query="query"
@onSearch="onSearch"
:disabled="loading"
></listSearchForm>
<component
:is="currentComponent"
:listData="tabData === 'placement_guide' ? placementGuideList : guideHistoryList"
@onSearch="onSearch"
@updateQuery="handleUpdateQuery"
/>
<div v-if="listData.total > 0" class="pagination-box flex justify-end ignore-export">
<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>
<a-spin
v-show="tabData === 'placement_guide'"
:loading="loading"
tip="AI分析中...."
wrapperClassName="custom-spin-wrapper"
>
<div>
<MonthData :overview="aiResult.overview"></MonthData>
<!-- 投放建议-->
<PlacementSuggestions :optimization="aiResult.optimization"></PlacementSuggestions>
<!-- 投放行动指南-->
<!-- <ActionGuideDistribution :action_guide="aiResult.action_guide"></ActionGuideDistribution>-->
</div>
</a-spin>
<div v-if="tabData == 'placement_guide'" class="ignore-export">
<a-space class="down-btn">
<a-button type="outline" :loading="exportLoading" @click="downPage">
<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 PlacementGuideList from './components/table-data/placementGuideList.vue';
import listSearchForm from './components/table-data/listSearchForm.vue';
import GuideListHistory from './components/table-data/guideListHistory.vue';
import MonthData from './components/month-data/index.vue';
import PlacementSuggestions from './components/placement-suggestions/index.vue';
2025-07-04 10:35:16 +08:00
import {
getAiResult,
getPlacementGuide,
getPlacementGuideHistory,
savePlacementGuide,
2025-07-04 10:35:16 +08:00
} from '@/api/all/propertyMarketing';
import { Message } from '@arco-design/web-vue';
import { AiResultStatus } from '@/views/property-marketing/put-account/investment-guidelines/constants';
import { uploadPdf } from '@/views/property-marketing/put-account/investment-guidelines/constants';
const tabData = ref('placement_guide');
2025-07-04 10:35:16 +08:00
const query = reactive({
platform: '',
account_name: '',
plan: '',
date_time: [],
sort_column: '',
sort_order: '',
page_size: 20,
page: 1,
});
2025-07-04 10:35:16 +08:00
const currentComponent = computed(() => {
return tabData.value === 'placement_guide' ? PlacementGuideList : GuideListHistory;
});
const onPageChange = (current) => {
query.page = current;
onSearch();
};
const onPageSizeChange = (pageSize) => {
query.page_size = pageSize;
onSearch();
};
const isGetAi = ref(true); // 是否获取AI数据
const handleUpdateQuery = (payload) => {
payload.order = payload.order === 'ascend' ? 'asc' : 'desc';
query.sort_column = payload.column;
query.sort_order = payload.order;
isGetAi.value = false;
loading.value = false;
onSearch();
};
const loading = ref(false);
const exportLoading = ref(false);
const listData = reactive({
total: 0,
list: [],
2025-07-04 10:35:16 +08:00
});
const placementGuideList = ref([]); // 投放指南数据
const guideHistoryList = ref([]); // 历史投放指南数据
2025-07-04 10:35:16 +08:00
const onSearch = async () => {
let result;
if (tabData.value === 'placement_guide') {
result = await getPlacementGuide(query);
placementGuideList.value = result?.data?.data || [];
} else {
result = await getPlacementGuideHistory(query);
guideHistoryList.value = result?.data?.data || [];
}
listData.total = result.data.total;
if (placementGuideList.value.length > 0 && isGetAi.value) {
loading.value = true;
syncGetAiResult();
startTask();
2025-07-04 10:35:16 +08:00
}
isGetAi.value = true;
2025-07-04 10:35:16 +08:00
};
const aiResult = reactive({
optimization: [], // 投放建议优化
action_guide: [], // 新投放建议生成
overview: [], // 新投放建议生成
});
// 下载当前页面
const downPage = async () => {
try {
let fileUrl = saveForm.file_url;
exportLoading.value = true;
if (saveForm.file_url === '') {
fileUrl = await uploadPdf('投放指南.pdf', '.guidelines-data-wrap');
saveForm.file_url = fileUrl;
}
console.log(fileUrl, 'fileUrl');
const link = document.createElement('a');
link.href = fileUrl;
link.download = '投放指南.pdf';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
exportLoading.value = false;
} catch (error) {
Message.error(error.message);
exportLoading.value = false;
}
};
const saveForm = reactive({
account: [],
plan: [],
platform: [],
aiResult: [],
code: '',
file_url: '',
});
const timerRef = ref<number | null>(null);
const startTask = () => {
if (timerRef.value !== null) return;
timerRef.value = setInterval(async () => {
syncGetAiResult();
}, 5000);
};
const syncGetAiResult = async () => {
try {
const { code, data } = await getAiResult(query);
saveForm.file_url = '';
console.log('定时任务执行结果:', data);
if (data.ai_result_status === AiResultStatus.SUCCESS || data.ai_result_status === AiResultStatus.FAILED) {
stopTask();
console.log('任务已完成,定时器已关闭');
2025-07-04 10:35:16 +08:00
}
if (data.ai_result_status === AiResultStatus.SUCCESS) {
loading.value = false;
aiResult.optimization = data.result?.optimization?.modules || [];
aiResult.action_guide = data.result?.action_guide?.modules || [];
aiResult.overview = data.result?.overview?.content_blocks[0] || [];
} else if (data.ai_result_status === AiResultStatus.FAILED) {
Message.error('AI分析失败');
aiError();
}
saveForm.code = data?.code;
} catch (error) {
aiError();
}
};
// ai 检测失败执行方法
const aiError = () => {
aiResult.optimization = [];
aiResult.action_guide = [];
aiResult.overview = [];
stopTask();
};
const handleReset = () => {
console.log('handleReset');
query.page = 1;
query.page_size = 20;
query.account_name = '';
query.platform = '';
query.sort_column = '';
query.sort_order = '';
query.platform = '';
query.date_time = [];
onSearch();
};
const stopTask = () => {
loading.value = false;
if (timerRef.value !== null) {
clearInterval(timerRef.value); // 清除定时器
timerRef.value = null; // 重置引用
console.log('定时器已停止');
}
};
onUnmounted(() => {
stopTask();
});
const handleSave = async () => {
await uploadPdf();
const updatedSaveForm = {
...saveForm,
ai_result: aiResult,
};
const { code, message, data } = await savePlacementGuide(updatedSaveForm);
if (code === 200) {
Message.success(message);
2025-07-04 10:35:16 +08:00
}
};
onMounted(() => {
onSearch();
});
</script>
<style lang="scss">
@import './style.scss';
.custom-spin-wrapper {
display: block;
width: 100%;
}
</style>