Преглед на файлове

Merge branch 'ETA1.4.9'

cxmo преди 1 година
родител
ревизия
f2d8e071ac
променени са 3 файла, в които са добавени 185 реда и са изтрити 6 реда
  1. 5 2
      src/views/ppt/hooks/createPPTContent.js
  2. 81 4
      src/views/ppt/hooks/usePPTPublish.js
  3. 99 0
      src/views/ppt/template/CustomCover.vue

+ 5 - 2
src/views/ppt/hooks/createPPTContent.js

@@ -3,6 +3,7 @@ import {formatPPTDate} from '../utils/index'
 import {bgList} from '../utils/config'
 import {ref} from 'vue'
 import Cover from '../template/Cover.vue'
+import CustomCover from '../template/CustomCover.vue'
 import Footer from '../template/Footer.vue'
 import FormatOne from '../template/FormatOne.vue'
 import FormatTwo from '../template/FormatTwo.vue'
@@ -59,7 +60,8 @@ export function createPPTContent(params){
         TemplateType,
         ReportId,
         ModifyTime,
-        PublishTime
+        PublishTime,
+        CoverContent
     }=params
 
     let arr=[]//ppt内容数组
@@ -75,6 +77,7 @@ export function createPPTContent(params){
         imgLocalUrl:bgList[lang][TemplateType-1],
         modelId:0,
         id:0,
+        CoverContent
     }
     arr.push(coverPageData)
 
