|
@@ -0,0 +1,1458 @@
|
|
|
+<script setup>
|
|
|
+import { nextTick, reactive, ref,toRefs, watch,onMounted,onUnmounted } from 'vue'
|
|
|
+import { V3ColorPicker } from "v3-color-picker-teleport"
|
|
|
+import ReportInsertContent from '../components/reportInsert/Index.vue'
|
|
|
+import ReportPublishTimeSet from '../components/ReportPublishTimeSet.vue'
|
|
|
+import apiReport from '@/api/report'
|
|
|
+import _ from 'lodash'
|
|
|
+import moment from 'moment'
|
|
|
+import { showToast,showDialog } from 'vant'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import {useCachedViewsStore} from '@/store/modules/cachedViews'
|
|
|
+import {usePublicSettingStore} from '@/store/modules/publicSetting'
|
|
|
+import {reportManageBtn,useAuthBtn} from '@/hooks/useAuthBtn'
|
|
|
+import {useReportApprove} from '@/hooks/useReportApprove'
|
|
|
+import AddReportBaseInfoV2 from '../components/AddReportBaseInfoV2.vue'
|
|
|
+import { useReportHandles,useChapterRepoprtHandles } from '../hooks/useReport'
|
|
|
+import draggable from 'vuedraggable'
|
|
|
+import TextEditor from './components/TextEditor.vue'
|
|
|
+import ImgEditor from './components/ImgEditor.vue'
|
|
|
+import TextComp from './components/TextComp.vue'
|
|
|
+import ChartComp from './components/ChartComp.vue'
|
|
|
+import ImgComp from './components/ImgComp.vue'
|
|
|
+import SheetComp from './components/SheetComp.vue'
|
|
|
+import ReportLayoutImg from './components/ReportLayoutImg.vue'
|
|
|
+
|
|
|
+
|
|
|
+const cachedViewsStore=useCachedViewsStore()
|
|
|
+const publicSettingStore = usePublicSettingStore()
|
|
|
+const {isApprove,hasApproveFlow,getEtaConfig,checkClassifyNameArr} = useReportApprove()
|
|
|
+const router=useRouter()
|
|
|
+const route=useRoute()
|
|
|
+const {checkAuthBtn} = useAuthBtn()
|
|
|
+
|
|
|
+
|
|
|
+const reportCoopType = ref(Number(route.query.coopType))
|
|
|
+let autoSaveTimer=null
|
|
|
+onMounted(() => {
|
|
|
+ if(reportCoopType.value===1) {
|
|
|
+ getEtaConfig()
|
|
|
+ getReportDetail()
|
|
|
+ autoSaveTimer=setInterval(() => {
|
|
|
+ autoSaveReportContent()
|
|
|
+ }, 6000);
|
|
|
+ }else if(reportCoopType.value===2) { //章节报告
|
|
|
+ getChapterDetail()
|
|
|
+ autoSaveTimer=setInterval(() => {
|
|
|
+ autoSaveReportChapter()
|
|
|
+ }, 6000);
|
|
|
+ }
|
|
|
+})
|
|
|
+onUnmounted(()=>{
|
|
|
+ clearInterval(autoSaveTimer)
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+// 获取报告详情
|
|
|
+const reportInfo=ref(null)
|
|
|
+const contentChange = ref(false)//内容是否发生变化
|
|
|
+const smartState = reactive({
|
|
|
+ conList: [],//内容列表
|
|
|
+ bgColor:'',//背景色
|
|
|
+ headImg:'',//版头图片
|
|
|
+ endImg:'',//版尾图片
|
|
|
+ headImgId:0,//版头Id
|
|
|
+ endImgId:0,//版尾Id
|
|
|
+ headImgStyle:'',//版头style
|
|
|
+ endImgStyle:'',//版尾style
|
|
|
+ layoutBaseInfo:{
|
|
|
+ 研报标题:'',
|
|
|
+ 研报作者:'',
|
|
|
+ 创建时间:''
|
|
|
+ },
|
|
|
+})
|
|
|
+async function getReportDetail(){
|
|
|
+ const res=await apiReport.getReportDetail({
|
|
|
+ ReportId:Number(route.query.id)
|
|
|
+ })
|
|
|
+ if(res.Ret===200){
|
|
|
+ reportInfo.value=res.Data;
|
|
|
+
|
|
|
+ smartState.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
|
|
|
+ smartState.headImg=res.Data.HeadImg
|
|
|
+ smartState.endImg=res.Data.EndImg
|
|
|
+ smartState.headImgId=res.Data.HeadResourceId
|
|
|
+ smartState.endImgId=res.Data.EndResourceId
|
|
|
+ smartState.headImgStyle=res.Data.HeadStyle?JSON.parse(res.Data.HeadStyle):[]
|
|
|
+ smartState.headImgStyle.map(st =>{
|
|
|
+ st.value=st.value || st.label
|
|
|
+ })
|
|
|
+ smartState.endImgStyle=res.Data.EndStyle?JSON.parse(res.Data.EndStyle):[]
|
|
|
+ smartState.endImgStyle.map(st =>{
|
|
|
+ st.value=st.value || st.label
|
|
|
+ })
|
|
|
+ smartState.bgColor=res.Data.CanvasColor
|
|
|
+ smartState.layoutBaseInfo['研报标题']=res.Data.Title
|
|
|
+ smartState.layoutBaseInfo['研报作者']=res.Data.Author
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ reportBaseInfoData.addType=res.Data.AddType
|
|
|
+ reportBaseInfoData.classifyName=[
|
|
|
+ {
|
|
|
+ id:res.Data.ClassifyIdFirst,
|
|
|
+ text:res.Data.ClassifyNameFirst,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id:res.Data.ClassifyIdSecond,
|
|
|
+ text:res.Data.ClassifyNameSecond,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id:res.Data.ClassifyIdThird,
|
|
|
+ text:res.Data.ClassifyNameThird,
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ reportBaseInfoData.author=res.Data.Author ? res.Data.Author.split(',') : ['FICC团队']
|
|
|
+ reportBaseInfoData.frequency=[res.Data.Frequency]
|
|
|
+ reportBaseInfoData.createtime=moment(res.Data.CreateTime).format('YYYY-MM-DD')
|
|
|
+ reportBaseInfoData.title=res.Data.Title
|
|
|
+ reportBaseInfoData.abstract=res.Data.Abstract
|
|
|
+ reportBaseInfoData.cooperationType=res.Data.CollaborateType
|
|
|
+ reportBaseInfoData.cooperationUsers=res.Data.GrandAdminList
|
|
|
+ ? res.Data.GrandAdminList.map(_ => ({
|
|
|
+ NodeId: _.AdminId,
|
|
|
+ NodeName: _.AdminName
|
|
|
+ }))
|
|
|
+ : []
|
|
|
+ reportBaseInfoData.reportLayout=res.Data.ReportLayout
|
|
|
+ reportBaseInfoData.isPublcPublish=res.Data.IsPublicPublish
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ contentChange.value = false
|
|
|
+ })
|
|
|
+
|
|
|
+ const classify = reportBaseInfoData.classifyName.map(i=>i.id)
|
|
|
+ checkClassifyNameArr(1,classify)
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//获取章节详情
|
|
|
+async function getChapterDetail() {
|
|
|
+ const res=await apiReport.getChapterDetail({
|
|
|
+ ReportChapterId:Number(route.query.chapterId)
|
|
|
+ })
|
|
|
+ reportInfo.value=res.Data;
|
|
|
+
|
|
|
+ smartState.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => smartState.conList,
|
|
|
+ () => {
|
|
|
+ contentChange.value = true;
|
|
|
+ },
|
|
|
+ {
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+/* map类型对应组件 */
|
|
|
+function getComponentName(item){
|
|
|
+ const temMap=new Map([
|
|
|
+ ['text',TextComp],
|
|
|
+ ['chart',ChartComp],
|
|
|
+ ['img',ImgComp],
|
|
|
+ ['sheet',SheetComp]
|
|
|
+ ])
|
|
|
+ return temMap.get(item.compType)
|
|
|
+}
|
|
|
+
|
|
|
+const isDragResize = ref(false)//是否正在拖动缩放
|
|
|
+// 大盒子的高度缩放
|
|
|
+function handleResizeP(e,index){
|
|
|
+ isDragResize.value=true
|
|
|
+ e.preventDefault()
|
|
|
+ const parentBox=e.target.parentNode.parentNode
|
|
|
+ const parentBoxWidth=parentBox.offsetWidth
|
|
|
+
|
|
|
+ const targetBox=e.target.parentNode
|
|
|
+ const targetBoxHeight=targetBox.offsetHeight
|
|
|
+ const targetBoxWidth=targetBox.offsetWidth
|
|
|
+
|
|
|
+ const startY=e.clientY
|
|
|
+ const startX=e.clientX
|
|
|
+ document.onmousemove=(mouseEl)=>{
|
|
|
+ mouseEl.preventDefault()
|
|
|
+ const h=mouseEl.clientY-startY+targetBoxHeight
|
|
|
+ // targetBox.style.minHeight=`${h<50?50:h}px`
|
|
|
+ targetBox.style.height=`${h}px`
|
|
|
+
|
|
|
+ // 去除minhight
|
|
|
+ targetBox.style.minHeight=`10px`
|
|
|
+
|
|
|
+ // 计算宽度
|
|
|
+ const w=mouseEl.clientX-startX+targetBoxWidth
|
|
|
+ const resW= (w/parentBoxWidth)*100//计算出的百分比结果值
|
|
|
+ targetBox.style.width=`${resW>=100?100:resW}%`
|
|
|
+ }
|
|
|
+ document.onmouseup=(el)=>{
|
|
|
+ console.log(targetBox.style.cssText);
|
|
|
+ smartState.conList[index].style = targetBox.style.cssText
|
|
|
+ el.preventDefault()
|
|
|
+ document.onmousemove=null
|
|
|
+ setTimeout(() => {
|
|
|
+ isDragResize.value=false
|
|
|
+ }, 50);
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+// 内部元素的缩放
|
|
|
+function handleResizeC(e,index,cindex,type){
|
|
|
+ isDragResize.value=true
|
|
|
+ e.preventDefault()
|
|
|
+ const parentBox=e.target.parentNode.parentNode
|
|
|
+ const parentBoxWidth=parentBox.offsetWidth
|
|
|
+ console.log(e);
|
|
|
+ const targetBox=e.target.parentNode
|
|
|
+ const targetBoxHeight=targetBox.offsetHeight
|
|
|
+ const targetBoxWidth=targetBox.offsetWidth
|
|
|
+ const startY=e.clientY
|
|
|
+ const startX=e.clientX
|
|
|
+ const initW=targetBoxWidth //拖动前要拖动盒子所占的宽度
|
|
|
+
|
|
|
+ let computerW=0//存放其他兄弟节点要改变的宽度的值
|
|
|
+
|
|
|
+ document.onmousemove=(mouseEl)=>{
|
|
|
+ mouseEl.preventDefault()
|
|
|
+ const h=mouseEl.clientY-startY+targetBoxHeight
|
|
|
+ // 计算宽度
|
|
|
+ const w=type==='rb'?mouseEl.clientX-startX+targetBoxWidth:startX-mouseEl.clientX+targetBoxWidth
|
|
|
+ const resW= (w/parentBoxWidth)*100//计算出的百分比结果值
|
|
|
+ targetBox.style.width=resW+'%'
|
|
|
+ targetBox.style.flex='none'
|
|
|
+
|
|
|
+ // 处理兄弟盒子的宽度
|
|
|
+ const changeW=w-initW //宽度变化值
|
|
|
+ computerW=changeW
|
|
|
+ if(parentBox.childNodes.length===3){
|
|
|
+ computerW=changeW/2
|
|
|
+ }
|
|
|
+ // console.log('改变的宽度',computerW);
|
|
|
+
|
|
|
+ // targetBox.style.height=`${h<50?50:h}px`
|
|
|
+ targetBox.style.height=`${h}px`
|
|
|
+ }
|
|
|
+ document.onmouseup=(el)=>{
|
|
|
+ if(document.onmousemove){
|
|
|
+ parentBox.childNodes.forEach(item=>{
|
|
|
+ if(item!==targetBox){
|
|
|
+ const temw=item.offsetWidth-computerW
|
|
|
+ item.style.width=((temw/parentBoxWidth)*100)+'%'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 存储修改的值
|
|
|
+ parentBox.childNodes.forEach((item,idx)=>{
|
|
|
+ smartState.conList[index].child[idx].style = item.style.cssText
|
|
|
+ })
|
|
|
+ }
|
|
|
+ el.preventDefault()
|
|
|
+ document.onmousemove=null
|
|
|
+ setTimeout(() => {
|
|
|
+ isDragResize.value=false
|
|
|
+ document.onmouseup=null
|
|
|
+ }, 50);
|
|
|
+ }
|
|
|
+}
|
|
|
+//新增内部元素
|
|
|
+function handleChildAdd(e,parent,parentIndex){
|
|
|
+ console.log('child-onAdd操作------------------->');
|
|
|
+
|
|
|
+ const {item,newDraggableIndex}=e
|
|
|
+
|
|
|
+ const compData=JSON.parse(item.getAttribute('comp-data'))
|
|
|
+
|
|
|
+ console.log(compData,newDraggableIndex);
|
|
|
+
|
|
|
+ const index=parentIndex
|
|
|
+ // if(index>-1){
|
|
|
+ let obj=_.cloneDeep(smartState.conList[index])
|
|
|
+
|
|
|
+ console.log(obj);
|
|
|
+
|
|
|
+ if(obj.child&&obj.child.length===1&&obj.id){
|
|
|
+ if(compData){
|
|
|
+ obj={
|
|
|
+ child:[
|
|
|
+ {
|
|
|
+ compId:obj.compId,
|
|
|
+ compType:obj.compType,
|
|
|
+ id:obj.id,
|
|
|
+ content:obj.content,
|
|
|
+ style:obj.compType==='chart'?'height:350px':'',
|
|
|
+ child:[]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ compId:compData.compId,
|
|
|
+ compType:compData.compType,
|
|
|
+ content:compData.content||'',
|
|
|
+ id:getCompId(compData.compType),
|
|
|
+ style:compData.compType==='chart'?'height:350px':'',
|
|
|
+ child:[]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }else{//是内容区域拖动排序的
|
|
|
+ const temItem=_.cloneDeep(obj.child[0])
|
|
|
+ if(temItem.child.length>0){//如果拖动的盒子里面有子元素则不能进入
|
|
|
+ obj={
|
|
|
+ ...obj,
|
|
|
+ child:[]
|
|
|
+ }
|
|
|
+ setTimeout(() => {
|
|
|
+ smartState.conList.splice(index,0,temItem)
|
|
|
+ }, 50);
|
|
|
+ }else{
|
|
|
+ obj={
|
|
|
+ child:[
|
|
|
+ {
|
|
|
+ compId:obj.compId,
|
|
|
+ compType:obj.compType,
|
|
|
+ id:obj.id,
|
|
|
+ content:obj.content,
|
|
|
+ style:obj.compType==='chart'?'height:350px':'',
|
|
|
+ child:[]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ...temItem
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }else{
|
|
|
+ if(compData){//如果是从内容区域拖入的没有compData
|
|
|
+ obj.child.splice(newDraggableIndex,1,{
|
|
|
+ compId:compData.compId,
|
|
|
+ compType:compData.compType,
|
|
|
+ content:compData.content||'',
|
|
|
+ id:getCompId(compData.compType),
|
|
|
+ style:compData.compType==='chart'?'height:350px':'',
|
|
|
+ child:[]
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(obj);
|
|
|
+
|
|
|
+ smartState.conList.splice(index,1,obj)
|
|
|
+ // }
|
|
|
+}
|
|
|
+//移除内部元素事件
|
|
|
+function handleChildRemove(e,arr){
|
|
|
+ console.log('child-remove操作------------------->');
|
|
|
+
|
|
|
+ // 如果当前移出的这个child还有两个的话则重置他们的宽度
|
|
|
+ arr.forEach(item=>{
|
|
|
+ if(item.style){
|
|
|
+ const styleArr=item.style.split(';').filter(s=>s&&(s.indexOf('width')===-1&&s.indexOf('flex')===-1)).join(';')
|
|
|
+ item.style=styleArr
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ // 如果child只剩一个了则移出来
|
|
|
+ smartState.conList=smartState.conList.map(_item=>{
|
|
|
+ if(_item.child&&_item.child.length===1){
|
|
|
+ const obj=_item.child[0]
|
|
|
+ if(obj.style){
|
|
|
+ const styleArr=obj.style.split(';').filter(s=>s&&(s.indexOf('width')===-1&&s.indexOf('flex')===-1)).join(';')
|
|
|
+ obj.style=styleArr
|
|
|
+ }
|
|
|
+ return obj
|
|
|
+ }else{
|
|
|
+ return _item
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// 点击删除某个元素
|
|
|
+function handleDelItem(pindex,cindex){
|
|
|
+ if(cindex===-1){
|
|
|
+ smartState.conList.splice(pindex,1)
|
|
|
+ }else{//删除子盒子
|
|
|
+ smartState.conList[pindex].child.splice(cindex,1)
|
|
|
+ if(smartState.conList[pindex].child.length===1){//只剩一个子盒子了则变成一个大盒子
|
|
|
+ const styleArr=smartState.conList[pindex].child[0].style.split(';').filter(s=>s&&(s.indexOf('width')===-1&&s.indexOf('flex')===-1)).join(';')
|
|
|
+ smartState.conList[pindex]=smartState.conList[pindex].child[0]
|
|
|
+ smartState.conList[pindex].style=styleArr
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 删除版头版尾
|
|
|
+function deleteLayoutPic(type){
|
|
|
+ if(type===1){
|
|
|
+ smartState.headImg=''
|
|
|
+ smartState.headImgId = 0
|
|
|
+ }else{
|
|
|
+ smartState.endImg=''
|
|
|
+ smartState.endImgId = 0
|
|
|
+ }
|
|
|
+ contentChange.value=true
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//当前选中的
|
|
|
+const currentState = reactive({
|
|
|
+ activeId: 0,
|
|
|
+ activeContent: '',
|
|
|
+ activePindex: '',
|
|
|
+ activeCindex: ''
|
|
|
+})
|
|
|
+// 当前再编辑哪个
|
|
|
+function handleChoose(item,index,cindex){
|
|
|
+ // console.log(item,index,cindex)
|
|
|
+ //{item:数据,index:父序号,cindex:子序号}
|
|
|
+ if(!item.id||isDragResize.value||!['text','img'].includes(item.compType)) return
|
|
|
+ currentState.activeId=item.id
|
|
|
+ currentState.activeContent=item.content||''
|
|
|
+ currentState.activePindex=index
|
|
|
+ currentState.activeCindex=cindex>=0?cindex:''
|
|
|
+
|
|
|
+ insertState.activeId = 0;
|
|
|
+ insertState.activePindex = '';
|
|
|
+
|
|
|
+ showInsertCompType.value = item.compId;
|
|
|
+ showReportInsertPop.value = true
|
|
|
+ if(item.compId === 1) {//文字组件
|
|
|
+ temTextVal.value = item.content
|
|
|
+ }else if(item.compId === 2) { //图片组件
|
|
|
+ temImgVal.value = item.content
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//在哪项后插入
|
|
|
+const insertState = reactive({
|
|
|
+ activeId: 0,
|
|
|
+ activePindex: '',
|
|
|
+})
|
|
|
+function handleOpenInsertCompPop(e,{element,index}) {
|
|
|
+ currentState.activeId=0
|
|
|
+ currentState.activeContent=''
|
|
|
+ currentState.activePindex=''
|
|
|
+ currentState.activeCindex=''
|
|
|
+
|
|
|
+ insertState.activeId = element.child?.length ? element.child.map(_ =>_.id).join('/') : element.id;
|
|
|
+ insertState.activePindex = index;
|
|
|
+
|
|
|
+ showInsertCompType.value = e.compId;
|
|
|
+ temTextVal.value = ''
|
|
|
+ temImgVal.value = ''
|
|
|
+ showReportInsertPop.value = true
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const showPopover = ref(false)
|
|
|
+const showReportInsertPop = ref(false)
|
|
|
+const showInsertCompType=ref(0)
|
|
|
+const compType = [
|
|
|
+ {
|
|
|
+ compId:1,
|
|
|
+ compType:'text',
|
|
|
+ text:'文字',
|
|
|
+ icon:'font-o'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ compId:2,
|
|
|
+ compType:'img',
|
|
|
+ text:'图片',
|
|
|
+ icon:'photo-o'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ compId:3,
|
|
|
+ compType:'chart',
|
|
|
+ text:'图表',
|
|
|
+ icon:'chart-trending-o'
|
|
|
+ },
|
|
|
+]
|
|
|
+function handleOpenComPop(e) {
|
|
|
+ showPopover.value = false
|
|
|
+ console.log(e)
|
|
|
+
|
|
|
+ currentState.activeId=0
|
|
|
+ currentState.activeContent=''
|
|
|
+ currentState.activePindex=''
|
|
|
+ currentState.activeCindex=''
|
|
|
+
|
|
|
+ insertState.activeId = 0;
|
|
|
+ insertState.activePindex = '';
|
|
|
+
|
|
|
+ showInsertCompType.value = e.compId;
|
|
|
+ temTextVal.value = ''
|
|
|
+ temImgVal.value = ''
|
|
|
+ showReportInsertPop.value = true
|
|
|
+}
|
|
|
+/* 插入图表表格 */
|
|
|
+function handleChartInsert({list,type,chartType}){
|
|
|
+ console.log(list,type,chartType)
|
|
|
+ let tempCompDataArr=[]
|
|
|
+
|
|
|
+ if(type==='iframe'){
|
|
|
+ let link=publicSettingStore.publicSetting.ChartViewUrl;
|
|
|
+ if(chartType==='chart'){
|
|
|
+
|
|
|
+ link=link+'/chartshow'
|
|
|
+
|
|
|
+ tempCompDataArr = list.map(item =>({
|
|
|
+ compId:3,
|
|
|
+ compType:'chart',
|
|
|
+ id:getCompId(3),
|
|
|
+ content:`${link}?code=${item}`,
|
|
|
+ titleText: '',
|
|
|
+ style:'height:350px',
|
|
|
+ child:[]
|
|
|
+ }))
|
|
|
+ }else if(chartType==='sheet'){
|
|
|
+ link=link+'/sheetshow'
|
|
|
+ tempCompDataArr = list.map(item =>({
|
|
|
+ compId:4,
|
|
|
+ compType:'sheet',
|
|
|
+ id:getCompId(4),
|
|
|
+ content:`${link}?code=${item}&fromScene=1`,
|
|
|
+ titleText: '',
|
|
|
+ style:'',
|
|
|
+ child:[]
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ }else if(type==='img'){
|
|
|
+
|
|
|
+ tempCompDataArr = list.map(item =>({
|
|
|
+ compId:2,
|
|
|
+ compType:'img',
|
|
|
+ id:getCompId(2),
|
|
|
+ content:item,
|
|
|
+ titleText: '',
|
|
|
+ style:'',
|
|
|
+ child:[]
|
|
|
+ }))
|
|
|
+ }
|
|
|
+
|
|
|
+ if(insertState.activeId) {
|
|
|
+ smartState.conList.splice(insertState.activePindex+1,0,...tempCompDataArr)
|
|
|
+ }else {
|
|
|
+ smartState.conList.splice(0,0,...tempCompDataArr)
|
|
|
+ }
|
|
|
+ showReportInsertPop.value=false
|
|
|
+}
|
|
|
+//插入文本
|
|
|
+const temTextVal = ref('')
|
|
|
+function handleInsertText(content) {
|
|
|
+ if(currentState.activeId) { //编辑
|
|
|
+ currentState.activeContent=content
|
|
|
+ if(currentState.activeCindex>=0&¤tState.activeCindex!==''){
|
|
|
+ smartState.conList[currentState.activePindex].child[currentState.activeCindex].content=content
|
|
|
+ }else{
|
|
|
+ smartState.conList[currentState.activePindex].content = content
|
|
|
+ console.log(smartState.conList[currentState.activePindex])
|
|
|
+ }
|
|
|
+ }else { //新增
|
|
|
+
|
|
|
+ let tempCompData = {
|
|
|
+ compId:1,
|
|
|
+ compType:'text',
|
|
|
+ id:getCompId(1),
|
|
|
+ content:content,
|
|
|
+ style:'',
|
|
|
+ child:[]
|
|
|
+ }
|
|
|
+ if(insertState.activeId) {
|
|
|
+ smartState.conList.splice(insertState.activePindex+1,0,tempCompData)
|
|
|
+ }else {
|
|
|
+ smartState.conList.splice(0,0,tempCompData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(smartState.conList)
|
|
|
+ showReportInsertPop.value = false
|
|
|
+}
|
|
|
+//插入图片
|
|
|
+const temImgVal=ref('')
|
|
|
+function handleInsertImg(e) {
|
|
|
+ if(temImgVal.value) { //编辑
|
|
|
+ currentState.activeContent=e
|
|
|
+ if(currentState.activeCindex>=0&¤tState.activeCindex!==''){
|
|
|
+ smartState.conList[currentState.activePindex].child[currentState.activeCindex].content=e
|
|
|
+ }else{
|
|
|
+ smartState.conList[currentState.activePindex].content = e
|
|
|
+ }
|
|
|
+ }else { //新增
|
|
|
+ let tempCompData = {
|
|
|
+ compId:2,
|
|
|
+ compType:'img',
|
|
|
+ id:getCompId(2),
|
|
|
+ content:e,
|
|
|
+ style:'',
|
|
|
+ child:[]
|
|
|
+ }
|
|
|
+ if(insertState.activeId) {
|
|
|
+ smartState.conList.splice(insertState.activePindex+1,0,tempCompData)
|
|
|
+ }else {
|
|
|
+ smartState.conList.splice(0,0,tempCompData)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ showReportInsertPop.value = false
|
|
|
+}
|
|
|
+function getCompId(type) {
|
|
|
+ return type+new Date().getTime()
|
|
|
+}
|
|
|
+
|
|
|
+// 更新sheet表格高度
|
|
|
+function reInitSheetIframe(e){
|
|
|
+ const { height,code } = e.data;
|
|
|
+ let iframeDom = document.getElementsByClassName(`iframe${code}`)
|
|
|
+ Array.prototype.forEach.call(iframeDom, function (ele) {
|
|
|
+ ele.height = `${height}px`;
|
|
|
+ });
|
|
|
+}
|
|
|
+onMounted(()=>{
|
|
|
+ window.addEventListener('message',reInitSheetIframe)
|
|
|
+})
|
|
|
+onUnmounted(()=>{
|
|
|
+ window.removeEventListener('message',reInitSheetIframe)
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//更多设置弹窗
|
|
|
+const showMoreHandlePop = ref(false)
|
|
|
+const showLayoutPop = ref(false)
|
|
|
+const showBgPop = ref(false)
|
|
|
+const temBgVar=ref("")
|
|
|
+//设置版图
|
|
|
+function handleConfirmSetLayout(e) {
|
|
|
+ if(e.type=='1'){
|
|
|
+ showToast('版头设置成功')
|
|
|
+ smartState.headImg=e.data.ImgUrl
|
|
|
+ smartState.headImgId = e.data.ResourceId
|
|
|
+ smartState.headImgStyle=e.data.Style?JSON.parse(e.data.Style):[]
|
|
|
+ }else{
|
|
|
+ showToast('版尾设置成功')
|
|
|
+ smartState.endImg=e.data.ImgUrl
|
|
|
+ smartState.endImgId = e.data.ResourceId
|
|
|
+ smartState.endImgStyle=e.data.Style?JSON.parse(e.data.Style):[]
|
|
|
+ }
|
|
|
+ contentChange.value=true
|
|
|
+ showLayoutPop.value = false
|
|
|
+}
|
|
|
+function handleOpenBgPop() {
|
|
|
+ temBgVar.value=smartState.bgColor||''
|
|
|
+ showMoreHandlePop.value=false
|
|
|
+ showBgPop.value=true;
|
|
|
+}
|
|
|
+//设置背景色
|
|
|
+function handleConfirmBgColor() {
|
|
|
+ smartState.bgColor=temBgVar.value||''
|
|
|
+ contentChange.value=true
|
|
|
+ showBgPop.value = false
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* 报告流程操作 */
|
|
|
+const { handleRefresh,handlePublishReportHook,handleDSPublish,showDSFBTime } = useReportHandles()
|
|
|
+// 报告基本信息
|
|
|
+const showReportBaseInfo=ref(false)
|
|
|
+let reportBaseInfoData={
|
|
|
+ addType:1,
|
|
|
+ classifyName:[],
|
|
|
+ author:['FICC团队'],
|
|
|
+ frequency: ['日度'],
|
|
|
+ createtime:moment().format('YYYY-MM-DD'),
|
|
|
+ title:'',
|
|
|
+ abstract:'',
|
|
|
+ cooperationType:1,
|
|
|
+ cooperationUsers:[],
|
|
|
+ reportLayout: 1,
|
|
|
+ isPublcPublish: 1
|
|
|
+}
|
|
|
+async function handleReportBaseInfoChange(e){
|
|
|
+ reportBaseInfoData={
|
|
|
+ ...e,
|
|
|
+ classifyName:e.classifys,
|
|
|
+ createtime:e.time,
|
|
|
+ }
|
|
|
+
|
|
|
+ const classify = e.classifys.map(i=>i.id)
|
|
|
+ checkClassifyNameArr(1,classify)
|
|
|
+ showReportBaseInfo.value=false
|
|
|
+}
|
|
|
+
|
|
|
+// 刷新所有图表
|
|
|
+async function handleRefreshAllChart(){
|
|
|
+ handleRefresh({ id: Number(route.query.id),chapterId:Number(route.query.chapterId) })
|
|
|
+}
|
|
|
+
|
|
|
+//预览
|
|
|
+async function handlePreviewReport() {
|
|
|
+ if(document.getElementById('report-html-content')) {
|
|
|
+ // 存一次草稿
|
|
|
+ const saveRes=await autoSaveReportContent("auto")
|
|
|
+ if(!saveRes) return
|
|
|
+ }
|
|
|
+ router.push({
|
|
|
+ path:'/report/preview',
|
|
|
+ query:{
|
|
|
+ id: reportInfo.value.Id
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+/* 保存 定时保存 */
|
|
|
+function autoSaveReportContent(type="auto") {
|
|
|
+ if(!route.query.id) return
|
|
|
+
|
|
|
+ const html= handleContentFormat()
|
|
|
+ return new Promise(async (resolve,reject)=>{
|
|
|
+
|
|
|
+ let imgParams = {
|
|
|
+ HeadImg:smartState.headImg,
|
|
|
+ EndImg:smartState.endImg,
|
|
|
+ HeadResourceId:smartState.headImgId,
|
|
|
+ EndResourceId:smartState.endImgId,
|
|
|
+ CanvasColor:smartState.bgColor
|
|
|
+ }
|
|
|
+
|
|
|
+ const res=await apiReport.reportContentSave({
|
|
|
+ ReportId:Number(route.query.id),
|
|
|
+ Content:html,
|
|
|
+ ContentStruct:JSON.stringify(smartState.conList),
|
|
|
+ NoChange:contentChange.value?0:1,
|
|
|
+ ...imgParams
|
|
|
+ })
|
|
|
+ if(res.Ret === 200) {
|
|
|
+ resolve(true)
|
|
|
+ type==='save' && showToast("保存成功");
|
|
|
+ contentChange.value=false
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+//处理内容格式
|
|
|
+function handleContentFormat() {
|
|
|
+ let htmlStr = document.getElementById('report-html-content').outerHTML.replace(/contenteditable="true"/g,'contenteditable="false"').replace(/comp-insert-add"/g,'comp-insert-add" style="display:none"');
|
|
|
+
|
|
|
+ contentChange.value = true;
|
|
|
+ return htmlStr
|
|
|
+}
|
|
|
+
|
|
|
+//发布,定时发布,提交
|
|
|
+async function handlePublishReport(tp) {
|
|
|
+ cachedViewsStore.removeCaches('ReportList')
|
|
|
+ if(document.getElementById('report-html-content')) {
|
|
|
+ // 存一次草稿
|
|
|
+ const saveRes=await autoSaveReportContent("auto")
|
|
|
+ if(!saveRes) return
|
|
|
+ }
|
|
|
+
|
|
|
+ handlePublishReportHook(tp,reportInfo.value)
|
|
|
+}
|
|
|
+
|
|
|
+// 定时发布报告选择时间
|
|
|
+function onConfirmDSFBTime(time){
|
|
|
+ // console.log(time);
|
|
|
+ handleDSPublish(time,reportInfo.value)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const { handlePublishChapterApi } = useChapterRepoprtHandles()
|
|
|
+//预览章节
|
|
|
+async function handlePreviewChapter() {
|
|
|
+ const saveRes = await autoSaveReportChapter('auto');
|
|
|
+ if(!saveRes) return
|
|
|
+
|
|
|
+ router.push({
|
|
|
+ path:'/report/chapter/preview',
|
|
|
+ query:{
|
|
|
+ id:reportInfo.value.ReportChapterId
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 自动保存章节报告
|
|
|
+async function autoSaveReportChapter(type="auto"){
|
|
|
+ if(!route.query.chapterId) return
|
|
|
+ const html = handleContentFormat();
|
|
|
+
|
|
|
+ return new Promise(async (resolve,reject)=>{
|
|
|
+ const res=await apiReport.chapterDetailSave({
|
|
|
+ ReportChapterId:Number(route.query.chapterId),
|
|
|
+ Content: html,
|
|
|
+ ContentStruct:JSON.stringify(smartState.conList)
|
|
|
+ })
|
|
|
+ if(res.Ret === 200) {
|
|
|
+ resolve(true)
|
|
|
+ type==='save' && showToast("保存成功");
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/* 提交章节 */
|
|
|
+async function handlePublishChapter() {
|
|
|
+ const saveRes = await autoSaveReportChapter('auto');
|
|
|
+ if(!saveRes) return
|
|
|
+
|
|
|
+ handlePublishChapterApi(reportInfo.value.ReportChapterId)
|
|
|
+}
|
|
|
+
|
|
|
+const {
|
|
|
+ conList,
|
|
|
+ bgColor,
|
|
|
+ headImg,
|
|
|
+ endImg,
|
|
|
+ headImgId,
|
|
|
+ endImgId,
|
|
|
+ headImgStyle,
|
|
|
+ endImgStyle,
|
|
|
+ layoutBaseInfo
|
|
|
+} = toRefs(smartState)
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="add-report-page">
|
|
|
+ <div class="main-wrap" :style="{backgroundColor:bgColor}">
|
|
|
+
|
|
|
+ <div class="report-content-box" id="report-content-box" >
|
|
|
+
|
|
|
+ <!-- 版头 -->
|
|
|
+ <div class="html-head-img-box">
|
|
|
+ <div class="opt-btn-box" style="display: none;">
|
|
|
+ <van-icon name="delete-o" @click.stop="deleteLayoutPic(1)" color="#f00" size="22"/>
|
|
|
+ </div>
|
|
|
+ <img :src="headImg" alt="" style="display:block;width:100%">
|
|
|
+ <div class="head-layout-item" v-for="item in headImgStyle" :key="item.value"
|
|
|
+ :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
|
|
|
+ width:item.width,height:item.height,left:item.left,top:item.top
|
|
|
+ }">
|
|
|
+ {{ layoutBaseInfo[item.value] }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="add-comp-wrapper">
|
|
|
+ <van-popover v-model:show="showPopover">
|
|
|
+ <van-grid
|
|
|
+ square
|
|
|
+ clickable
|
|
|
+ :border="false"
|
|
|
+ column-num="3"
|
|
|
+ style="width: 240px;"
|
|
|
+ >
|
|
|
+ <van-grid-item
|
|
|
+ v-for="i in compType"
|
|
|
+ :key="i.id"
|
|
|
+ :text="i.text"
|
|
|
+ :icon="i.icon"
|
|
|
+ @click="handleOpenComPop(i)"
|
|
|
+ />
|
|
|
+ </van-grid>
|
|
|
+ <template #reference>
|
|
|
+ <svg-icon name="add-comp" size="40"/>
|
|
|
+ </template>
|
|
|
+ </van-popover>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <draggable
|
|
|
+ :list="conList"
|
|
|
+ item-key="id"
|
|
|
+ :group="{ name: 'component', pull: true, put: true }"
|
|
|
+ handle=".drag-btn_p"
|
|
|
+ class="report-html-wrap"
|
|
|
+ id="report-html-content"
|
|
|
+ animation="300"
|
|
|
+ tag="div"
|
|
|
+ >
|
|
|
+ <template #item="{element,index}">
|
|
|
+ <div
|
|
|
+ :class="[
|
|
|
+ 'report-drag-item-wrap',
|
|
|
+ currentState.activeId===element.id?'blue-bg':'',
|
|
|
+ element.child&&!element.child.length?'report-drag-item-out':''
|
|
|
+ ]"
|
|
|
+ :comp-type="element.compType"
|
|
|
+ @click="handleChoose(element,index)"
|
|
|
+ :style="element.style"
|
|
|
+ >
|
|
|
+ <div class="resize-drag-box" @mousedown.stop="handleResizeP($event,index)"></div>
|
|
|
+ <div class="opt-btn-box" style="display: none;">
|
|
|
+ <van-icon name="delete-o" @click.stop="handleDelItem(index,-1)" color="#f00" size="22"/>
|
|
|
+ <div class="drag-btn drag-btn_p"></div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="element.child&&!element.child.length"
|
|
|
+ class="report-drag-item-wrap_content"
|
|
|
+ style="width:100%;height:100%"
|
|
|
+ :data-id="element.id"
|
|
|
+ >
|
|
|
+ <component :is="getComponentName(element)" :compData="element"/>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 插入 -->
|
|
|
+ <div class="add-comp-wrapper comp-insert-add" @click.stop>
|
|
|
+ <van-popover v-model:show="element.showAddPopover">
|
|
|
+ <van-grid
|
|
|
+ square
|
|
|
+ clickable
|
|
|
+ :border="false"
|
|
|
+ column-num="3"
|
|
|
+ style="width: 240px;"
|
|
|
+ >
|
|
|
+ <van-grid-item
|
|
|
+ v-for="i in compType"
|
|
|
+ :key="i.id"
|
|
|
+ :text="i.text"
|
|
|
+ :icon="i.icon"
|
|
|
+ @click.stop="handleOpenInsertCompPop(i,{element,index})"
|
|
|
+ />
|
|
|
+ </van-grid>
|
|
|
+ <template #reference>
|
|
|
+ <svg-icon name="add-comp" size="40"/>
|
|
|
+ </template>
|
|
|
+ </van-popover>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <draggable
|
|
|
+ :list="element.child"
|
|
|
+ item-key="id"
|
|
|
+ :group="{ name: 'component', pull: true, put: element.child&&element.child.length<3?true:false }"
|
|
|
+ handle=".drag-btn_c"
|
|
|
+ animation="300"
|
|
|
+ tag="div"
|
|
|
+ class="report-drag-item-wrap_child-wrap"
|
|
|
+ @add="handleChildAdd($event,element,index)"
|
|
|
+ @remove="handleChildRemove($event,element.child)"
|
|
|
+ style="display: flex;gap: 3px;align-items: flex-start;"
|
|
|
+ >
|
|
|
+ <template #item="child">
|
|
|
+ <div
|
|
|
+ :class="['report-drag-item-wrap_child_content',currentState.activeId===child.element.id?'blue-bg':'']"
|
|
|
+ :comp-type="child.element.compType"
|
|
|
+ :data-id="child.element.id"
|
|
|
+ @click.stop="handleChoose(child.element,index,child.index)"
|
|
|
+ style="flex:1"
|
|
|
+ :style="child.element.style"
|
|
|
+ >
|
|
|
+ <div class="opt-btn-box2" style="display: none;">
|
|
|
+ <div class="drag-btn drag-btn_c"></div>
|
|
|
+ <van-icon name="delete-o" @click.stop="handleDelItem(index,child.index)" color="#f00" size="22"/>
|
|
|
+ </div>
|
|
|
+ <!-- 拖动按钮 -->
|
|
|
+ <div class="resize-drag-box_lb" @mousedown.stop="handleResizeC($event,index,child.index,'lb')"></div>
|
|
|
+ <div class="resize-drag-box_rb" @mousedown.stop="handleResizeC($event,index,child.index,'rb')"></div>
|
|
|
+ <component :is="getComponentName(child.element)" :compData="child.element"/>
|
|
|
+ <!-- -->
|
|
|
+ <div class="mark-box" v-if="isDragResize" style="position: absolute;left:0;right:0;top:0;bottom: 0;z-index: 10;"></div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </draggable>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </draggable>
|
|
|
+
|
|
|
+ <!-- 版尾 -->
|
|
|
+ <div class="html-end-img-box">
|
|
|
+ <div class="opt-btn-box" style="display: none;">
|
|
|
+ <van-icon name="delete-o" @click.stop="deleteLayoutPic(2)" color="#f00" size="22"/>
|
|
|
+ </div>
|
|
|
+ <img :src="endImg" alt="" style="display:block;width:100%">
|
|
|
+ <div class="head-layout-item" v-for="item in endImgStyle" :key="item.value"
|
|
|
+ :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
|
|
|
+ width:item.width,height:item.height,left:item.left,top:item.top
|
|
|
+ }">
|
|
|
+ {{ layoutBaseInfo[item.value] }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 底部操作 -->
|
|
|
+ <div class="bot-action-box">
|
|
|
+ <div class="left-box" v-if="reportInfo">
|
|
|
+ <div class="item" @click="showReportBaseInfo=true" v-if="!reportInfo.ReportChapterId">
|
|
|
+ <img src="@/assets/imgs/report/icon_info.png" alt="">
|
|
|
+ <span>基础信息</span>
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="handleRefreshAllChart">
|
|
|
+ <img src="@/assets/imgs/report/icon_refresh.png" alt="">
|
|
|
+ <span>刷新</span>
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="reportInfo.ReportChapterId?handlePreviewChapter():handlePreviewReport()" v-permission="reportManageBtn.reportManage_reportView">
|
|
|
+ <img src="@/assets/imgs/report/icon_preview.png" alt="">
|
|
|
+ <span>预览</span>
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="reportInfo.ReportChapterId?autoSaveReportChapter('save'):autoSaveReportContent('save')" v-permission="reportManageBtn.reportManage_publish">
|
|
|
+ <img src="@/assets/imgs/report/icon_save2.png" alt="">
|
|
|
+ <span>保存</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 章节报告提交章节 -->
|
|
|
+ <div
|
|
|
+ class="item"
|
|
|
+ @click="handlePublishChapter"
|
|
|
+ v-permission="reportManageBtn.reportManage_publish"
|
|
|
+ v-if="reportInfo.ReportChapterId"
|
|
|
+ >
|
|
|
+ <img src="@/assets/imgs/report/icon_publish3.png" alt="">
|
|
|
+ <span>提交</span>
|
|
|
+ </div>
|
|
|
+ <!-- 单人报告提交发布 -->
|
|
|
+ <template v-else>
|
|
|
+ <template v-if="!isApprove||!hasApproveFlow">
|
|
|
+ <div class="item" @click="handlePublishReport('dsfb')" v-permission="reportManageBtn.reportManage_publish">
|
|
|
+ <img src="@/assets/imgs/report/icon_time.png" alt="">
|
|
|
+ <span>定时发布</span>
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="handlePublishReport('fb')" v-permission="reportManageBtn.reportManage_publish">
|
|
|
+ <img src="@/assets/imgs/report/icon_publish3.png" alt="">
|
|
|
+ <span>发布</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-if="isApprove&&hasApproveFlow">
|
|
|
+ <div class="item" @click="handlePublishReport('submit')" >
|
|
|
+ <img src="@/assets/imgs/report/icon_publish3.png" alt="">
|
|
|
+ <span>提交</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="item" @click="showMoreHandlePop=true" v-if="!reportInfo.ReportChapterId">
|
|
|
+ <van-icon name="ellipsis" size="24"/>
|
|
|
+ <div>更多设置</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 报告插入数据模块 -->
|
|
|
+ <van-popup
|
|
|
+ v-model:show="showReportInsertPop"
|
|
|
+ position="bottom"
|
|
|
+ round
|
|
|
+ >
|
|
|
+ <!-- 文字插入 -->
|
|
|
+ <TextEditor
|
|
|
+ v-if="showInsertCompType===1"
|
|
|
+ :defaultVal="temTextVal"
|
|
|
+ @close="showReportInsertPop=false;temTextVal=''"
|
|
|
+ @confirm="handleInsertText"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 图片 -->
|
|
|
+ <ImgEditor
|
|
|
+ v-else-if="showInsertCompType===2"
|
|
|
+ :defaultVal="temImgVal"
|
|
|
+ @close="showReportInsertPop=false;temImgVal=''"
|
|
|
+ @confirm="handleInsertImg"
|
|
|
+ />
|
|
|
+ <!-- 图表资源 -->
|
|
|
+ <ReportInsertContent v-if="showInsertCompType===3" @insert="handleChartInsert"/>
|
|
|
+ </van-popup>
|
|
|
+
|
|
|
+ <!-- 报告基础信息 -->
|
|
|
+ <van-popup
|
|
|
+ v-model:show="showReportBaseInfo"
|
|
|
+ position="bottom"
|
|
|
+ :style="{ height: '100%' }"
|
|
|
+ >
|
|
|
+ <AddReportBaseInfoV2
|
|
|
+ @close="showReportBaseInfo=false"
|
|
|
+ :id="Number(route.query.id)"
|
|
|
+ :defaultData="reportBaseInfoData"
|
|
|
+ @confirm="handleReportBaseInfoChange"
|
|
|
+ />
|
|
|
+ </van-popup>
|
|
|
+
|
|
|
+ <!-- 定时发布选择时间 -->
|
|
|
+ <ReportPublishTimeSet
|
|
|
+ v-model="showDSFBTime"
|
|
|
+ :prePublishTime="reportInfo?.PrePublishTime"
|
|
|
+ @confirm="onConfirmDSFBTime"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 更多操作 背景色 版图 -->
|
|
|
+ <van-action-sheet
|
|
|
+ teleport="body"
|
|
|
+ v-model:show="showMoreHandlePop"
|
|
|
+ cancel-text="取消"
|
|
|
+ close-on-click-action
|
|
|
+ >
|
|
|
+ <div class="report-item-action-box">
|
|
|
+
|
|
|
+ <div class="item" @click="showLayoutPop=true;showMoreHandlePop=false">版图选择</div>
|
|
|
+ <div class="item" @click="handleOpenBgPop">背景色设置</div>
|
|
|
+ </div>
|
|
|
+ </van-action-sheet>
|
|
|
+
|
|
|
+ <!-- 版图设置 -->
|
|
|
+ <van-popup
|
|
|
+ v-model:show="showLayoutPop"
|
|
|
+ position="bottom"
|
|
|
+ >
|
|
|
+ <ReportLayoutImg
|
|
|
+ v-if="showLayoutPop"
|
|
|
+ @close="showLayoutPop=false"
|
|
|
+ @confirm="handleConfirmSetLayout"
|
|
|
+ />
|
|
|
+ </van-popup>
|
|
|
+
|
|
|
+ <!-- 背景色设置 -->
|
|
|
+ <van-popup
|
|
|
+ v-model:show="showBgPop"
|
|
|
+ position="bottom"
|
|
|
+ :style="{ height: '50%' }"
|
|
|
+ >
|
|
|
+ <div class="top-box">
|
|
|
+ <span style="color:#666666" @click="showBgPop=false">取消</span>
|
|
|
+ <span style="font-size:18px;font-weight:bold">背景色设置</span>
|
|
|
+ <span style="color:#0052D9" @click="handleConfirmBgColor">确定</span>
|
|
|
+ </div>
|
|
|
+ <div class="color-box">
|
|
|
+ <span>颜色选择</span>
|
|
|
+ <V3ColorPicker v-model:value="temBgVar" :zIndex="9999"/>
|
|
|
+ </div>
|
|
|
+ </van-popup>
|
|
|
+</template>
|
|
|
+<style scoped lang="scss">
|
|
|
+.add-report-page{
|
|
|
+ height: 100dvh;
|
|
|
+ min-height: 95vh;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.main-wrap{
|
|
|
+ flex: 1;
|
|
|
+ width: calc(100% - 32PX);
|
|
|
+ margin: 0 auto;
|
|
|
+ overflow-y: auto;
|
|
|
+ margin-top: 30px;
|
|
|
+ border: 1px solid #DCDFE6;
|
|
|
+
|
|
|
+ .report-drag-item-wrap{
|
|
|
+ width: 100%;
|
|
|
+ padding: 6px;
|
|
|
+ min-height: 80px;
|
|
|
+ border: 1px dashed #0052D9;
|
|
|
+ position: relative;
|
|
|
+ margin-bottom: 120px;
|
|
|
+ &:hover{
|
|
|
+ border-style: solid;
|
|
|
+ .opt-btn-box{
|
|
|
+ display: block !important;
|
|
|
+ }
|
|
|
+ .resize-drag-box{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .drag-btn::after{
|
|
|
+ content: '';
|
|
|
+ display: block;
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ background-image: url('@/assets/imgs/report/icon_drag.png');
|
|
|
+ background-size: cover;
|
|
|
+ cursor:move;
|
|
|
+ }
|
|
|
+ .opt-btn-box{
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ padding: 6px 10px 0;
|
|
|
+ top: -80px;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid #ECF2FE;
|
|
|
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.04);
|
|
|
+
|
|
|
+ .drag-btn {
|
|
|
+ display: inline-block;
|
|
|
+ margin-left: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .resize-drag-box{
|
|
|
+ position: absolute;
|
|
|
+ right: -4px;
|
|
|
+ bottom: -4px;
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ display: none;
|
|
|
+ border: 1px solid #0052D9;
|
|
|
+ cursor: nw-resize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .report-drag-item-out{
|
|
|
+ .report-drag-item-wrap_child-wrap{
|
|
|
+ position: absolute;
|
|
|
+ width: 40px;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .report-drag-item-wrap_child_content{
|
|
|
+ min-height: 80px;
|
|
|
+ border: 1px dashed #0052D9;
|
|
|
+ flex: 1;
|
|
|
+ position: relative;
|
|
|
+ &:hover{
|
|
|
+ border-style: solid;
|
|
|
+ .opt-btn-box2{
|
|
|
+ display: block !important;
|
|
|
+ }
|
|
|
+ .resize-drag-box_lt,
|
|
|
+ .resize-drag-box_lb,
|
|
|
+ .resize-drag-box_rt,
|
|
|
+ .resize-drag-box_rb{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .opt-btn-box2{
|
|
|
+ position: absolute;
|
|
|
+ padding: 6px 4px;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ z-index: 10;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid #ECF2FE;
|
|
|
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.04);
|
|
|
+ .drag-btn {
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .resize-drag-box_lt,
|
|
|
+ .resize-drag-box_lb,
|
|
|
+ .resize-drag-box_rt,
|
|
|
+ .resize-drag-box_rb{
|
|
|
+ position: absolute;
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ display: none;
|
|
|
+ border: 1px solid #0052D9;
|
|
|
+ }
|
|
|
+ .resize-drag-box_lt{
|
|
|
+ left: -4px;
|
|
|
+ top: -4px;
|
|
|
+ cursor: nw-resize;
|
|
|
+ }
|
|
|
+ .resize-drag-box_lb{
|
|
|
+ left: -4px;
|
|
|
+ bottom: -4px;
|
|
|
+ cursor: ne-resize;
|
|
|
+ }
|
|
|
+ .resize-drag-box_rt{
|
|
|
+ right: -4px;
|
|
|
+ top: -4px;
|
|
|
+ cursor: ne-resize;
|
|
|
+ }
|
|
|
+ .resize-drag-box_rb{
|
|
|
+ right: -4px;
|
|
|
+ bottom: -4px;
|
|
|
+ cursor: nw-resize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .blue-bg{
|
|
|
+ background: var(--brand-brand-1-light, #ECF2FE);
|
|
|
+ }
|
|
|
+}
|
|
|
+.report-content-box{
|
|
|
+ width: 100%;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 20px;
|
|
|
+ .html-head-img-box,.html-end-img-box{
|
|
|
+ position: relative;
|
|
|
+ &:hover{
|
|
|
+ .opt-btn-box{
|
|
|
+ display: block !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .opt-btn-box{
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ padding: 6px 10px 0;
|
|
|
+ top: -60px;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid #ECF2FE;
|
|
|
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.04);
|
|
|
+ }
|
|
|
+ .head-layout-item{
|
|
|
+ position: absolute;
|
|
|
+ overflow: hidden;
|
|
|
+ box-sizing: border-box
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.add-comp-wrapper {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ .add-ico {
|
|
|
+ background: $theme-color;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+}
|
|
|
+.bot-action-box{
|
|
|
+ padding: 20px 16PX;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .left-box{
|
|
|
+ flex: 1;
|
|
|
+ background: #FFFFFF;
|
|
|
+ box-shadow: 0px 12px 60px 10px rgba(0, 0, 0, 0.05), 0px 32px 48px 4px rgba(0, 0, 0, 0.04), 0px 16px 20px -10px rgba(0, 0, 0, 0.08);
|
|
|
+ border-radius: 100px;
|
|
|
+ height: 112px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-right: 20px;
|
|
|
+ padding: 0 20px;
|
|
|
+ .item{
|
|
|
+ flex: 1;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 20px;
|
|
|
+ img{
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ display: block;
|
|
|
+ margin: 5px auto;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right-btn{
|
|
|
+ flex-shrink: 0;
|
|
|
+ position: relative;
|
|
|
+ width: 96px;
|
|
|
+ height: 96px;
|
|
|
+ background-color: $theme-color;
|
|
|
+ border-radius: 50%;
|
|
|
+ box-shadow: 0px 6px 28px 4px rgba(0, 0, 0, 0.05), 0px 16px 20px 2px rgba(0, 0, 0, 0.06), 0px 10px 10px -6px rgba(0, 0, 0, 0.1);
|
|
|
+ svg{
|
|
|
+ width: 27px;
|
|
|
+ height: 27px;
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%,-50%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.report-item-action-box{
|
|
|
+ .item{
|
|
|
+ padding: 20px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 32px;
|
|
|
+ border-top: 1px solid $border-color;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.top-box{
|
|
|
+ padding:32px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ border-bottom: 1px solid #DCDFE6;
|
|
|
+ .close{
|
|
|
+ color:#666666;
|
|
|
+ }
|
|
|
+ .title{
|
|
|
+ font-size: 36px;
|
|
|
+ }
|
|
|
+ .add-btn{
|
|
|
+ color:$theme-color;
|
|
|
+ }
|
|
|
+}
|
|
|
+.color-box {
|
|
|
+ padding: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.comp-insert-add {
|
|
|
+ position: absolute;
|
|
|
+ bottom: -110px;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+}
|
|
|
+@media screen and (min-width:$media-width){
|
|
|
+ .add-report-page{
|
|
|
+ height: calc(100dvh - 60px);
|
|
|
+ min-height: calc(95vh - 60px);
|
|
|
+ }
|
|
|
+ .report-content-box{
|
|
|
+ .html-head-img-box,.html-end-img-box{
|
|
|
+ .opt-btn-box{
|
|
|
+ top:-32px;
|
|
|
+ padding: 6px 10px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .bot-action-box{
|
|
|
+ margin: 0 auto;
|
|
|
+ width: 600px;
|
|
|
+ padding: 10px 16px;
|
|
|
+ .left-box{
|
|
|
+ border-radius: 50px;
|
|
|
+ height: 56px;
|
|
|
+ margin-right: 10px;
|
|
|
+ padding: 0 10px;
|
|
|
+ .item{
|
|
|
+ font-size: 12px;
|
|
|
+ img{
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ margin: 3px auto;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right-btn{
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ svg{
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .main-wrap{
|
|
|
+ margin-top: 20px;
|
|
|
+ max-width: 800px;
|
|
|
+ .report-content-box {
|
|
|
+ padding: 20px ;
|
|
|
+ }
|
|
|
+ .report-drag-item-wrap {
|
|
|
+ margin-bottom: 80px;
|
|
|
+
|
|
|
+ .drag-btn::after{
|
|
|
+ width: 22px;
|
|
|
+ height: 22px;
|
|
|
+ }
|
|
|
+ .opt-btn-box{
|
|
|
+ top:-42px;
|
|
|
+ padding: 6px 10px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .report-item-action-box{
|
|
|
+ .item{
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .comp-insert-add {
|
|
|
+ bottom: -60px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|