Преглед изворни кода

Merge branch 'demand-199-copy'

cxmo пре 5 месеци
родитељ
комит
070a748873
26 измењених фајлова са 700 додато и 231 уклоњено
  1. 20 0
      src/lang/modules/Slides/pptPresent.js
  2. 3 0
      src/views/ppt_manage/mixins/layerMixins.js
  3. 91 0
      src/views/ppt_manage/mixins/pptEditorMixins.js
  4. 28 0
      src/views/ppt_manage/mixins/pptMixins.js
  5. 1 0
      src/views/ppt_manage/mixins/virtualScrollMixins.js
  6. 5 1
      src/views/ppt_manage/newVersion/components/IndexItem.vue
  7. 1 0
      src/views/ppt_manage/newVersion/components/TextEditor.vue
  8. 14 2
      src/views/ppt_manage/newVersion/components/catalog/pptContent.vue
  9. 14 2
      src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue
  10. 2 2
      src/views/ppt_manage/newVersion/components/editor/InsertPageDialog.vue
  11. 128 0
      src/views/ppt_manage/newVersion/components/editor/TitleEditorTool.vue
  12. 3 20
      src/views/ppt_manage/newVersion/components/editor/chooseCover/TextEl.vue
  13. 2 55
      src/views/ppt_manage/newVersion/components/formatEl/TextEl.vue
  14. 9 4
      src/views/ppt_manage/newVersion/components/formatPage/mixins.js
  15. 3 22
      src/views/ppt_manage/newVersion/components/layer/Element/TextShape.vue
  16. 90 0
      src/views/ppt_manage/newVersion/css/common.scss
  17. 4 4
      src/views/ppt_manage/newVersion/pptCatalog.vue
  18. 56 49
      src/views/ppt_manage/newVersion/pptEditor.vue
  19. 4 3
      src/views/ppt_manage/newVersion/pptEnCatalog.vue
  20. 57 47
      src/views/ppt_manage/newVersion/pptEnEditor.vue
  21. 28 2
      src/views/ppt_manage/newVersion/pptEnPresent.vue
  22. 19 5
      src/views/ppt_manage/newVersion/pptEnPublish.vue
  23. 26 2
      src/views/ppt_manage/newVersion/pptPresent.vue
  24. 19 11
      src/views/ppt_manage/newVersion/pptPublish.vue
  25. 65 0
      src/views/ppt_manage/newVersion/utils/tinymceSetting.js
  26. 8 0
      src/views/ppt_manage/newVersion/utils/untils.js

+ 20 - 0
src/lang/modules/Slides/pptPresent.js

@@ -91,6 +91,16 @@ export const presentEn = {
   table_chart: "Chart",
   is_incomplete_please_edit:'Slide {num} content is incomplete, please re-edit!',
   publishing_loading:'Publishing',
+
+  page_title_style_setting:'Title Style Setting',
+  title_location_settings:'Location Settings',
+  title_location_up_down:'up and down',
+  title_location_left_right:'left and right',
+  title_size_settings:'Size Settings',
+  title_size_width:'width',
+  title_size_height:'height',
+  title_content_settings:'Content Settings',
+  apply_to_the_entire:'Apply to the entire PPT'
 };
 
 /* 中文 */
