From 41873335d5755695ab8c4fe553f64786a9433411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=BF=97=E5=86=9B?= <543024265@qq.com> Date: Wed, 9 Jul 2025 15:15:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(property-marketing):=20=E6=96=B0=E5=A2=9EP?= =?UTF-8?q?DF=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8A=95=E6=94=BE=E6=8C=87=E5=8D=97=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/unplugin/auto-import.ts | 2 +- src/components/upload/ImageUpload.vue | 2 - .../components/month-data/index.vue | 4 +- .../placement-suggestions/index.vue | 52 +++++++++-- .../table-data/placementGuideList.vue | 8 +- .../investment-guidelines/constants.ts | 50 +++++++++++ .../investment-guidelines/detail.vue | 38 +++++++- .../investment-guidelines/index.vue | 87 ++++++------------- 8 files changed, 162 insertions(+), 81 deletions(-) diff --git a/config/unplugin/auto-import.ts b/config/unplugin/auto-import.ts index 1036483..a6244c8 100644 --- a/config/unplugin/auto-import.ts +++ b/config/unplugin/auto-import.ts @@ -21,7 +21,7 @@ export function configAutoImport() { '@vueuse/core', { dayjs: [['default', 'dayjs']], - 'lodash-es': ['cloneDeep', 'omit', 'pick', 'union', 'isNumber'], + 'lodash-es': ['cloneDeep', 'omit', 'pick', 'union', 'isNumber', 'isEmpty'], '@/hooks': ['useModal'], }, ], diff --git a/src/components/upload/ImageUpload.vue b/src/components/upload/ImageUpload.vue index 0054575..9a0be66 100644 --- a/src/components/upload/ImageUpload.vue +++ b/src/components/upload/ImageUpload.vue @@ -75,7 +75,6 @@ let previousFileListLength = 0; //删除图片 const onChange = (fileList) => { if (fileList.length < previousFileListLength) { - // 在这里执行你需要的操作 if (props.limit === 1) { if (fileList.length === 0) { emit('update:modelValue', ''); @@ -90,7 +89,6 @@ const onChange = (fileList) => { } } - // 更新上一次的文件列表长度 previousFileListLength = fileList.length; }; diff --git a/src/views/property-marketing/put-account/investment-guidelines/components/month-data/index.vue b/src/views/property-marketing/put-account/investment-guidelines/components/month-data/index.vue index b99e439..6a2e1ed 100644 --- a/src/views/property-marketing/put-account/investment-guidelines/components/month-data/index.vue +++ b/src/views/property-marketing/put-account/investment-guidelines/components/month-data/index.vue @@ -1,11 +1,11 @@ @@ -65,17 +73,18 @@ 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'; +import { uploadPdf } from '@/views/property-marketing/put-account/investment-guidelines/constants'; +import { Message } from '@arco-design/web-vue'; const aiResult = reactive({ optimization: [], // 投放建议优化 action_guide: [], // 新投放建议生成 overview: [], // 新投放建议生成 }); - +const fileUrl = ref(''); const detailData = reactive({ created_at: '', account: '', @@ -92,6 +101,27 @@ const getDetail = async () => { } }; +const exportLoading = ref(false); +const downPage = async () => { + try { + let downFileUrl = fileUrl.value; + exportLoading.value = true; + if (downFileUrl === '') { + downFileUrl = await uploadPdf('投放指南.pdf', '.guidelines-data-wrap'); + fileUrl.value = downFileUrl; + } + const link = document.createElement('a'); + link.href = downFileUrl; + 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; + } +}; onMounted(() => { getDetail(); }); diff --git a/src/views/property-marketing/put-account/investment-guidelines/index.vue b/src/views/property-marketing/put-account/investment-guidelines/index.vue index a1f079a..709f2d9 100644 --- a/src/views/property-marketing/put-account/investment-guidelines/index.vue +++ b/src/views/property-marketing/put-account/investment-guidelines/index.vue @@ -10,7 +10,7 @@ > - + @@ -30,7 +30,7 @@ @updateQuery="handleUpdateQuery" /> -
+
- + @@ -84,7 +84,6 @@ 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'; -import ActionGuideDistribution from './components/action-guide-distribution'; import { getAiResult, getPlacementGuide, @@ -92,11 +91,8 @@ import { savePlacementGuide, } from '@/api/all/propertyMarketing'; import { Message } from '@arco-design/web-vue'; -import html2canvas from 'html2canvas'; -import { jsPDF } from 'jspdf'; import { AiResultStatus } from '@/views/property-marketing/put-account/investment-guidelines/constants'; -import { fetchUploadFile } from '@/api/all'; -import axios from 'axios'; +import { uploadPdf } from '@/views/property-marketing/put-account/investment-guidelines/constants'; const tabData = ref('placement_guide'); @@ -133,7 +129,7 @@ const handleUpdateQuery = (payload) => { }; const loading = ref(false); - +const exportLoading = ref(false); const listData = reactive({ total: 0, list: [], @@ -166,15 +162,27 @@ const aiResult = reactive({ // 下载当前页面 const downPage = async () => { - await nextTick(); - const fileUrl = await uploadPdf(); - const link = document.createElement('a'); - link.href = fileUrl; - link.download = '投放指南.pdf'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); + 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: [], @@ -258,51 +266,6 @@ const handleSave = async () => { } }; -// 上传pdf文件 -const uploadPdf = async () => { - if (saveForm.file_url !== '') { - return saveForm.file_url; - } - const response = await fetchUploadFile({ suffix: 'pdf' }); - const preSignedUrl = response?.data?.upload_url; - const fileUrl = response?.data?.file_url; - if (!preSignedUrl) { - throw new Error('未能获取有效的预签名上传地址'); - } - saveForm.file_url = fileUrl; - const pdfBlob = await generatePDF(); // 生成 PDF Blob - console.log('pdfBlob', pdfBlob); - await axios.put(preSignedUrl, pdfBlob, { - headers: { - 'Content-Type': pdfBlob.type, - }, - }); - return fileUrl; -}; - -const generatePDF = async (): Promise => { - await nextTick(); - const sections = document.querySelectorAll('.guidelines-data-wrap'); - const pdf = new jsPDF('p', 'mm', 'a4'); - let position = 0; - for (const section of sections) { - if (section.children.length === 0) continue; // 跳过空内容区域 - const canvas = await html2canvas(section as HTMLElement, { - ignoreElements: (element) => { - return element.classList.contains('ignore-export'); // 例如:忽略 class 为 ignore-export 的元素 - }, - }); - const imgData = canvas.toDataURL('image/png'); - const imgProps = pdf.getImageProperties(imgData); - const pdfWidth = pdf.internal.pageSize.getWidth(); - const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; - pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, pdfHeight); - position += pdfHeight + 10; - } - - return pdf.output('blob'); -}; - onMounted(() => { onSearch(); });