@@ -101,7 +104,7 @@ export function createPPTContent(params){
  */
 export function getTemplate(modelId){
     const modelMap=new Map([
-        [0,Cover],
+        [0,CustomCover],
         [1,FormatOne],
         [2,FormatTwo],
         [3,FormatThree],

+ 81 - 4
src/views/ppt/hooks/usePPTPublish.js

@@ -7,6 +7,7 @@ import { parse } from "himalaya";
 import _ from 'lodash'
 import {pptLayout,pptSlideMaster,pptSlideMasterEn,modelConfig} from '../utils/config'
 import {useUploadFileToOSS,useUploadToMinIO} from '@/hooks/useUploadFileToOSS'
+import {getPPTConfig} from './createPPTContent'
 import {usePublicSettingStore} from '@/store/modules/publicSetting'
 import moment from 'moment'
 
@@ -55,6 +56,78 @@ function PPTInit(pptx,LayoutType,lang='ch'){
     pptx.defineSlideMaster(sliderMaster)
     return pptx
 }
+/**
+ * ppt配置化后 init ppt
+ * @param pptx ppt插件实例
+ * @param LayoutType ppt版式 1-10:7,2-16:9,3-4:3
+ * @param lang 
+ */
+function pptConfigInit(pptx,LayoutType,lang='ch'){
+    let layout = pptLayout
+    let sliderMaster = lang==='ch'?pptSlideMaster:pptSlideMasterEn
+    //将背景图替换成基本配置图
+    const pptBgImg = getPPTConfig().pptBgImage||"/pptImg/pptitem_bg.png"
+    sliderMaster.objects[1] = {image: {x:0,y:0,w:10,h:lang==='ch'?7:7+0.1,path:pptBgImg}}
+    //如果布局不是10:7 背景图、页码需要做位置调整
+    if(LayoutType!==1){
+        layout = { name: "myppt", width: 10, height: LayoutType===2?5.625:7.5 }
+        const y = lang==='ch'?0:-0.1
+        const h = LayoutType===2?5.625:7.5
+        sliderMaster.objects[1] = {image: {x:0,y:y,w:10,h:lang==='ch'?h:h+0.1,path:pptBgImg}}
+        sliderMaster.slideNumber = {x:'95%',y:LayoutType===2?'92%':'95%',fontSize:12}
+    }
+    pptx.defineLayout(layout)
+    pptx.layout = layout.name
+    pptx.defineSlideMaster(sliderMaster)
+    return pptx
+}
+//配置自定义封面内容
+function setPPTCover(cover,pptCoverContent='',title=''){
+    let contentList = []
+    try{
+        contentList = JSON.parse(pptCoverContent)
+    }catch(e){
+        contentList=[]
+    }
+    //将contentList的内容通过addText写入,方法与图层写入文字一致
+    for(let i=0;i<contentList.length;i++){
+        const {
+            percentageTop,
+            percentageLeft,
+            percentageWidth,
+            percentageHeight,
+            richContent
+        } = contentList[i]
+        const position = {
+            x:percentageLeft*100+'%',
+            y:percentageTop*100+'%',
+            w:percentageWidth*100+'%',
+            h:percentageHeight*100+'%'
+        }
+        let textData = toTextProps(toJson(richContent))
+        cover.addText(textData,{
+            ...position,
+            margin:10,
+            fontSize:16*0.75,
+            valign:'top'
+        })
+    }
+    //若contentList为空,则在右下的位置显示标题
+    if(!contentList.length){
+        cover.addText(
+            [{text:title,options:{fontSize:28*0.75,breakLine:true}}],
+            {
+                x:'38%',
+                y:'50%',
+                w:'60%',
+                h:'28%',
+                color:'333333',
+                align:'center',
+                fontFace:'SimHei'
+            })
+    }
+    return cover
+}
 
 // svg转base64图片,参考:https://github.com/scriptex/svg64
 const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
@@ -458,7 +531,8 @@ async function handleUploadToMinIO(data){
 
 // 页面转ppt
 async function pageToPPT(){
-    const PPTINS=PPTInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch')
+    //const PPTINS=PPTInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch')
+    const PPTINS = pptConfigInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch')
     PPTINS.addSlide()
 
     // ppt正文内容
@@ -609,7 +683,8 @@ async function pageToPPT(){
 
     //为了把封面放到第一页,操作pptx.slides达不成想要的效果,于是弄了个pptx2
     //将封面放在最后生成是因为htmlToCanvans占用太多内存会导致页面假死
-    let pptx2 = PPTInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch');
+    //let pptx2 = PPTInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch');
+    let pptx2 = pptConfigInit(new pptxgen(),1,window.location.pathname.startsWith('/ppten')?'en':'ch')
     //添加封面
     let cover = pptx2.addSlide()
     let coverImg = $(`#ppt-cover-page .pptbg`)[0].src
@@ -622,7 +697,7 @@ async function pageToPPT(){
         size: { type: "contain" },
     })
     //生成的ppt需要可以在封面页更改标题和类型,所以封面信息手动写入
-    const coverInfo = window.location.pathname.startsWith('/ppten')?[
+    /* const coverInfo = window.location.pathname.startsWith('/ppten')?[
         {text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
         {text:PPTContentList[0].Title,options:{fontSize:28*0.75,breakLine:true}},
         {text:`\nHORIZON INSIGHTS PTE. LTD.`,options:{fontSize:16*0.75,breakLine:true}},
@@ -646,7 +721,9 @@ async function pageToPPT(){
         color:'ffffff',
         align:'center',
         fontFace:'SimHei'
-    })
+    }) */
+    //自定义封面页内容
+    cover = setPPTCover(cover,PPTContentList[0].CoverContent,PPTContentList[0].Title)
     //遍历pptx.slides,重新给每一项的部分属性赋值,再推入pptx2.slides中
     //第一页不需要,因为是空白的
     for(let i=1;i<PPTINS.slides.length;i++){

+ 99 - 0
src/views/ppt/template/CustomCover.vue

@@ -0,0 +1,99 @@
+<script setup>
+import { ref, watch } from "vue";
+const props = defineProps({
+  pageData: {
+    type: Object,
+    default: {},
+  }
+});
+let coverList = ref([])
+function setCoverContent(){
+    try{
+        coverList.value = JSON.parse(props.pageData.CoverContent)
+    }catch(e){
+        coverList.value = []
+    }
+}
+setCoverContent()
+
+watch(
+    ()=>props.CoverContent,
+    ()=>{
+        setCoverContent()
+    },
+)
+</script>
+
+<template>
+    <!-- 自定义封面页渲染 -->
+    <div class="cover-new-wrap ppt-item-box" id="ppt-cover-page">
+        <!-- 封面图 -->
+        <img :src="pageData.BackgroundImg||''" class="cover-img pptbg" style="object-fit: fill !important;">
+        <!-- 自定义文本 -->
+        <div v-for="el in coverList" :key="el.id"
+            class="cover-el el-text" :id="`cover-el-${el.id}`" :style="{
+            top: el.percentageTop*100 + '%',
+            left: el.percentageLeft*100 + '%',
+            width: el.percentageWidth*100 + '%',
+            height: el.percentageHeight*100 + '%',
+            pointerEvents:'none'
+        }" >
+            <div class="layer-editor-wrap">
+                <div style="width:100%;height:100%;" :id="`${el.id}-editorDom`">
+                        <div class="editor-content" :style="{width:el.width+'px'}" v-html="el.richContent"></div>
+                </div>
+            </div>
+        </div>
+        <!-- 如果没有自定义文本,则在右下的位置显示标题 -->
+        <div class="cover-el default" v-if="!coverList.length">
+            <div class="editor-content"><p style="font-size:28px;">{{ pageData.Title }}</p></div>
+        </div>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.cover-new-wrap{
+    position:relative;
+    .cover-img{
+        width: 100%;
+        height: 100%;
+    }
+    .cover-el{
+        position: absolute;
+        .layer-editor-wrap {
+            z-index: 2;
+            width: 100%;
+            height: 100%;
+            /* padding: 10px; */
+            box-sizing: border-box;
+            position: relative;
+            >div {
+                cursor: pointer;
+            }
+            .editor-content {
+                padding: 10px;
+                position: absolute;
+                transform-origin: 0 0;
+                word-wrap: break-word;
+                ul {
+                    margin-left: 1em;
+                    list-style-type: disc;
+                }
+
+                ol {
+                    margin-left: 1em;
+                    list-style-type: decimal;
+                }
+            }
+        }
+        &.default{
+            width:62%; 
+            font-size:16px; 
+            text-align:center; 
+            line-height:1.6;
+            right:20px; 
+            top:50%;
+        }
+    }
+}
+</style>