@@ -182,6 +192,16 @@ export const presentZh = {
   previous_sheet_default: "上一张",
   is_incomplete_please_edit:'第{num}页内容不完整,请重新编辑!',
   publishing_loading:'发布中...',
+
+  page_title_style_setting:'标题编辑模式',
+  title_location_settings:'位置设置',
+  title_location_up_down:'上下',
+  title_location_left_right:'左右',
+  title_size_settings:'大小设置',
+  title_size_width:'宽度',
+  title_size_height:'高度',
+  title_content_settings:'内容设置',
+  apply_to_the_entire:'应用至整个PPT'
 };
 
 /**

+ 3 - 0
src/views/ppt_manage/mixins/layerMixins.js

@@ -31,6 +31,9 @@ export default {
         this.activeLayerEl = {}
       }
       if(this.isEditLayer){
+        //进入图层编辑模式,需要退出其他模式
+        this.isEditTitle = false
+        
         //如果当前活跃图层没有layers,加上
         if(!this.currentItem.layers){
           this.refleshLayerEl([])

+ 91 - 0
src/views/ppt_manage/mixins/pptEditorMixins.js

@@ -25,6 +25,8 @@ export default{
 
       refreshLoading:null,//一键刷新的loading
       refreshBtnLoading:false,//一键刷新的按钮loading
+
+      isEditTitle:false,
     }
   },
   directives: {
@@ -48,6 +50,95 @@ export default{
     },
   },
   methods:{
+    //切换标题编辑模式
+    handleEditTitle(){
+        //判断当前ppt是否添加了页面
+        if(this.pageList.length===0){
+        this.$message.warning(this.$t('Slides.msg_page_at_least_one'))
+        return
+        }
+        this.isEditTitle = !this.isEditTitle
+        if(this.isEditTitle){
+            //进入标题编辑模式,需要退出其他模式
+            this.isEditLayer = false
+            this.activeLayerEl = {}
+            
+            //初始化该页标题的数据
+            if(!this.currentItem.titleDetail){
+                this.currentItem.titleDetail = {top:5.5,left:10,width:68,height:7}
+                this.$set(this.pageList,this.currentIndex,this.currentItem) 
+            }
+            
+            this.$nextTick(()=>{
+                this.$refs.titleEditor.initFlag = true
+                this.$refs.titleEditor.initTitleEditor()
+            })
+        }
+    },
+    //获取标题内容
+    handleTextChange({val,richContent}){
+        this.currentItem.title = richContent/* val */
+        this.$set(this.pageList,this.currentIndex,this.currentItem) 
+    },
+    //获取标题样式 需要存一份px单位
+    handleTitelStyleChange({top,left,width,height}){
+        const baseWidth = 900
+        const baseHeight = 630
+        this.currentItem.titleDetail = {
+            top,left,width,height,
+            baseTop:baseHeight*top/100,//px单位,基准为编辑页的ppt大小
+            baseLeft:baseWidth*left/100,
+            baseWidth:baseWidth*width/100,
+            baseHeight:baseHeight*height/100
+        }
+        this.$set(this.pageList,this.currentIndex,this.currentItem) 
+    },
+    //全局改变标题位置
+    changePositionAll({left,top}){
+        //遍历所有PPT页
+        //替换每一页titleDetail的left top
+        //若width,height没有值,则使用默认的,若有值,则不变
+        const defaultWidth = 900
+        const defaultHeight = 630
+        const defaultWidthPercent = 68
+        const defaultHeightPercent = 7
+        this.pageList.forEach(page=>{
+            const {width='',height='',baseWidth='',baseHeight=''} = page.titleDetail||{}
+            page.titleDetail = {
+                top,left,
+                width:width||defaultWidthPercent,
+                height:height||defaultHeightPercent,
+                baseTop:defaultHeight*top/100,//px单位,基准为编辑页的ppt大小
+                baseLeft:defaultWidth*left/100,
+                baseWidth:baseWidth||defaultWidth*width/100,
+                baseHeight:baseHeight||defaultHeight*height/100
+            }
+        })
+        /* this.$message.success('全局设置成功') */
+    },
+    //全局改变标题宽高
+    changeSizeAll({width,height}){
+        //遍历所有PPT页
+        //替换每一页titleDetail的width height
+        //若left,top没有值,则使用默认的,若有值,则不变
+        const defaultWidth = 900
+        const defaultHeight = 630
+        const defaultLeftPercent = 10
+        const defaultTopPercent = 5.5
+        this.pageList.forEach(page=>{
+            const {top='',left='',baseTop='',baseLeft=''} = page.titleDetail||{}
+            page.titleDetail = {
+                width,height,
+                top:top||defaultTopPercent,
+                left:left||defaultLeftPercent,
+                baseWidth:defaultWidth*width/100,
+                baseHeight:defaultHeight*height/100,
+                baseTop:baseTop||defaultHeight*top/100,
+                baseLeft:baseLeft||defaultWidth*left/100,
+            }
+        })
+        this.$message.success(this.$t('MsgPrompt.set_success_msg'))
+    },
     //显示切换模板弹窗
     handleChangeFormat(item){
       this.choosedItem = item

+ 28 - 0
src/views/ppt_manage/mixins/pptMixins.js

@@ -82,6 +82,34 @@ export default {
     }
   },
   methods: {
+    //配置自定义标题内容
+    setPPTTitle(slide,page){
+        const {titleDetail,title} = page
+        //兼容之前的ppt
+        if(!titleDetail){
+            slide.addText(title, {
+                placeholder:"slideTitle",
+                x:'10%',
+                y:'5.5%',
+                w:'68%',
+                h:'7%',
+                color:'333333'
+              });
+        }else{
+            const {left,top,width,height} = titleDetail
+            const text = toTextProps(toJson(title))
+            slide.addText(text,{
+                /* placeholder:"slideTitle", */ //加上后会走母版slideTitle的设置
+                x:left+'%',
+                y:top+'%',
+                w:width+'%',
+                h:height+'%',
+                color:'333333',
+                fontSize:12
+            })
+        }
+        return slide
+    },
     //配置自定义封面内容
     setPPTCover(cover,pptCoverContent='',title=''){
         let contentList = []

+ 1 - 0
src/views/ppt_manage/mixins/virtualScrollMixins.js

@@ -1,3 +1,4 @@
+//已停用 可删除
 /** 图库9.0(智能PPT) 虚拟列表 */
 import Highcharts from "highcharts/highstock"
 export default {

+ 5 - 1
src/views/ppt_manage/newVersion/components/IndexItem.vue

@@ -5,7 +5,7 @@
         <div class="wrap">
             <div class="item-flex">
                 <div class="item-icon-left"></div>
-                <div class="item-name">{{pageItem.title}}</div> 
+                <div class="item-name">{{getPlainText(pageItem.title)}}</div> 
                 <div class="item-icon-right none">
                   <el-dropdown @command="handleOperateCommand" trigger="click" v-if="showCloseBtn" v-show="!ctrlKeyActive">
                     <span class="el-dropdown-link"> 
@@ -48,6 +48,7 @@
 </template>
 
 <script>
+import {getPlainText} from '@/views/ppt_manage/newVersion/utils/untils';
 export default {
   props:{
     pageItem:{//ppt页
@@ -118,6 +119,9 @@ export default {
       },
       handleOperateCommand(command){
         this.$emit('operatePpt',{type:command.key,pageItem:this.pageItem})
+      },
+      getPlainText(str){
+        return getPlainText(str)
       }
   },
 };

+ 1 - 0
src/views/ppt_manage/newVersion/components/TextEditor.vue

@@ -1,4 +1,5 @@
 <template>
+    <!-- 需求199上线后停用,可删除 -->
   <!-- <div style="width:100%;height:100%">{{content}}</div> -->
   <Editor v-model="content" 
           :init="setting" ref="editor"

+ 14 - 2
src/views/ppt_manage/newVersion/components/catalog/pptContent.vue

@@ -15,11 +15,23 @@
             <img :src="pptBackImage" class="pptbg" />
           </div>
           <div class="ppt-item" v-else :key="item.id">
-              <div class="title-wrap" :title="item.title" 
+              <!-- <div class="title-wrap" :title="item.title" 
                 :style="`${getStrCount(item.title)<58?'':'top:0;height:14%;'}`"
                 :class="{'title-ellipsis':getStrCount(item.title)>172}">
                 {{item.title}}
-              </div>
+              </div> -->
+              <!-- 自定义标题 -->
+              <div class="custom-title-wrap editor-content" 
+                    :style="item.titleDetail?{
+                        left:item.titleDetail.baseLeft+'px',
+                        top:item.titleDetail.baseTop+'px',
+                        width:item.titleDetail.baseWidth+'px',
+                        height:item.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="item.title"></div>
+                </div>
               <component  :is="getComponentName(item.modelId)"
                           :ref="`pptPage_${index-1}`"
                           :pageIndex="index-1"

+ 14 - 2
src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue

@@ -14,11 +14,23 @@
             <img :src="pptBackImage" class="pptbg" style="width:100%;height:100%;object-fit: fill !important;"/>
           </div>
           <div class="ppt-item" v-else :key="item.id">
-              <div class="title-wrap" :title="item.title" 
+              <!-- <div class="title-wrap" :title="item.title" 
                 :style="`${getStrCount(item.title)<52?'top:4.5%;left:8%;width:62%;':'top:0;left:8%;width:62%;height:14%;'}`"
                 :class="{'title-ellipsis':getStrCount(item.title)>150}">
                 {{item.title}}
-              </div>
+              </div> -->
+              <!-- 自定义标题 -->
+              <div class="custom-title-wrap editor-content" 
+                    :style="item.titleDetail?{
+                        left:item.titleDetail.baseLeft+'px',
+                        top:item.titleDetail.baseTop+'px',
+                        width:item.titleDetail.baseWidth+'px',
+                        height:item.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="item.title"></div>
+                </div>
               <component  :is="getComponentName(item.modelId)"
                           :ref="`pptPage_${index-1}`"
                           :pageIndex="index-1"

+ 2 - 2
src/views/ppt_manage/newVersion/components/editor/InsertPageDialog.vue

@@ -77,7 +77,7 @@
 <script>
 import {pptInterface } from "@/api/api.js";
 import {pptEnInterface} from '@/api/modules/pptEnApi.js';
-import {changeCatalogArr} from '@/views/ppt_manage/newVersion/utils/untils';
+import {changeCatalogArr,getPlainText} from '@/views/ppt_manage/newVersion/utils/untils';
 export default {
   props:{
     insertPageShow:{
@@ -185,7 +185,7 @@ export default {
       data.forEach((item,index)=>{
         let temp = {}
         temp.key = index
-        temp.label = `${this.$i18n.locale == 'zh' ?`第${index+1}页`:` Slide${index+1}`} ${item.title||this.$t('Slides.untitled_title')}`
+        temp.label = `${this.$i18n.locale == 'zh' ?`第${index+1}页`:` Slide${index+1}`} ${getPlainText(item.title||this.$t('Slides.untitled_title'))}`
         temp.disabled = false
         list.push(temp)
       })

+ 128 - 0
src/views/ppt_manage/newVersion/components/editor/TitleEditorTool.vue

@@ -0,0 +1,128 @@
+<template>
+    <div class="title-editor-tool-wrap">
+        <el-collapse v-model="activeNames" class="tool-list">
+            <!-- 位置设置 -->
+            <el-collapse-item :title="$t('Slides.title_location_settings')" name="position">
+                <div>
+                    <!-- 上下 -->
+                    <span class="demonstration">{{$t('Slides.title_location_up_down')}}(%)</span>
+                    <el-slider v-model="detail.top" :max="12"></el-slider>
+                </div>
+                <div>
+                    <!-- 左右 -->
+                    <span class="demonstration">{{$t('Slides.title_location_left_right')}}(%)</span>
+                    <el-slider v-model="detail.left"></el-slider>
+                </div>
+                <!-- <el-button type="text" @click="changePosition">应用至整个PPT</el-button> -->
+            </el-collapse-item>
+            <!-- 大小设置 -->
+            <el-collapse-item :title="$t('Slides.title_size_settings')" name="size">
+                <div>
+                    <!-- 宽度 -->
+                    <span class="demonstration">{{$t('Slides.title_size_width')}}(%)</span>
+                    <el-slider v-model="detail.width" :max="100 - detail.left"></el-slider>
+                </div>
+                <div>
+                    <!-- 高度 -->
+                    <span class="demonstration">{{$t('Slides.title_size_height')}}(%)</span>
+                    <el-slider v-model="detail.height" :max="14-detail.top"></el-slider>
+                </div>
+                <!-- 应用至整个PPT -->
+                <el-button type="text" @click="changeSize">{{$t('Slides.apply_to_the_entire')}}</el-button>
+            </el-collapse-item>
+            <el-collapse-item :title="$t('Slides.title_content_settings')" name="content">
+                <div class="editor-tool"></div>
+                <div class="editor" id="editorDom">
+                    <Editor v-model="content" 
+                        :init="setting" 
+                        ref="editor"/>
+                </div>
+            </el-collapse-item>
+        </el-collapse>
+    </div>
+</template>
+
+<script>
+import tinymce from "tinymce";
+import Editor from "@tinymce/tinymce-vue";
+import "tinymce/themes/silver";
+import "tinymce/plugins/lists"; //列表插件
+import "tinymce/plugins/quickbars"; //快速栏插件
+import "tinymce/plugins/fullscreen"; //全屏插件
+import "tinymce/plugins/paste"; //黏贴插件
+import "tinymce/icons/default/icons";
+import {setting} from '../../utils/tinymceSetting'
+export default {
+    components:{Editor},
+    props:{
+        currentItem:{
+            type:Object,
+        }
+    },
+    data() {
+        return {
+            activeNames:'content',
+            content:'&*^%', //若设置为空,则init时没有标题就不会触发watch,随便设置几个字符即可
+            detail:{
+                left:0,top:0,width:0,height:0,
+            },
+            initFlag:false,
+            setting:{
+                ...setting,
+                language: "zh_CN",
+                language_url: require("../../utils/zh_CN.js"),
+                select:'#editorDom',//将编辑器渲染至该dom
+                fixed_toolbar_container: ".editor-tool",//将toolbar渲染至该dom
+                toolbar_persist:true,//是否一直显示toolbar
+                placeholder:this.$t('Slides.click_input_text_content'),
+            },
+        };
+    },
+    watch:{
+        content(con){
+            if(this.initFlag){
+                this.initFlag = false
+                return
+            }
+            const { elementId } = this.$refs.editor;
+            let richContent = tinymce.editors[elementId].getContent();
+            let val = tinymce.editors[elementId].getContent({ format: "text" });
+            this.$emit("textChange", { val, richContent });
+        },
+        detail:{
+            handler(newval){
+                //若init还未执行完成,不派发事件
+                if(this.initFlag) return
+                this.$emit("styleChange",newval)
+            },
+            deep:true
+        },
+    },
+    methods: {
+        initTitleEditor(){
+            const {left,top,width,height} = this.currentItem.titleDetail
+            this.detail = {left,top,width,height}
+            this.content = this.currentItem.title
+        },
+        changePosition(){
+            const {left,top} = this.detail
+            this.$emit('changePositionAll',{top,left})
+        },
+        changeSize(){
+            this.changePosition()
+            const {width,height} = this.detail
+            this.$emit('changeSizeAll',{width,height})
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.title-editor-tool-wrap{
+    #editorDom{
+        min-height: 200px;
+        border:1px solid #ccc;
+        border-top: none;
+    }
+}
+</style>

+ 3 - 20
src/views/ppt_manage/newVersion/components/editor/chooseCover/TextEl.vue

@@ -46,6 +46,7 @@
         BaseTextShape
     } from '@/views/ppt_manage/newVersion/utils/config';
     import elMixin from './elMixin';
+    import tinymce from "tinymce";
     import Editor from "@tinymce/tinymce-vue";
     import "tinymce/themes/silver";
     import "tinymce/plugins/lists"; //列表插件
@@ -53,6 +54,7 @@
     import "tinymce/plugins/fullscreen"; //全屏插件
     import "tinymce/plugins/paste"; //黏贴插件
     import "tinymce/icons/default/icons";
+    import {setting} from '@/views/ppt_manage/newVersion/utils/tinymceSetting'
     export default {
         mixins: [elMixin],
         props: {
@@ -77,33 +79,14 @@
         data() {
             return {
                 setting: {
+                    ...setting,
                     language: "zh_CN",
                     language_url: require("../../../utils/zh_CN.js"),
-                    menubar: false,
-                    toolbar: [
-                        "indent outdent alignleft aligncenter alignright alignjustify forecolor",
-                        "bold italic underline strikethrough numlist bullist backcolor",
-                        "fontselect fontsizeselect",
-                    ],
-                    quickbars_selection_toolbar: false,
-                    quickbars_insert_toolbar: false,
-                    plugins: "lists quickbars paste",
                     height: 350,
                     inline: true,
                     selector: `#${this.elementInfo.id}-editorDom`,
                     paste_as_text: true,
-                    fontsize_formats: '6px 8px 10px 12px 14px 16px 18px 20px 22px 24px 36px 48px',
-                    font_formats: `微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';
-                        楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;
-                        Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;
-                        Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;
-                        Courier New=courier new,courier;Georgia=georgia,palatino;
-                        Helvetica=helvetica;Impact=impact,chicago;
-                        Webdings=webdings;Wingdings=wingdings`,
                     fixed_toolbar_container: ".cover-text-toolbar", //将toolbar放到指定div上
-                    skin_url: "/static/css",
-                    content_url: "/static/css",
-                    //加placeholder
                     placeholder:this.$t('Slides.click_input_text_content')
                 }
             };

+ 2 - 55
src/views/ppt_manage/newVersion/components/formatEl/TextEl.vue

@@ -43,6 +43,7 @@ import "tinymce/plugins/quickbars"; //快速栏插件
 import "tinymce/plugins/fullscreen"; //全屏插件
 import "tinymce/plugins/paste"; //黏贴插件
 import "tinymce/icons/default/icons";
+import {setting} from '@/views/ppt_manage/newVersion/utils/tinymceSetting'
 export default {
   components:{Editor},
   props:{
@@ -56,36 +57,15 @@ export default {
   data() {
     return {
       setting: {
+        ...setting,
         language: "zh_CN",
         language_url: require("../../utils/zh_CN.js"),
-        menubar: false,
-        toolbar: [
-          "indent outdent alignleft aligncenter alignright alignjustify forecolor",
-          "bold italic underline strikethrough numlist bullist backcolor",
-          "fontselect fontsizeselect",
-        ],
-        quickbars_selection_toolbar:false,  
-        quickbars_insert_toolbar: false,
-        plugins: "lists quickbars paste",
         height: 350,
-        inline: true,
         selector: `#text_${this.index}_${this.position}`,
         paste_as_text: true,
        /*  paste_block_drop: true, 开启后阻止drop事件*/
-        fontsize_formats:'6px 8px 10px 12px 14px 16px 18px 20px 22px 24px 36px 48px',
-        font_formats:`微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';
-                      楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;
-                      Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;
-                      Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;
-                      Courier New=courier new,courier;Georgia=georgia,palatino;
-                      Helvetica=helvetica;Impact=impact,chicago;
-                      Webdings=webdings;Wingdings=wingdings`,
-        /* toolbar_persist:true,//始终显示toolbar */
         fixed_toolbar_container: ".richtext-tool",//将toolbar放到指定div上
-        skin_url: "/static/css",
-        content_url: "/static/css",
         placeholder:this.$t('Slides.click_input_text_content')
-       
       },
       content:'',
       initFlag: false,
@@ -150,38 +130,5 @@ export default {
     left:-10px;
     top:-10px;
   }
-  .mce-content-body {
-    width: 100%;
-    height: 100%;
-    padding: 10px;
-    box-sizing: border-box;
-    font-size: 16px;
-    &:focus-visible{
-      outline: 0;
-    }
-    ul{
-      margin-left: 1em;
-      list-style-type: disc;
-    }
-    ol{
-      margin-left: 1em;
-      list-style-type: decimal;
-    }
-  }
-  .mce-edit-focus{
-    outline: 0;
-  }
-  .tox .tox-tbtn--bespoke .tox-tbtn__select-label{
-    width:4.5em !important;
-  }
-  .tox .tox-tbtn{
-    width:32px;
-  }
-  .tox-menu.tox-swatches-menu.tox-selected-menu{
-    left:185px !important;
-  }
-  .mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before {
-    left:10px !important;
-  }
 }
 </style>

+ 9 - 4
src/views/ppt_manage/newVersion/components/formatPage/mixins.js

@@ -1,7 +1,7 @@
 import {checkClipboard,checkClipboardItems,getTextContentSize} from '../../utils/untils';
 import {defaultPosition} from "../../utils/config";
 import { copyFit } from '@/utils/svgToblob.js';
-import Ediotr from '../TextEditor.vue';
+/* import Ediotr from '../TextEditor.vue'; */
 import BaseShape from '../layer/Element/BaseShape.vue';
 import LineShape from "../layer/Element/LineShape.vue";
 import TextShape from "../layer/Element/TextShape.vue";
@@ -11,7 +11,7 @@ import ImageEl from "../formatEl/ImageEl.vue";
 import SheetEl from "../formatEl/SheetEl.vue";
 export default {
     components: {
-        Ediotr,BaseShape,LineShape,TextShape,ChartEl,TextEl,ImageEl,SheetEl
+        /* Ediotr, */BaseShape,LineShape,TextShape,ChartEl,TextEl,ImageEl,SheetEl
       },
     props: {
         pageIndex: {//当前是第几页
@@ -45,6 +45,10 @@ export default {
           type:Boolean,
           default:false
         },
+        isEditTitle:{//父组件是否是标题编辑模式
+            type:Boolean,
+            default:false
+          },
         activeLayerEl:{//当前页面在图层编辑模式时,选中的图层元素
           type:Object,
         },
@@ -100,8 +104,8 @@ export default {
         },
         //判断遮罩layers是否显示
         isLayerShow(){
-          //在图层编辑模式+是当前ppt+是编辑模式
-          return this.isEditLayer&&this.type==='edit'&&this.choosedId===this.pageItem.id
+          //在图层编辑模式/标题编辑模式+是当前ppt+是编辑模式
+          return (this.isEditLayer||this.isEditTitle)&&this.type==='edit'&&this.choosedId===this.pageItem.id
         },
         //判断该渲染哪个图层组件
         getLayerElName(item){
@@ -117,6 +121,7 @@ export default {
         },
         //切换当前选中的图层元素
         changeActEl(item){
+          if(!this.isEditLayer) return
           this.isClickLayer = false
           //如果该元素已被选中,则什么也不做
           const id = this.activeLayerEl.id

+ 3 - 22
src/views/ppt_manage/newVersion/components/layer/Element/TextShape.vue

@@ -50,6 +50,7 @@
 <script>
 import {BaseTextShape} from '../../../utils/config';
 import shapeMixin from './shapeMixin';
+import tinymce from "tinymce";
 import Editor from "@tinymce/tinymce-vue";
 import "tinymce/themes/silver";
 import "tinymce/plugins/lists"; //列表插件
@@ -57,6 +58,7 @@ import "tinymce/plugins/quickbars"; //快速栏插件
 import "tinymce/plugins/fullscreen"; //全屏插件
 import "tinymce/plugins/paste"; //黏贴插件
 import "tinymce/icons/default/icons";
+import {setting} from '@/views/ppt_manage/newVersion/utils/tinymceSetting'
 export default {
   mixins:[shapeMixin],
   props:{
@@ -71,34 +73,13 @@ export default {
   data() {
     return {
       setting: {
+        ...setting,
         language: "zh_CN",
         language_url: require("../../../utils/zh_CN.js"),
-        menubar: false,
-        toolbar: [
-          "indent outdent alignleft aligncenter alignright alignjustify forecolor",
-          "bold italic underline strikethrough numlist bullist backcolor",
-          "fontselect fontsizeselect",
-        ],
-        quickbars_selection_toolbar:false,  
-        quickbars_insert_toolbar: false,
-        plugins: "lists quickbars paste",
         height: 350,
-        inline: true,
         selector: `#${this.elementInfo.id}-editorDom`,
         paste_as_text: true,
-        fontsize_formats:'6px 8px 10px 12px 14px 16px 18px 20px 22px 24px 36px 48px',
-        font_formats:`微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';
-                      楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;
-                      Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;
-                      Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;
-                      Courier New=courier new,courier;Georgia=georgia,palatino;
-                      Helvetica=helvetica;Impact=impact,chicago;
-                      Webdings=webdings;Wingdings=wingdings`,
-        /* toolbar_persist:true,//始终显示toolbar */
         fixed_toolbar_container: ".layer-text-toolbar",//将toolbar放到指定div上
-        skin_url: "/static/css",
-        content_url: "/static/css",
-        //加placeholder
         placeholder:this.$t('Slides.click_input_text_content')
       }
     };

+ 90 - 0
src/views/ppt_manage/newVersion/css/common.scss

@@ -5,7 +5,52 @@ $titleColor:#333333;
     * {
         box-sizing: border-box;
     }
+    .el-tabs__nav-wrap::after {
+        height: 0;
+    }
+    .el-tabs__item { font-size: 16px; }
 
+    //富文本编辑器样式
+    .mce-content-body{
+        width: 100%;
+        height: 100%;
+        padding: 10px;
+        box-sizing: border-box;
+        font-size: 16px;
+        &:focus-visible{
+            outline: 0;
+        }
+        ul{
+            margin-left: 1em;
+            list-style-type: disc;
+          }
+          ol{
+            margin-left: 1em;
+            list-style-type: decimal;
+          }
+    }
+    .mce-edit-focus{
+        outline: 0;
+    }
+    .mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before {
+        left:10px !important;
+    }
+    .mce-content-body.placeholder-hidden:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before{
+        display: none;
+    }
+    .tox .tox-tbtn--bespoke .tox-tbtn__select-label{
+        width:4.5em !important;
+      }
+    .tox-menu.tox-swatches-menu.tox-selected-menu{
+        left:auto !important;
+        right:0;
+    }
+    .tox{
+        .tox-collection__group{
+            max-height: 200px;
+            overflow-y: auto;
+        }
+    }
     //wrap
     .ppt-page-wrap {
         background-color: #fff;
@@ -48,6 +93,51 @@ $titleColor:#333333;
         -webkit-box-orient:vertical;
         word-break: break-word;
     }
+    .custom-title-wrap{
+        position: absolute;
+        transform-origin: 0 0;
+        &.editor-model{
+            background-color: #99999946;
+        }
+        &.ppt-editor-title{
+            border:1px dashed #999;
+        }
+        .title{
+            width:100%;
+            height:100%;
+            font-size: 16px;
+            ul{
+                margin-left: 1em;
+                list-style-type: disc;
+              }
+              ol{
+                margin-left: 1em;
+                list-style-type: decimal;
+              }
+        }
+        .normal-title{
+            font-size: 16px;
+            word-break: break-all;
+        }
+    }
+    .ppt-tool{
+        .layer-edit-box,.title-edit-box{
+          .tool-list{
+            border:none;
+            .el-collapse-item:first-child{
+                .el-collapse-item__content{
+                    padding-bottom: 5px;
+                }
+            }
+            .el-collapse-item__header{
+              margin-bottom: 0;
+            }
+            .el-collapse-item__wrap{
+              overflow: visible;
+            }
+          }
+        }
+      }
 
     .hint-text {
         text-align: center;

+ 4 - 4
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -569,14 +569,14 @@ export default {
         this.$nextTick(()=>{
            //选中节点
           this.$refs[`${this.treeName}Tree`].setCurrentKey(item.nodeKeyId)
-          //展开该节点的父节点
+          //找到该节点的父节点,展开,获取父节点id
           const node = this.$refs[`${this.treeName}Tree`].getCurrentNode()
           !this[`${this.treeName}ExpandKeys`].includes(node.catalogId)&&this[`${this.treeName}ExpandKeys`].push(node.catalogId)
+          this.pptItem.catalogId = node.catalogId||''
           this.selectNode = item
         })
       }else{
         //获取目录下的ppt列表:getCatalogListByGroupId/getCatalogListByAdminId
-
         const res = this.treeName==='public' 
           ? await pptInterface.getCatalogListByAdminId({ AdminId:item.AdminId||''})
           : this.treeName==='private'
@@ -771,13 +771,13 @@ export default {
             this.$refs[`${this.treeName}Tree`].setCurrentKey(data.catalogId)
             //删除的是公共目录下,某目录的最后一个PPT时,该公共目录会消失
             if(this.treeName==='public'&&catalog.PptList.length>1){
-              this.changeModel('list',catalog)
+              this.changeModel('list',catalog||{})
             }else if(this.treeName==='public'&&catalog.PptList.length===1){
               this.changeModel('list',{})
             }
             //但是私有目录不会
             if(this.treeName==='private'){
-              this.changeModel('list',catalog)
+              this.changeModel('list',catalog||{})
             }
           }
         })

+ 56 - 49
src/views/ppt_manage/newVersion/pptEditor.vue

@@ -56,8 +56,25 @@
                         v-loading="item.isUpdating" :element-loading-text="$t('Slides.updating_chart_loading')"
                         @click="changeCurrentItem(item)">
                         <!-- 标题 -->
-                        <div class="title-wrap">
-                            <input type="text" :placeholder="$t('Slides.click_to_input_title')" v-model="item.title"/> 
+                        <!-- <div class="title-wrap" style="background-color: #999999;">
+                            <input type="text" placeholder="单击输入标题" v-model="item.title"/> 
+                        </div> -->
+                        <!-- 自定义标题 -->
+                        <div @click.stop="handleEditTitle"
+                            :class="[
+                                'ppt-editor-title',
+                                'custom-title-wrap',
+                                currentItem.id===item.id&&isEditTitle?'editor-model':''
+                                ]" 
+                            :style="item.titleDetail?{
+                                left:item.titleDetail.left+'%',
+                                top:item.titleDetail.top+'%',
+                                width:item.titleDetail.width+'%',
+                                height:item.titleDetail.height+'%',
+                            }:{
+                                left:'10%',top:'5.5%',width:'68%',height:'7%'
+                            }">
+                            <div class="title" v-html="item.title"></div>
                         </div>
                         <!-- 内容 -->
                         <component  :is="getComponentName(item.modelId)"
@@ -68,6 +85,7 @@
                                     :isCopy="true"
                                     :isAdd="true"
                                     :isEditLayer="isEditLayer"
+                                    :isEditTitle="isEditTitle"
                                     :choosedId="currentItem.id"
                                     :activeLayerEl="activeLayerEl"
                                     :amendatoryPositionInfo="item.positionInfo"
@@ -121,7 +139,7 @@
             </div>
             <div class="richtext-tool"></div>
             <!-- 防止el-tabs未渲染时触发scrollToActiveTab 报错,v-if改为v-show-->
-            <div class="addppt-right-box" v-show="!isEditLayer">
+            <div class="addppt-right-box" v-show="!isEditLayer&&!isEditTitle">
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab.label" :name="tab.val" v-for="tab in panelTabs" :key="tab.val"></el-tab-pane>
               </el-tabs>
@@ -187,7 +205,7 @@
               </div>
             </div>
             <!-- 图层编辑 -->
-            <div class="layer-edit-box" v-show="isEditLayer">
+            <div class="layer-edit-box" v-if="isEditLayer">
               	<el-collapse v-model="activeNames" class="tool-list">
                   <el-collapse-item :title="$t('Slides.layer_element')" name="el">
                     <div class="el-wrap">
@@ -226,6 +244,17 @@
                   </el-collapse-item>
                 </el-collapse>
             </div>
+            <!-- 标题编辑 -->
+            <div class="title-edit-box" v-if="isEditTitle">
+                <p>{{$t('Slides.page_title_style_setting')}}</p>
+                <TitleEditorTool 
+                    ref="titleEditor"
+                    :currentItem="currentItem"
+                    @changeSizeAll="changeSizeAll"
+                    @changePositionAll="changePositionAll"
+                    @styleChange="handleTitelStyleChange"
+                    @textChange="handleTextChange"/>
+            </div>
           </div>
     </div>
 
@@ -310,6 +339,7 @@ import InsertCharts from './components/editor/InsertCharts.vue';
 import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
 import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
+import TitleEditorTool from './components/editor/TitleEditorTool';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -319,7 +349,7 @@ export default {
   components: {
     IndexItem, ChooseCover, AddFormat, ShapePreview,
     LayerEditTool, DeletePageDialog, ChangeFormatDialog, InsertPageDialog, addMyClassifyDia, InsertCharts, ContextMenu, InsertSemantics,
-    ChooseCoverNew
+    ChooseCoverNew,TitleEditorTool
 },
   data() {
     return {
@@ -742,6 +772,8 @@ export default {
         if(this.currentItem&&this.currentItem.id!==id){
           this.isEditLayer = false
           this.activeLayerEl = {}
+          
+          this.isEditTitle = false
         }
         this.pageList.map((item,index)=>{
           if(item.id===id){
@@ -1323,23 +1355,6 @@ export default {
 <style lang="scss">
 @import './css/common.scss';
 @import './css/format.scss';
-.page-wrap{
-  .ppt-editor-wrap{
-    .ppt-tool{
-      .layer-edit-box{
-        .tool-list{
-          .el-collapse-item__header{
-            margin-bottom: 0;
-          }
-          .el-collapse-item__wrap{
-            overflow: visible;
-          }
-        }
-      }
-    }
-  }
-}
-
 </style>
 <style scoped lang="scss">
 $titleColor:#333333;
@@ -1493,17 +1508,19 @@ $titleColor:#333333;
            min-width:320px;
            width: 320px;
            height:100%;
-           .tool-btn{
-               margin-bottom: 12px;
+           overflow-y: hidden;
+           .richtext-tool{
+            margin:10px 0;
            }
             .addppt-right-box{
               flex: 1;
-              height: calc(100% - 182px);
+             /* height: calc(100% - 182px); */
               padding: 0 10px;
-              margin-top: 12px;
               box-sizing: border-box;
-              border:1px solid #B2B9C3;
+              border: 2px solid #EBEBEB;
+              border-radius: 4px;
               min-width: 320px;
+              overflow-y: auto;
               #tabs {
                 padding: 0px 40px;
                 box-sizing: border-box;
@@ -1579,20 +1596,20 @@ $titleColor:#333333;
               }
 
 		        }
-            .layer-edit-box{
+            .layer-edit-box,.title-edit-box{
               flex: 1;
-              height: calc(100% - 182px);
+              /* height: calc(100% - 182px); */
               padding: 0 20px;
-              margin-top: 12px;
               box-sizing: border-box;
               border: 2px solid #EBEBEB;
               border-radius: 4px;
               min-width: 320px;
-              overflow-y: scroll;
+              overflow-y: auto;
               .tool-list{
                 .el-wrap{
                   display: flex;
-                  justify-content: space-between;
+                  /* justify-content: space-between; */
+                  gap: 0 15px;
                   flex-wrap: wrap;
                   .el-item{
                     border: 1px solid #DCDFE6;
@@ -1614,24 +1631,14 @@ $titleColor:#333333;
                 }
               }
             }
+            .title-edit-box{
+                p{
+                    font-size: 16px;
+                    font-weight: bold;
+                    margin-top:16px;
+                }
+            }
        }
     }
 }
 </style>
-<style lang="scss">
-.page-wrap {
-	.el-tabs__nav-wrap::after {
-		height: 0;
-	}
-	.el-tabs__item { font-size: 16px; }
-	.layer-edit-box{
-		.tool-list{
-			.el-collapse-item:first-child{
-				.el-collapse-item__content{
-					padding-bottom: 5px;
-				}
-			}
-		}
-	}
-}	
-</style>

+ 4 - 3
src/views/ppt_manage/newVersion/pptEnCatalog.vue

@@ -545,9 +545,10 @@ export default {
         this.$nextTick(()=>{
            //选中节点
           this.$refs[`${this.treeName}Tree`].setCurrentKey(item.nodeKeyId)
-          //展开该节点的父节点
+          //找到该节点的父节点,展开,获取父节点id
           const node = this.$refs[`${this.treeName}Tree`].getCurrentNode()
           !this[`${this.treeName}ExpandKeys`].includes(node.catalogId)&&this[`${this.treeName}ExpandKeys`].push(node.catalogId)
+          this.pptItem.catalogId = node.catalogId||''
           this.selectNode = item
         })
       }else{
@@ -740,13 +741,13 @@ export default {
             this.$refs[`${this.treeName}Tree`].setCurrentKey(data.catalogId)
             //删除的是公共目录下,某目录的最后一个PPT时,该公共目录会消失
             if(this.treeName==='public'&&catalog.PptList.length>1){
-              this.changeModel('list',catalog)
+              this.changeModel('list',catalog||{})
             }else if(this.treeName==='public'&&catalog.PptList.length===1){
               this.changeModel('list',{})
             }
             //但是私有目录不会
             if(this.treeName==='private'){
-              this.changeModel('list',catalog)
+              this.changeModel('list',catalog||{})
             }
           }
         })

+ 57 - 47
src/views/ppt_manage/newVersion/pptEnEditor.vue

@@ -54,9 +54,27 @@
                   v-loading="item.isUpdating" :element-loading-text="$t('Slides.updating_chart_loading')"
                   @click="changeCurrentItem(item)">
                     <!-- 标题 -->
-                    <div class="title-wrap" style="left:8%;width:62%;">
+                    <!-- <div class="title-wrap" style="left:8%;width:62%;">
                         <input type="text" :placeholder="$t('Slides.click_to_input_title')" v-model="item.title"/> 
-                    </div>
+                    </div> -->
+                    <!-- 自定义标题 -->
+                    <div @click.stop="handleEditTitle"
+                            :class="[
+                                'ppt-editor-title',
+                                'custom-title-wrap',
+                                currentItem.id===item.id&&isEditTitle?'editor-model':''
+                                ]" 
+                            :style="item.titleDetail?{
+                                left:item.titleDetail.left+'%',
+                                top:item.titleDetail.top+'%',
+                                width:item.titleDetail.width+'%',
+                                height:item.titleDetail.height+'%',
+                            }:{
+                                left:'10%',top:'5.5%',width:'68%',height:'7%'
+                            }">
+                            <div class="title" v-html="item.title"></div>
+                            <!-- <div v-else class="normal-title">{{item.title}}</div> -->
+                        </div>
                     <!-- 内容 -->
                     <component  :is="getComponentName(item.modelId)"
                                 :ref="`pptPage_${index}`"
@@ -64,6 +82,7 @@
                                 :pageItem="item"
                                 :key="item.key"
                                 :isEditLayer="isEditLayer"
+                                :isEditTitle="isEditTitle"
                                 :choosedId="currentItem.id"
                                 :activeLayerEl="activeLayerEl"
                                 :isCopy="true"
@@ -117,7 +136,7 @@
                 <el-button type="text" @click="handleChangeEditModal"><i class="el-icon-sort" style="transform: rotate(90deg);margin-right:5px;"></i>{{isEditLayer? $t('Slides.ppt_edit_btn'):$t('Slides.layer_editing')}}</el-button>
             </div>
             <div class="richtext-tool"></div>
-            <div class="addppt-right-box" v-show="!isEditLayer">
+            <div class="addppt-right-box" v-show="!isEditLayer&&!isEditTitle">
 
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab.label" :name="tab.val" v-for="tab in panelTabs" :key="tab"></el-tab-pane>
@@ -226,6 +245,17 @@
                   </el-collapse-item>
                 </el-collapse>
             </div>
+            <!-- 标题编辑 -->
+            <div class="title-edit-box" v-if="isEditTitle">
+                <p>{{$t('Slides.page_title_style_setting')}}</p>
+                <TitleEditorTool 
+                    ref="titleEditor"
+                    :currentItem="currentItem"
+                    @changeSizeAll="changeSizeAll"
+                    @changePositionAll="changePositionAll"
+                    @styleChange="handleTitelStyleChange"
+                    @textChange="handleTextChange"/>
+            </div>
           </div>
     </div>
 
@@ -322,6 +352,7 @@ import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue';
 import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
 import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
+import TitleEditorTool from './components/editor/TitleEditorTool';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -342,7 +373,8 @@ export default {
     InsertCharts,
     ContextMenu,
     InsertSemantics,
-    ChooseCoverNew
+    ChooseCoverNew,
+    TitleEditorTool
   },
   data() {
     return {
@@ -745,6 +777,8 @@ export default {
         if(this.currentItem&&this.currentItem.id!==id){
           this.isEditLayer = false
           this.activeLayerEl = {}
+
+          this.isEditTitle = false
         }
         this.pageList.map((item,index)=>{
           if(item.id===id){
@@ -1309,23 +1343,6 @@ export default {
 <style lang="scss">
 @import './css/common.scss';
 @import './css/format.scss';
-.page-wrap{
-  .ppt-editor-wrap{
-    .ppt-tool{
-      .layer-edit-box{
-        .tool-list{
-          .el-collapse-item__header{
-            margin-bottom: 0;
-          }
-          .el-collapse-item__wrap{
-            overflow: visible;
-          }
-        }
-      }
-    }
-  }
-}
-
 </style>
 <style scoped lang="scss">
 $titleColor:#333333;
@@ -1480,17 +1497,19 @@ $titleColor:#333333;
            min-width:320px;
            width: 320px;
            height:100%;
-           .tool-btn{
-               margin-bottom: 12px;
+           overflow-y: hidden;
+           .richtext-tool{
+            margin:10px 0;
            }
             .addppt-right-box{
               flex: 1;
-              height: calc(100% - 182px);
+              /* height: calc(100% - 182px); */
               padding: 0 10px;
-              margin-top: 12px;
               box-sizing: border-box;
-              border:1px solid #B2B9C3;
+              border:2px solid #EBEBEB;
+              border-radius: 4px;
               min-width: 320px;
+              overflow-y: auto;
               #tabs {
                 padding: 0px 40px;
                 box-sizing: border-box;
@@ -1578,20 +1597,21 @@ $titleColor:#333333;
               }
 
 		        }
-            .layer-edit-box{
+            .layer-edit-box,.title-edit-box{
               flex: 1;
-              height: calc(100% - 182px);
+              /* height: calc(100% - 182px); */
               padding: 0 20px;
               margin-top: 12px;
               box-sizing: border-box;
               border: 2px solid #EBEBEB;
               border-radius: 4px;
               min-width: 320px;
-              overflow-y: scroll;
+              overflow-y: auto;
               .tool-list{
                 .el-wrap{
                   display: flex;
-                  justify-content: space-between;
+                  /* justify-content: space-between; */
+                  gap:0 15px;
                   flex-wrap: wrap;
                   .el-item{
                     border: 1px solid #DCDFE6;
@@ -1613,24 +1633,14 @@ $titleColor:#333333;
                 }
               }
             }
+            .title-edit-box{
+                p{
+                    font-size: 16px;
+                    font-weight: bold;
+                    margin-top:16px;
+                }
+            }
        }
     }
 }
 </style>
-<style lang="scss">
-.page-wrap {
-	.el-tabs__nav-wrap::after {
-		height: 0;
-	}
-	.el-tabs__item { font-size: 16px; }
-	.layer-edit-box{
-		.tool-list{
-			.el-collapse-item:first-child{
-				.el-collapse-item__content{
-					padding-bottom: 5px;
-				}
-			}
-		}
-	}
-}	
-</style>

+ 28 - 2
src/views/ppt_manage/newVersion/pptEnPresent.vue

@@ -49,7 +49,7 @@
             </div>
             <!-- PPT内容 -->
               <div class="ppt-item" v-else>
-                <div class="title-wrap" 
+                <!-- <div class="title-wrap" 
                     :title="currentItem.title" 
                     :style="`
                         top:${lineClamp===2?'2%':getStrCount(currentItem.title)<52?'4.5%':'0'};
@@ -57,6 +57,19 @@
                         -webkit-line-clamp:${lineClamp===2?2:3};`" 
                     :class="{'title-ellipsis':getStrCount(currentItem.title)>lineClamp*50}">
                   {{currentItem.title}}
+                </div> -->
+                 <!-- 自定义标题 -->
+                 <div class="custom-title-wrap editor-content" 
+                    :style="currentItem.titleDetail?{
+                        left:currentItem.titleDetail.baseLeft+'px',
+                        top:currentItem.titleDetail.baseTop+'px',
+                        width:currentItem.titleDetail.baseWidth+'px',
+                        height:currentItem.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="currentItem.title"></div>
+                    <!-- <div v-else class="normal-title">{{currentItem.title}}</div> -->
                 </div>
                 <component
                   :ref="`pptPage_${currentIndex-1}`" 
@@ -108,7 +121,7 @@
             </div>
             <!-- PPT内容 -->
               <div class="ppt-item" v-else>
-                <div class="title-wrap" 
+                <!-- <div class="title-wrap" 
                     :title="currentItem.title" 
                     :style="`
                         top:${lineClamp===2?'2%':'0'};
@@ -116,6 +129,19 @@
                         -webkit-line-clamp:${lineClamp===2?2:3};`" 
                     :class="{'title-ellipsis':getStrCount(currentItem.title)>lineClamp*57}">
                   {{currentItem.title}}
+                </div> -->
+                <!-- 自定义标题 -->
+                <div class="custom-title-wrap editor-content" 
+                    :style="currentItem.titleDetail?{
+                        left:currentItem.titleDetail.baseLeft+'px',
+                        top:currentItem.titleDetail.baseTop+'px',
+                        width:currentItem.titleDetail.baseWidth+'px',
+                        height:currentItem.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="currentItem.title"></div>
+                    <!-- <div v-else class="normal-title">{{currentItem.title}}</div> -->
                 </div>
                 <component
                   :ref="`pptPage_${currentIndex-1}`" 

+ 19 - 5
src/views/ppt_manage/newVersion/pptEnPublish.vue

@@ -35,8 +35,21 @@
           </div>
           <!-- 内容 -->
           <div class="ppt-item" v-for="(item,index) in pageList" :key="item.id">
-            <div class="title-wrap">
+            <!-- <div class="title-wrap">
               {{item.title}} 
+            </div> -->
+            <!-- 自定义标题 -->
+            <div class="custom-title-wrap editor-content" 
+                :style="item.titleDetail?{
+                    left:item.titleDetail.baseLeft+'px',
+                    top:item.titleDetail.baseTop+'px',
+                    width:item.titleDetail.baseWidth+'px',
+                    height:item.titleDetail.baseHeight+'px',
+                }:{
+                    left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                }">
+                <div class="title" v-html="item.title"></div>
+                <!-- <div v-else class="normal-title">{{item.title}}</div> -->
             </div>
             <component
               :is="getComponentName(item.modelId)"
@@ -263,7 +276,7 @@ export default {
       let pptx = pptConfigInit(new pptxgen(),this.LayoutType,'en',SlideMaster,this.pptBgImage)
       //添加封面
       let cover = pptx.addSlide()
-      let coverId = this.loadingAll?'cover':'changecover'
+      let coverId = 'cover'
       //let coverImg = await this.htmlToCanvans(coverId)
       let coverImg = $(`#${coverId} .cover img`)[0].src
       cover.addImage({
@@ -279,14 +292,15 @@ export default {
       const length = this.pageList.length;
       for (let i = 0; i < length; i++) {
         let slide = pptx.addSlide({ masterName: pptSlideMaster.title });
-        slide.addText(this.pageList[i].title, {
+        /* slide.addText(this.pageList[i].title, {
           placeholder:"slideTitle",
           x:'8%',
           y:'5.5%',
           w:'62%',
           h:'7%',
           color:'333333'
-        });
+        }); */
+        slide = this.setPPTTitle(slide,this.pageList[i])
         const elements = this.pageList[i].elements;
         const elLength = elements.length;
         for (let j = 0; j < elLength; j++) {
@@ -401,7 +415,7 @@ export default {
       //添加封底 如果有
       if(this.pptBackImage.length){
         let back = pptx.addSlide()
-        let backId = this.loadingAll?'back':'changeback'
+        let backId = 'back'
         let backImg = $(`#${backId} img`)[0].src
         back.addImage({
             path: backImg,

+ 26 - 2
src/views/ppt_manage/newVersion/pptPresent.vue

@@ -49,7 +49,7 @@
             </div>
             <!-- PPT内容 -->
               <div class="ppt-item" v-else>
-                <div class="title-wrap" 
+                <!-- <div class="title-wrap" 
                     :title="currentItem.title" 
                     :style="`
                         top:${lineClamp===2?'2%':getStrCount(currentItem.title)<58?'5.5%':'0'};
@@ -57,6 +57,18 @@
                         -webkit-line-clamp:${lineClamp===2?2:3};`" 
                     :class="{'title-ellipsis':getStrCount(currentItem.title)>lineClamp*57}">
                   {{currentItem.title}}
+                </div> -->
+                <!-- 自定义标题 -->
+                <div class="custom-title-wrap editor-content" 
+                    :style="currentItem.titleDetail?{
+                        left:currentItem.titleDetail.baseLeft+'px',
+                        top:currentItem.titleDetail.baseTop+'px',
+                        width:currentItem.titleDetail.baseWidth+'px',
+                        height:currentItem.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="currentItem.title"></div>
                 </div>
                 <component
                   :ref="`pptPage_${currentIndex-1}`" 
@@ -108,7 +120,7 @@
             </div>
             <!-- PPT内容 -->
               <div class="ppt-item" v-else>
-                <div class="title-wrap" 
+                <!-- <div class="title-wrap" 
                     :title="currentItem.title" 
                     :style="`
                         top:${lineClamp===2?'2%':getStrCount(currentItem.title)<58?'5.5%':'0'};
@@ -116,6 +128,18 @@
                         -webkit-line-clamp:${lineClamp===2?2:3};`" 
                     :class="{'title-ellipsis':getStrCount(currentItem.title)>lineClamp*57}">
                   {{currentItem.title}}
+                </div> -->
+                <!-- 自定义标题 -->
+                <div class="custom-title-wrap editor-content" 
+                    :style="currentItem.titleDetail?{
+                        left:currentItem.titleDetail.baseLeft+'px',
+                        top:currentItem.titleDetail.baseTop+'px',
+                        width:currentItem.titleDetail.baseWidth+'px',
+                        height:currentItem.titleDetail.baseHeight+'px',
+                    }:{
+                        left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                    }">
+                    <div class="title" v-html="currentItem.title"></div>
                 </div>
                 <component
                   :ref="`pptPage_${currentIndex-1}`" 

+ 19 - 11
src/views/ppt_manage/newVersion/pptPublish.vue

@@ -36,13 +36,25 @@
           </div>
           <!-- 内容 -->
           <div class="ppt-item" v-for="(item,index) in pageList" :key="item.id">
-            <div class="title-wrap"
+            <!-- <div class="title-wrap"
             :style="`
                 top:${lineClamp===2?'2%':getStrCount(item.title)<58?'5.5%':'0'};
                 height:${lineClamp===2?'12%':getStrCount(item.title)<58?'7%':'14%'};
                 -webkit-line-clamp:${lineClamp===2?2:3};`" 
             :class="{'title-ellipsis':getStrCount(item.title)>lineClamp*57}">
               {{item.title}} 
+            </div> -->
+            <!-- 自定义标题 -->
+            <div class="custom-title-wrap editor-content" 
+                :style="item.titleDetail?{
+                    left:item.titleDetail.baseLeft+'px',
+                    top:item.titleDetail.baseTop+'px',
+                    width:item.titleDetail.baseWidth+'px',
+                    height:item.titleDetail.baseHeight+'px',
+                }:{
+                    left:'90px',top:'34.65px',width:'612px',height:'44.1px'
+                }">
+                <div class="title" v-html="item.title"></div>
             </div>
             <component
               :is="getComponentName(item.modelId)"
@@ -78,7 +90,6 @@ import {countComponentName,pptConfigInit,toTextProps,toJson,svg2Base64,svgData2B
 import {marginTop,modelConfig,pptSlideMaster} from './utils/config';
 import pptmixin from '../mixins/pptMixins';
 import mixins from '../mixins/mixins';
-import virtualScroll from '../mixins/virtualScrollMixins'
 import html2canvas from 'html2canvas';
 import pptxgen from "pptxgenjs";
 import moment from 'moment';
@@ -92,7 +103,7 @@ HightchartsExport(Highcharts)
 HighchartszhCN(Highcharts)
 export default {
   components: {Cover,TransReport,CustomCover},
-  mixins:[pptmixin,mixins,virtualScroll],
+  mixins:[pptmixin,mixins],
   data() {
     return {
         coverInfo:{
@@ -215,11 +226,7 @@ export default {
 
         this.dataLoading.close();
         $('.ppt-item').css('background-image',`url(${this.pptBgImage})`);
-      }else{
-        await this.getpptData();
-        this.initVirtualScroll()
       }
-      //console.log($('#back img')[0].src)
     },
     async getpptData(){
       const {id} = this.$route.query
@@ -289,7 +296,7 @@ export default {
       let pptx = pptConfigInit(new pptxgen(),this.LayoutType,'ch',SlideMaster,this.pptBgImage)
       //添加封面
       let cover = pptx.addSlide()
-      let coverId = this.loadingAll?'cover':'changecover'
+      let coverId = 'cover'
       let coverImg = $(`#${coverId} .cover img`)[0].src
       cover.addImage({
         path: coverImg,
@@ -304,14 +311,15 @@ export default {
       const length = this.pageList.length;
       for (let i = 0; i < length; i++) {
         let slide = pptx.addSlide({ masterName: pptSlideMaster.title });
-        slide.addText(this.pageList[i].title, {
+        /* slide.addText(this.pageList[i].title, {
           placeholder:"slideTitle",
           x:'10%',
           y:'5.5%',
           w:'68%',
           h:'7%',
           color:'333333'
-        });
+        }); */
+        slide = this.setPPTTitle(slide,this.pageList[i])
         const elements = this.pageList[i].elements;
         const elLength = elements.length;
         for (let j = 0; j < elLength; j++) {
@@ -432,7 +440,7 @@ export default {
       //添加封底 如果有
       if(this.pptBackImage.length){
         let back = pptx.addSlide()
-        let backId = this.loadingAll?'back':'changeback'
+        let backId = 'back'
         let backImg = $(`#${backId} img`)[0].src
         back.addImage({
             path: backImg,

+ 65 - 0
src/views/ppt_manage/newVersion/utils/tinymceSetting.js

@@ -0,0 +1,65 @@
+export const setting = {
+    menubar: false,
+    toolbar: [
+        "indent outdent alignleft aligncenter alignright alignjustify forecolor",
+        "bold italic underline strikethrough numlist bullist backcolor",
+        "fontselect fontsizeselect",
+    ],
+    quickbars_selection_toolbar:false,  
+    quickbars_insert_toolbar: false,
+    plugins: "lists quickbars paste",
+    paste_as_text: true,
+    fontsize_formats:'6px 8px 10px 12px 14px 16px 18px 20px 22px 24px 36px 48px',
+    font_formats:`微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';
+            楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;
+            Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;
+            Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;
+            Courier New=courier new,courier;Georgia=georgia,palatino;
+            Helvetica=helvetica;Impact=impact,chicago;
+            Webdings=webdings;Wingdings=wingdings`,
+    skin_url: "/static/css",
+    content_url: "/static/css",
+    inline: true,//启动内联模式,否则会以iframe的形式渲染
+    setup:function(editor){
+        editor.on('ExecCommand',function(evt) {
+            let cmd = evt.command; 
+            //设置ul/ol li的字体大小,颜色
+            if (cmd === 'FontSize' || cmd === 'FontName' /* || cmd === 'mceApplyTextcolor' */) {
+                let val = evt.value; 
+                let node = evt.target.selection.getNode(); 
+                let nodeParent = node.parentNode; 
+                if (node.nodeName === 'SPAN' && nodeParent.nodeName === 'LI') {
+                    if (cmd === 'FontSize') { 
+                        editor.dom.setStyle(nodeParent, 'font-size', val); 
+                    } 
+                    if (cmd === 'FontName') { 
+                        editor.dom.setStyle(nodeParent, 'font-family', val); 
+                    } 
+                    /* if (cmd === 'mceApplyTextcolor') {
+                        editor.dom.setStyle(nodeParent,'color',val)
+                    } */
+                } else if (node.nodeName === 'UL' || node.nodeName === 'OL') { 
+                    let li = editor.dom.select('li', node); 
+                    if (cmd === 'FontSize') { 
+                        editor.dom.setStyle(li, 'font-size', val); 
+                    } 
+                    if (cmd === 'FontName') { 
+                        editor.dom.setStyle(li, 'font-family', val); 
+                    }
+                    /* if (cmd === 'mceApplyTextcolor') {
+                        editor.dom.setStyle(li,'color',val)
+                    } */
+                } 
+            }
+        });
+        //中文输入法和placeholder并存的问题
+        editor.on('input',function(){
+            let content = editor.getContent()
+            if(content){
+                editor.getBody().classList.add('.placeholder-hidden')
+            }else{
+                editor.getBody().classList.remove('.placeholder-hidden')
+            }
+        })
+    }
+}

+ 8 - 0
src/views/ppt_manage/newVersion/utils/untils.js

@@ -727,3 +727,11 @@ export const isShowPPTTitle = (Source,MyChartType)=>{
     const sense_2 = [2,5,6,7,8,9].includes(Source)
     return sense_1||sense_2
 }
+
+//获取富文本字符串的纯文本
+export const getPlainText = (richText='')=>{
+    let tempDiv = document.createElement("div");
+    tempDiv.innerHTML = richText;
+    let plainText = tempDiv.textContent || tempDiv.innerText || "";
+    return plainText.trim(); // 使用trim()移除可能的前后空格
+}