jwyu 1 éve
szülő
commit
3b92f188a9

+ 32 - 8
src/api/modules/smartReport.js

@@ -15,17 +15,12 @@ const apiSmartReport={
 
     //删除报告
     delReport:params=>{
-        return http.post('/report/delete',params)
+        return http.post('/smart_report/remove',params)
     },
 
     //报告推送
     reportMsgSend:params=>{
-        return http.post('/report/ths/sendTemplateMsg',params)
-    },
-
-    //报告取消发布
-    publishCancel:params=>{
-        return http.post('/report/publish/cancle',params)
+        return http.post('/smart_report/send_msg',params)
     },
 
     // 作者
@@ -46,8 +41,37 @@ const apiSmartReport={
     //报告详情
     reportDetail:params=>{
         return http.get('/smart_report/detail',params)
-    }
+    },
+
+    //保存报告内容
+    saveReportContent:params=>{
+        return http.post('/smart_report/save_content',params)
+    },
+
+    //定时发布报告
+    prePublishReport:params=>{
+        return http.post('/smart_report/pre_publish',params)
+    },
 
+    //发布/取消发布报告
+    publishReport:params=>{
+        return http.post('/smart_report/publish',params)
+    },
+
+    //编辑状态
+    markReport:params=>{
+        return http.post('/smart_report/mark_edit',params)
+    },
+
+    //音频上传
+    voiceupload:params=>{
+        return http.post('/smart_report/voice_upload',params)
+    },
+
+    //报告导出图片
+    getReportImg:params=>{
+        return http.get('/smart_report/detail_img',params)
+    }
 
 }
 

BIN
src/assets/img/smartReport/bg01.png


BIN
src/assets/img/smartReport/icon16.png


+ 6 - 0
src/routes/modules/oldRoutes.js

@@ -58,6 +58,12 @@ export default [
     name: "智能报告",
     component: () => import("@/views/smartReport/editReport.vue"),
   },
+  // 智能研报详情页
+  {
+    path: "/smartReportDetail",
+    name: "智能报告",
+    component: () => import("@/views/smartReport/reportDetail.vue"),
+  },
 
   // 主页
   {

+ 20 - 0
src/utils/buttonConfig.js

@@ -34,6 +34,26 @@ export const reportManageBtn={
     reportManage_dayWeekReportAdd:'reportManage:dayWeekReportAdd',//添加晨报周报
     reportManage_reportAdd:'reportManage:reportAdd',//添加研报
 }
+/*
+ *--------智能研报列表----------- 
+ */
+ export const smartReportManageBtn={
+    reportManage_sendMsg:'smartReportManage:sendMsg',//推送消息/已推送消息
+    reportManage_reportView:'smartReportManage:reportView',//研报预览:即是否能点击研报名称跳转预览页面
+    reportManage_reportView_wechartShare:'smartReportManage:reportView:wechartShare',//研报预览页面-微信分享
+    reportManage_reportView_copyWechat:'smartReportManage:reportView:copyWechat',//研报预览页面-复制链接
+    reportManage_reportView_exportImg:'smartReportManage:reportView:exportImg',//研报预览页面-导出图片
+    reportManage_audioDownload:'smartReportManage:audioDownload',//音频下载
+    reportManage_audioUpload:'smartReportManage:audioUpload',//音频上传
+    reportManage_reportDel:'smartReportManage:reportDel',//删除研报
+    reportManage_reportEdit:'smartReportManage:reportEdit',//编辑研报
+    reportManage_cancelPublish:'smartReportManage:cancelPublish',//取消发布
+    reportManage_publish:'smartReportManage:publish',//发布研报
+    reportManage_reportList:'smartReportManage:reportList',//研报列表的选项
+    reportManage_reportList_uv:'smartReportManage:reportList:uv',//研报列表-PV/UV
+    reportManage_reportList_sendTime:'smartReportManage:reportList:sendTime',//研报列表-报告推送时间
+    reportManage_reportAdd:'smartReportManage:reportAdd',//添加研报
+}
 /*
 *--------英文研报列表----------- 
 */

+ 1 - 1
src/views/smartReport/components/ChartComp.vue

@@ -1,7 +1,7 @@
 <template>
     <div 
         class="report-comp-item chart-comp"
-        style="height:300px;width:100%;overflow: hidden;"
+        style="min-height:300px;width:100%;height:100%;overflow: hidden;"
     >
         <iframe :src="compData.content" style="width:100%;height:100%;border-width:0px; "></iframe>
     </div>

+ 0 - 4
src/views/smartReport/components/ImgComp.vue

@@ -14,7 +14,3 @@ export default {
     }
 }
 </script>
-
-<style>
-
-</style>

+ 478 - 31
src/views/smartReport/editReport.vue

@@ -8,23 +8,23 @@
                     <img src="~@/assets/img/smartReport/icon01.png" alt="">
                     <span>基础信息</span>
                 </li>
-                <li class="action-item">
+                <li class="action-item" @click="handleRefreshAllChart">
                     <img src="~@/assets/img/smartReport/icon02.png" alt="">
                     <span>图表刷新 </span>
                 </li>
-                <li class="action-item">
+                <li class="action-item" @click="handlePreviewReport">
                     <img src="~@/assets/img/smartReport/icon03.png" alt="">
                     <span>预览</span>
                 </li>
-                <li class="action-item">
+                <li class="action-item" @click="handleSaveContent">
                     <img src="~@/assets/img/smartReport/icon01.png" alt="">
                     <span>存草稿</span>
                 </li>
-                <li class="action-item">
+                <li class="action-item" @click="handlePublishOpt('dsfb')">
                     <img src="~@/assets/img/smartReport/icon01.png" alt="">
                     <span>定时发布</span>
                 </li>
-                <li class="action-item">
+                <li class="action-item" @click="handlePublishOpt('fb')">
                     <img src="~@/assets/img/smartReport/icon01.png" alt="">
                     <span>发布</span>
                 </li>
@@ -69,10 +69,13 @@
                             :key="item.id"
                             :comp-type="item.compType"
                             @click="handleChoose(item,index)"
+                            :style="item.style"
                         >
-                            <div class="opt-btn-box">
+                            <!-- 缩放的盒子 -->
+                            <div class="resize-drag-box" @mousedown.stop="handleResizeP($event,index)"></div>
+                            <div class="opt-btn-box" style="display: none;">
                                 <div class="drag-btn drag-btn_p"></div>
-                                <div class="del-btn"></div>
+                                <div class="del-btn" @click.stop="handleDelItem(index,-1)"></div>
                             </div>
                             <div 
                                 v-if="item.child&&!item.child.length"
@@ -88,8 +91,9 @@
                                 tag="div"
                                 class="report-drag-item-wrap_child-wrap"
                                 @add="handleChildAdd($event,item)"
-                                @remove="handleChildRemove"
+                                @remove="handleChildRemove($event,item.child)"
                                 handle=".drag-btn_c"
+                                style="display: flex;gap: 20px;align-items: flex-start;"
                             >
                                 <div 
                                     :class="['report-drag-item-wrap_child_content',activeId===child.id?'blue-bg':'']" 
@@ -98,11 +102,16 @@
                                     :comp-type="child.compType"
                                     :data-id="child.id"
                                     @click.stop="handleChoose(child,index,cindex)"
+                                    style="flex:1"
+                                    :style="child.style"
                                 >
-                                    <div class="opt-btn-box2">
+                                    <div class="opt-btn-box2" style="display: none;">
                                         <div class="drag-btn drag-btn_c"></div>
-                                        <div class="del-btn"></div>
+                                        <div class="del-btn" @click.stop="handleDelItem(index,cindex)"></div>
                                     </div>
+                                    <!-- 拖动按钮 -->
+                                    <div class="resize-drag-box_lb" @mousedown.stop="handleResizeC($event,index,cindex,'lb')"></div>
+                                    <div class="resize-drag-box_rb" @mousedown.stop="handleResizeC($event,index,cindex,'rb')"></div>
                                     <component :is="getComponentName(child)" :compData="child"/>
                                 </div>
                             </draggable>
@@ -147,6 +156,34 @@
 
         <!-- 报告基础信息 -->
         <BaseInfo  v-model="showReportBaseInfo" :id="$route.query.id" @save="handleReportEdit" />
+
+        <!-- 定时发布弹窗 -->
+		<el-dialog 
+			v-dialogDrag 
+			:append-to-body="true" 
+			:visible.sync="showDSFB" 
+			width="500px" 
+			title="定时发布"
+		>
+			<div>
+				<div>
+					<span>发送时间</span>
+					<el-date-picker
+						v-model="taskTime"
+						type="datetime"
+						placeholder="选择日期时间"
+						value-format="yyyy-MM-dd HH:mm"
+						:picker-options="timePickerOpt"
+					/>
+				</div>
+				<p style="margin:15px 0">设置成功之后,研报将定时进行发送。</p>
+				<div style="text-align:right;margin:20px 0">
+					<el-button type="primary" plain @click="showDSFB=false">取消</el-button>
+					<el-button type="primary" @click="handleSetReportPrepublish">确定</el-button>
+				</div>
+			</div>
+		</el-dialog>
+
     </div>
 </template>
 
@@ -162,13 +199,14 @@ import ImgEdit from './components/ImgEdit.vue'
 import ETAChart from './components/ETAChart.vue'
 import ETASheet from './components/ETASheet.vue'
 import { getPublicSettingsApi } from '@/api/modules/oldApi';
+import { dataBaseInterface } from "@/api/api.js";
 import {apiSmartReport}  from '@/api/modules/smartReport'
 import BaseInfo from './components/BaseInfo.vue'
 import StatisticAnalysis from './components/StatisticAnalysis.vue'
 import ETAPriceChart from './components/ETAPriceChart.vue'
 import ETASandBox from './components/ETASandBox.vue'
 import SemanticAnalysis from './components/SemanticAnalysis.vue'
-
+import { getUrlParams } from '@/utils/common'
 export default {
     name:"smartReportEdit",
     components: {
@@ -187,6 +225,30 @@ export default {
         ETASandBox,
         SemanticAnalysis
     },
+    watch:{
+        'taskTime'(){
+            this.taskTime=this.$moment(this.taskTime).format('YYYY-MM-DD HH:mm')+':00'
+			const date = this.$moment(this.taskTime).startOf('day').format('x');
+	        const nowDate = this.$moment().startOf('day').format('x');
+	        // 如果选择的是今天 则需要禁用已经过去的时间节点
+	        if (date <= nowDate) {
+	            // 默认选择的最新时间 是当前时间的两分钟后 (留出2分钟的富裕时间)
+	            this.timePickerOpt.selectableRange = (
+	                `${this.$moment().add(2,'m').format('HH:mm:ss')} - 23:59:59`
+	            );
+	        }else {
+				// 如果是以后的日期,则不需要禁用时间节点
+	            this.timePickerOpt.selectableRange = '00:00:00 - 23:59:59';
+	        }
+		},
+        conList:{
+            handler(n,o){
+                console.log('内容改变');
+                this.contentChange=true
+            },
+            deep:true
+        }
+    },
     data() {
         return {
             reportInfo:null,
@@ -251,11 +313,120 @@ export default {
             activePindex:'',
             activeCindex:'',
             showRight:false,
-            rightType:''
+            rightType:'',
+
+            timer:null,//自动保存定时器
+
+            showDSFB:false,//显示定时发布弹窗
+			taskTime:'',//定时发布的时间
+			timePickerOpt:{
+				disabledDate(e){
+					return e.getTime()< new Date().getTime()-24 * 60 * 60 * 1000
+				},
+				selectableRange:'00:00:00 - 23:59:59',
+                format:'HH:mm'
+			},
 
+            contentChange:false,//内容是否发生变化
+
+            isDragResize:false,//是否正在拖动缩放
         }
     },
     methods: {
+        // 大盒子的高度缩放
+        handleResizeP(e,index){
+            this.isDragResize=true
+            e.preventDefault()
+            const targetBox=e.target.parentNode
+            const targetBoxHeight=targetBox.offsetHeight
+            const startY=e.clientY
+            document.onmousemove=(mouseEl)=>{
+                mouseEl.preventDefault()
+                const h=mouseEl.clientY-startY+targetBoxHeight
+                targetBox.style.minHeight=`${h<50?50:h}px`
+            }
+            document.onmouseup=(el)=>{
+                console.log(targetBox.style.cssText);
+                this.$set(this.conList[index],'style',targetBox.style.cssText)
+                el.preventDefault()
+                document.onmousemove=null
+                setTimeout(() => {
+                    this.isDragResize=false
+                }, 50);
+                
+            }
+        },
+        // 内部元素的缩放
+        handleResizeC(e,index,cindex,type){
+            this.isDragResize=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`
+            }   
+            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)=>{
+                        this.$set(this.conList[index].child[idx],'style',item.style.cssText)
+                    })
+                }
+                el.preventDefault()
+                document.onmousemove=null
+                setTimeout(() => {
+                    this.isDragResize=false
+                    document.onmouseup=null
+                }, 50);
+            }
+        },
+
+        // 跳转预览
+        handlePreviewReport(){
+            const htmlStr=$('.report-html-wrap').html()
+            sessionStorage.setItem('smartReportContent', htmlStr);
+			let { href } = this.$router.resolve({ 
+                path: '/smartReportDetail',
+                query:{
+                    id:this.$route.query.id,
+                    type:'preview'
+                }
+            });
+			window.open(href, '_blank');
+        },
+
         // 批量插入myETA数据
         handleImportMyChart(list){
             const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
@@ -309,6 +480,13 @@ export default {
 
             const hasid=item.getAttribute('data-id')
             console.log(hasid);
+
+            this.conList.forEach(item=>{
+                if(item.id==hasid&&item.style){
+                    const styleArr=item.style.split(';').filter(s=>s&&(s.indexOf('width')===-1&&s.indexOf('flex')===-1)).join(';')
+                    item.style=styleArr
+                }
+            })
             if(hasid) return
 
             // 要添加的元素数据
@@ -337,6 +515,7 @@ export default {
             const {item,newDraggableIndex}=e
 
             const compData=JSON.parse(item.getAttribute('comp-data'))
+            if(!compData) return//如果是从内容里面拖入的则不用处理
 
             console.log(compData,newDraggableIndex);
 
@@ -398,25 +577,32 @@ export default {
 
                 this.conList.splice(index,1,obj)
             }
-            // console.log(this.conList);
-
-            // console.log(list,data);
-            // this.conList.forEach(item=>{
-            //     if(item.id===data.id){
-            //         item.child=list
-            //     }
-            // })
         },
 
         // 移除事件 
-        handleChildRemove(e){
+        handleChildRemove(e,arr){
             console.log('child-remove操作------------------->');
             // 如果都移除了则删除这个
-            this.conList=this.conList.filter(_item=>!(_item.child&&_item.child.length===0&&!_item.id))
+            // this.conList=this.conList.filter(_item=>!(_item.child&&_item.child.length===0&&!_item.id))
+
+            // 如果当前移出的这个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只剩一个了则移出来
             this.conList=this.conList.map(_item=>{
                 if(_item.child&&_item.child.length===1){
-                    return _item.child[0]
+                    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
                 }
@@ -427,6 +613,18 @@ export default {
             console.log('container-remove操作------------------->');
         },
 
+        // 点击删除某个
+        handleDelItem(pindex,cindex){
+            if(cindex===-1){
+                this.conList.splice(pindex,1)
+            }else{
+                this.conList[pindex].child.splice(cindex,1)
+                if(this.conList[pindex].child.length===1){
+                    this.conList[pindex]=this.conList[pindex].child[0]
+                }
+            }
+        },
+
         // 富文本编辑组件/图片组件数据变化
         handleTextChange(e){
             console.log(e);
@@ -449,7 +647,7 @@ export default {
         // 当前再编辑哪个
         handleChoose(item,index,cindex){
             //{item:数据,index:父序号,cindex:子序号}
-            if(!item.id) return
+            if(!item.id||this.isDragResize) return
             this.activeId=item.id
             this.showRight=true
             this.rightType=item.compType
@@ -492,7 +690,7 @@ export default {
             return type+new Date().getTime()
         },
 
-        // 编辑报告
+        // 编辑保存报告
         handleReportEdit(e){
             const params={
                 SmartReportId:Number(this.$route.query.id)||0,
@@ -528,10 +726,197 @@ export default {
                 if(res.Ret===200){
                     this.reportInfo=res.Data
                     this.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
+                    this.$nextTick(()=>{
+                        this.contentChange=false
+                    })
                 }
             })
-        }
+        },
+
+        // 刷新所有图表
+        handleRefreshAllChart: _.debounce ( async function() {
+            let code_arr = [];
+            $('iframe').each((k,i) => {
+                try {
+                    let href = $(i).attr('src');
+                    code_arr.push(getUrlParams(href,'code'));
+                } catch (err) {
+                }
+            });
+
+            if(!code_arr.length) return this.$message.warning('请插入图表');
+
+            const loading = this.$loading({
+                lock: true,
+                text: '刷新中..',
+                spinner: 'el-icon-loading',
+                background: 'rgba(0, 0, 0, 0.02)'
+            });
+
+            const { Ret } = await dataBaseInterface.reportRefresh({
+                ChartInfoCode: code_arr
+            })
         
+            loading.close();
+            
+            if(Ret === 200) {
+                $('iframe').each((k,i) => {
+                    $(i).attr('src',$(i).attr('src'))
+                });
+                this.$message.success('刷新成功');
+            }
+
+        },1000),
+        
+        // 自动/存草稿保存内容
+        handleSaveContent({isAutoSave}){
+            return new Promise((resolve,reject)=>{
+                const id=this.$route.query.id||0
+                if(!id) return
+                apiSmartReport.saveReportContent({
+                    SmartReportId:Number(id),
+                    Content:$('.report-html-wrap').html(),
+                    ContentStruct:JSON.stringify(this.conList),
+                    NoChange:this.contentChange?2:1,
+                }).then(res=>{
+                    if(res.Ret===200){
+                        resolve(true)
+                        if(!isAutoSave){
+                            this.$message.success('保存成功')
+                        }
+                    }
+                })
+            })
+        },
+
+        // 点击定时发布/发布
+        async handlePublishOpt(type){
+            // 存一次草稿
+            const saveRes=await this.handleSaveContent({isAutoSave:true})
+            if(!saveRes) return
+            if(type==='dsfb'){
+                this.showDSFB=true
+                return
+            }
+            // 发布
+            if(this.reportInfo.MsgIsSend==1){//该报告已经推送过模板消息
+                this.reportPublish({sendMsg:false})
+            }else{
+                this.$confirm(
+                    '发布后,是否推送模板消息?', 
+                    '发布提示', 
+                    {
+                        confirmButtonText: '推送',
+                        cancelButtonText: '不推送',
+                        type: 'warning',
+                        distinguishCancelAndClose:true,
+                    
+                        beforeClose:(action, instance,done)=>{
+                            if(action==='close') {
+                                //右上角
+                                // this.isPublishloading = false;
+                            } else if(action==='cancel') {
+                                //cancelButton
+                                this.reportPublish({sendMsg:false})
+                            }else {
+                                //confirmButton
+                                this.reportPublish({sendMsg:true})
+                            }
+                            done()
+                        }
+                    }
+                )
+            }
+        },
+
+        // 定时发布报告
+        async handleSetReportPrepublish(){
+            if(!this.taskTime){
+				this.$message.warning('请选择定时发布的时间')
+				return
+			}
+			const now=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+			// console.log(now);
+			// console.log(this.taskTime);
+			if(this.$moment(this.taskTime).isBefore(now,'second')){
+				this.$message.warning('定时发布不得早于当前时间')
+				return
+			}
+            // 如果该报告已经推送过模板消息
+            if(this.reportInfo.MsgIsSend==1){
+                apiSmartReport.prePublishReport({
+                    SmartReportId:Number(this.$route.query.id),
+                    PrePublishTime:this.taskTime,
+                    PreMsgSend:0
+                }).then(res=>{
+                    if(res.Ret===200){
+                        this.$message.success('定时发布成功!')
+                        this.$router.replace({ path: '/smartReportList' });
+                    }
+                })
+                return
+            }
+
+            const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.smartReportManageBtn.reportManage_sendMsg)
+
+            this.$confirm(isPost?'是否发布定时报告,并推送模板消息?':'是否发布定时报告?', '发布提示', {
+				confirmButtonText: isPost?'推送':'发布',
+				cancelButtonText: isPost?'不推送':'取消',
+				type: 'warning',
+				distinguishCancelAndClose:true,
+				beforeClose:(action, instance,done)=>{
+					console.log(action, instance);
+					if(action==='close'||action==='cancel') {
+						//右上角或者不推送
+						if(isPost){
+							apiSmartReport.prePublishReport({
+								SmartReportId:Number(this.$route.query.id),
+								PrePublishTime:this.taskTime,
+								PreMsgSend:0,
+							}).then(res=>{
+								if(res.Ret===200){
+									this.$message.success('定时发布成功!')
+									this.$router.replace({ path: '/smartReportList' });
+								}
+							})
+						}
+					} else {
+						//confirmButton
+						apiSmartReport.prePublishReport({
+							SmartReportId:Number(this.$route.query.id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:isPost?1:0,
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success('定时发布成功!')
+								this.$router.replace({ path: '/smartReportList' });
+							}
+						})
+					}
+					done()
+				}
+			})
+        },
+
+        // 发布报告
+        reportPublish({sendMsg}){
+            apiSmartReport.publishReport({
+                SmartReportId:Number(this.$route.query.id),
+                PublishState:2
+            }).then(res=>{
+                if(res.Ret===200){
+                    if(sendMsg){
+                        this.reportSendMsg()
+                    }
+                    this.$router.replace({ path: '/smartReportList' });
+                }
+            })
+        },
+
+        //报告消息推送
+        reportSendMsg(){
+            apiSmartReport.reportMsgSend({SmartReportId:Number(this.$route.query.id)}).then(res=>{})
+        }
     },
     created() {
         this.getPublicSettings()
@@ -539,9 +924,15 @@ export default {
     },
     mounted () {
         window.addEventListener('message',this.setSheetIframeStyle)
+        this.timer = setInterval(() => {
+			this.handleSaveContent({isAutoSave:true});
+		}, 6000);
     },
     destroyed() {
 		window.removeEventListener('message',this.setSheetIframeStyle)
+        if (this.timer) {
+			clearInterval(this.timer);
+		}
 	},
 }
 </script>
@@ -549,6 +940,14 @@ export default {
 div{
     box-sizing: border-box;
 }
+// .sortable-ghost{
+//     height: 5px !important;
+//     background-color: #0052D9 !important;
+//     overflow: hidden !important;
+//     padding: 0 !important;
+//     min-height: 0 !important;
+//     border: none !important;
+// }
 .edit-smart-report-page{
     background: var(--unnamed, #F2F6FA);
     min-width: 100vw;
@@ -676,13 +1075,17 @@ div{
             min-height: 80px;
             border: 1px dashed #0052D9;
             position: relative;
+            margin-bottom: 10px;
             &:hover{
+                border-style: solid;
                 .opt-btn-box{
+                    display: block !important;
+                }
+                .resize-drag-box{
                     display: block;
                 }
             }
             .opt-btn-box{
-                display: none;
                 position: absolute;
                 left: -36px;
                 padding-right: 8px;
@@ -706,11 +1109,19 @@ div{
                     cursor: pointer;
                 }
             }
+            .resize-drag-box{
+                position: absolute;
+                right: -4px;
+                bottom: -4px;
+                width: 8px;
+                height: 8px;
+                display: none;
+                border: 1px solid #0052D9;
+                cursor: n-resize;
+            }
         }
         .report-drag-item-wrap_child-wrap{
-            display: flex;
-            gap: 20px;
-            min-height: 10px;
+            min-height: 30px;
         }
         .report-drag-item-wrap_child_content{
             min-height: 80px;
@@ -718,12 +1129,18 @@ div{
             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{
-                display: none;
                 position: absolute;
                 right: -15px;
                 top: 0;
@@ -746,6 +1163,36 @@ div{
                     cursor: pointer;
                 }
             }
+            .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);

+ 209 - 0
src/views/smartReport/reportDetail.vue

@@ -0,0 +1,209 @@
+<template>
+    <div class="smart-report-detail">
+        <div class="main-box">
+            <div class="top-box">
+                <div class="title">{{reportInfo&&reportInfo.Title}}</div>
+                <div class="flex">
+                    <span>{{reportInfo&&reportInfo.Author}}</span>
+                    <span>{{reportInfo&&reportInfo.PublishTime}}</span>
+                </div>
+            </div>
+            <div class="html-wrap" v-html="content"></div>
+        </div>
+        <div class="right-opt-box" v-if="$route.query.type!=='preview'">
+            <div 
+                class="item copy" 
+                v-if="linkUrl" 
+                :data-clipboard-text='linkUrl' 
+                @click="copyHandle"
+                v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_copyWechat"
+            >
+                <img src="~@/assets/img/icons/cop.png" alt="" style="width:30px;height:30px;marginRight:10px;">
+                <span>复制链接</span>
+            </div>
+            <div 
+                class="item wechat-item" 
+                v-if="linkUrl"
+                v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_copyWechat"
+            >
+                <img src="~@/assets/img/icons/wechat.png" alt="" style="width:30px;height:30px;marginRight:10px;">
+                <span>微信分享</span>
+                <vue-qr 
+                    :text="linkUrl" 
+                    :margin="0" 
+                    colorDark="#333" 
+                    colorLight="#fff" 
+                    :dotScale="1" 
+                    :size="100" 
+                    class="qrcode"
+                ></vue-qr>
+            </div>
+            <div class="item" @click="handleGetReportImg" v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_exportImg">
+                <img src="~@/assets/img/smartReport/icon16.png" alt="" style="width:30px;height:30px;marginRight:10px;">
+                <span>导&nbsp;&nbsp;图</span>
+            </div>
+        </div>
+
+        <!-- 报告图片 -->
+        <div class="report-img-box" v-if="showReportImg&&reportImgUrl" @click="showReportImg=false">
+            <img :src="reportImgUrl" alt="" @click.stop="">
+        </div>
+    </div>
+</template>
+
+<script>
+import {apiSmartReport}  from '@/api/modules/smartReport'
+import vueQr from 'vue-qr'
+export default {
+    computed: {
+		linkUrl(){
+			let str=''
+			const baseUrl= localStorage.getItem('dynamicOutLinks') ? JSON.parse(localStorage.getItem('dynamicOutLinks')).ReportViewUrl : '';
+			if(this.$route.query.code){
+				str=`${baseUrl}/reportshare_smart_report?code=${this.$route.query.code}`
+			}
+			return str
+		}
+	},
+    data() {
+        return {
+            reportInfo:null,
+            content:'',
+            reportImgUrl:'',
+            showReportImg:false
+        }
+    },
+    created() {
+        this.getReportDetail()
+    },
+    methods: {
+        // 获取报告详情
+        getReportDetail(){
+            const id=this.$route.query.id||0
+            if(!id) return
+            apiSmartReport.reportDetail({
+                SmartReportId:Number(id)
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.reportInfo=res.Data
+                    if(this.$route.query.type==='preview'){
+                       this.content=sessionStorage.getItem('smartReportContent')
+                    }else{
+                        this.content=res.Data.Content
+                    }
+                }
+            })
+        },
+
+        /* 复制链接 */
+		copyHandle() {
+				var clipboard = new this.Clipboard('.copy')
+				clipboard.on('success', e => {
+					this.$message.success('复制链接成功')
+					e.clearSelection() // 释放内存
+					clipboard.destroy()
+				})
+				// // 浏览器不支持
+				clipboard.on('error', e => {
+					this.$message.warning('浏览器暂不支持')
+					// 释放内存
+					clipboard.destroy()
+				})
+		},
+
+        handleGetReportImg(){
+            if(this.reportImgUrl){
+                this.showReportImg=true
+                return
+            }
+            apiSmartReport.getReportImg({
+                SmartReportId:Number(this.$route.query.id)
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.reportImgUrl=res.Data
+                    this.showReportImg=true
+                }else{
+                    if(res.Ret!==403){
+                        this.$message.warning(res.Msg)
+                    }
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.smart-report-detail{
+    .right-opt-box{
+            position: fixed;
+            top: 100px;
+            left: calc(50% + 450px);
+            .item{
+                display: flex;
+                align-items: center;
+                cursor: pointer;
+                margin-bottom: 20px;
+                position: relative;
+                .qrcode{
+                    position: absolute;
+                    left: 110%;
+                    display: none !important;
+                    z-index: 9;
+                }
+            }
+            .wechat-item{
+                &:hover{
+                    .qrcode{
+                        display: inline-block !important;
+                    }
+                }
+            }
+    }
+    .main-box{
+        width: 800px;
+        margin: 0 auto;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        border-radius: 4px;
+        overflow: hidden;
+        position: relative;
+        .top-box{
+            width: 100%;
+            height: 160px;
+            background-image: url('~@/assets/img/smartReport/bg01.png');
+            background-size: cover;
+            background-repeat: no-repeat;
+            background-position: center;
+            padding: 40px;
+            color: #fff;
+            .title{
+                font-size: 20px;
+                margin-bottom: 20px;
+            }
+            .flex{
+                display: flex;
+                justify-content: space-between;
+            }
+        }
+        .html-wrap{
+            padding: 30px;
+        }
+    }
+    .report-img-box{
+        position: fixed;
+        left: 0;
+        top: 0;
+        bottom: 0;
+        right: 0;
+        overflow-y: auto;
+        background: rgba($color: #000000, $alpha: 0.6);
+        text-align: center;
+        img{
+            max-width: 800px;
+        }
+    }
+}
+</style>

+ 147 - 36
src/views/smartReport/reportList.vue

@@ -5,7 +5,7 @@
                 <el-form :inline="true" :model="searchform" @submit.native.prevent>
                 <el-form-item label="">
                     <el-button
-                        v-permission="permissionBtn.reportManageBtn.reportManage_reportAdd"
+                        v-permission="permissionBtn.smartReportManageBtn.reportManage_reportAdd"
                         type="primary"
                         size="medium"
                         @click="showAddReport=true"
@@ -79,9 +79,9 @@
                         <el-option label="未发布" :value="1"></el-option>
                     </el-select>
                 </el-form-item>
-                <el-form-item label="">
+                <!-- <el-form-item label="">
                     <el-select
-                        v-permission="permissionBtn.reportManageBtn.reportManage_reportList_sendTime"
+                        v-permission="permissionBtn.smartReportManageBtn.reportManage_reportList_sendTime"
                         @change="search"
                         v-model.number="searchform.msgIsSend"
                         placeholder="推送消息状态"
@@ -92,11 +92,11 @@
                         <el-option label="未推送消息" :value="1"></el-option>
                         <el-option label="已推送消息" :value="2"></el-option>
                     </el-select>
-                </el-form-item>
+                </el-form-item> -->
                 <el-form-item>
                     <el-input
                         @input="search"
-                        placeholder="标题 / 创建人"
+                        placeholder="标题 / 创建人 / 更新人"
                         v-model="searchform.key_word"
                         clearable
                         size="medium"
@@ -166,6 +166,12 @@
                     align="center"
                     min-width="100"
                 ></el-table-column>
+                <el-table-column
+                    prop="LastModifyAdminName"
+                    label="更新人"
+                    align="center"
+                    min-width="100"
+                ></el-table-column>
                 <el-table-column label="发布状态" align="center">
                     <template slot-scope="scope">
                     <span v-if="scope.row.State == '2'" style="color: #46c371"
@@ -188,7 +194,7 @@
                     </svg>
                     </template>
                 </el-table-column>
-                <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_reportList_sendTime)"
+                <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_reportList_sendTime)"
                     prop="MsgSendTime"
                     label="报告推送时间"
                     min-width="124"
@@ -199,7 +205,7 @@
                     }}</template>
                 </el-table-column>
                 <el-table-column
-                    prop="ModifyTime"
+                    prop="ContentModifyTime"
                     label="更新时间"
                     min-width="124"
                     align="center"
@@ -228,28 +234,28 @@
                         v-if="scope.row.State == 1"
                         >
                         <span
-                            v-permission="permissionBtn.reportManageBtn.reportManage_publish"
+                            v-permission="permissionBtn.smartReportManageBtn.reportManage_publish"
                             class="editsty"
-                            @click="publishreport(scope.row)"
+                            @click="handlePublishReportOpt(scope.row)"
                             v-if="scope.row.CanEdit"
                             >发布</span
                         >
                         <span
-                            v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit"
+                            v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
                             class="editsty"
                             @click="editreport(scope.row, 'edit')"
                             v-if="scope.row.CanEdit"
                             >编辑</span
                         >
                         <span
-                            v-permission="permissionBtn.reportManageBtn.reportManage_reportEdit"
+                            v-permission="permissionBtn.smartReportManageBtn.reportManage_reportEdit"
                             class="editsty"
                             @click="editreport(scope.row, 'editing')"
                             v-else
                             >{{ scope.row.Editor || "" }}编辑中...</span
                         >
                         <span
-                            v-permission="permissionBtn.reportManageBtn.reportManage_reportDel"
+                            v-permission="permissionBtn.smartReportManageBtn.reportManage_reportDel"
                             class="deletesty"
                             @click="handleDelReport(scope.row)"
                             v-if="scope.row.CanEdit"
@@ -257,28 +263,27 @@
                         >
                         </template>
                         <template v-if="scope.row.State == 2">
-                        <span v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_cancelPublish)"
-                            @click="canclepublish(scope.row)"
+                        <span v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_cancelPublish)"
+                            @click="handleReportPublishCancel(scope.row)"
                             style="color: red; cursor: pointer"
-                            >取消发布</span
-                        >
-                        <span
-                            v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
+                            >取消发布</span>
+                        <!-- <span
+                            v-if="scope.row.MsgIsSend == 0 && permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_sendMsg)"
                             style="color: #4099ef; cursor: pointer"
                             @click="handleSendMsg(scope.row)"
                             >推送消息</span
                         >
-                        <span v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_sendMsg)"
-                            style="color: red">已推送消息</span>
+                        <span v-else-if="scope.row.MsgIsSend != 0&&permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_sendMsg)"
+                            style="color: red">已推送消息</span> -->
                         </template>
                         <span
                         style="color: #46c371; cursor: pointer"
-                        v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_audioUpload)"
-                        @click="openupload(scope.row.Id)"
+                        v-if="permissionBtn.checkPermissionBtn(permissionBtn.smartReportManageBtn.reportManage_audioUpload)"
+                        @click="openupload(scope.row.SmartReportId)"
                         >音频上传</span
                         >
                         <a
-                        v-permission="permissionBtn.reportManageBtn.reportManage_audioDownload"
+                        v-permission="permissionBtn.smartReportManageBtn.reportManage_audioDownload"
                         :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)"
                         v-if="scope.row.VideoUrl"
                         :download="scope.row.VideoName"
@@ -370,6 +375,44 @@
 
         <!-- 新增报告基础信息 -->
         <BaseInfo v-model="showAddReport" :id="0" />
+
+        <!-- 批量发布弹窗 -->
+        <el-dialog
+            title="发布提示"
+            :visible.sync="showPublish"
+            :modal-append-to-body="false"
+            :close-on-click-modal="false"
+            :center="true"
+            v-dialogDrag
+            custom-class="dialogclass"
+            width="510px"
+            @close="handleClosePublish"
+        >
+            <div>
+                <div style="height: 100px; padding-top: 40px">
+                    <i
+                        class="el-icon-warning"
+                        style="font-size: 24px; color: #e6a23c; vertical-align: middle"
+                    ></i>
+                    {{isDSFB?'该报告已设置定时发布,是否立即发布报告?':'是否立即发布报告?'}}
+                </div>
+                <div style="margin-bottom: 20px; text-align: center">
+                    <el-button
+                        type="primary"
+                        plain
+                        style="width: 100px"
+                        @click="handleClosePublish"
+                        >取消</el-button
+                    >
+                    <el-button
+                        type="primary"
+                        style="width: 100px; margin: 0 20px"
+                        @click="handleConfirmPublishReport"
+                        >发布</el-button
+                    >
+                </div>
+            </div>
+        </el-dialog>
     </div>
 </template>
 
@@ -386,7 +429,7 @@ export default {
         },
         //是否有UV
         hasUV(){
-            return this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_reportList_uv)
+            return this.permissionBtn.checkPermissionBtn(this.permissionBtn.smartReportManageBtn.reportManage_reportList_uv)
         }
     },
     data() {
@@ -420,7 +463,11 @@ export default {
             },
             uploadloading: false,
 
-            showAddReport:false
+            showAddReport:false,
+
+            showPublish:false,
+            activeReportId:0,
+            isDSFB:false
         }
     },
     methods:{
@@ -430,7 +477,7 @@ export default {
             this.$confirm("确认删除吗?", "提示", {
                 type: "warning",
             }).then(() => {
-                apiSmartReport.delReport({ ReportIds: item.Id }).then((res) => {
+                apiSmartReport.delReport({ SmartReportId: item.SmartReportId }).then((res) => {
                     if (res.Ret === 200) {
                         this.$message.success(res.Msg);
                         this.getReportList();
@@ -441,7 +488,7 @@ export default {
 
         //取消发布
         handleReportPublishCancel(item){
-            apiSmartReport.publishCancel({ ReportIds: item.Id }).then((res) => {
+            apiSmartReport.publishReport({ SmartReportId: item.SmartReportId,PublishState:1 }).then((res) => {
                 if (res.Ret === 200) {
                     this.$message.success(res.Msg);
                     this.getReportList();
@@ -449,15 +496,79 @@ export default {
             });
         },
 
-        // 推送消息
-        async handleSendMsg(item){
-            const res = await apiSmartReport.reportMsgSend({
-                ReportId: [item.Id],
+        // 发布报告
+        handlePublishReportOpt(item){
+            this.activeReportId=item.SmartReportId
+            this.isDSFB=item.PrePublishTime?true:false
+            this.showPublish=true
+        },
+        handleConfirmPublishReport(){
+            apiSmartReport.publishReport({ SmartReportId: this.activeReportId,PublishState:2 }).then((res) => {
+                if (res.Ret === 200) {
+                    this.$message.success(res.Msg);
+                    this.getReportList();
+                    this.handleClosePublish()
+                }
+            });
+        },
+        handleClosePublish(){
+            this.activeReportId=0
+            this.isDSFB=false
+            this.showPublish=false
+        },
+
+        //编辑报告
+        async editreport(item, type){
+            //编辑前标记一下
+            const res = await apiSmartReport.markReport({
+                Status: 1,
+                SmartReportId: item.SmartReportId,
             });
-            if (res.Ret == 200) {
-                item.ThsMsgIsSend = 1;
-                this.$message.success("发送成功");
+            if (res.Ret === 200) {
+                if (res.Data.Status == 1) {
+                    this.$message.warning(res.Data.Msg || "该研报正在编辑,不可重复编辑");
+                    item.CanEdit = false;
+                    item.Editor = res.Data.Editor || "";
+                    return;
+                } else if (res.Data.Status == 0) {
+                    item.CanEdit = true;
+                    item.Editor = res.Data.Editor || "";
+                }
+            } else {
+                this.$message.error(res.ErrMsg || "未知错误,请稍后重试");
+                return;
             }
+            let { href } = this.$router.resolve({
+                path: "/smartReportEdit",
+                query: { id: item.SmartReportId },
+            });
+            window.open(href, "_blank");
+        },
+
+        // 推送消息
+        // async handleSendMsg(item){
+        //     const res = await apiSmartReport.reportMsgSend({
+        //         SmartReportId: [item.Id],
+        //     });
+        //     if (res.Ret == 200) {
+        //         item.ThsMsgIsSend = 1;
+        //         this.$message.success("发送成功");
+        //     }
+        // },
+
+        // 跳转报告详情
+        lookreportdtl(item){
+            //如果没有预览权限,就不跳转
+            if(!this.permissionBtn.checkPermissionBtn(this.permissionBtn.smartReportManageBtn.reportManage_reportView)) return
+            
+            let { href } = this.$router.resolve({ 
+                path: '/smartReportDetail',
+                query:{
+                    id:item.SmartReportId,
+                    code:item.ReportCode
+                }
+            });
+            window.open(href, "_blank");
         },
 
         // 报告列表
@@ -596,7 +707,7 @@ export default {
                 ) {
                 let form = new FormData();
                 form.append("file", hostfile); //hostfile.name
-                form.append("ReportId", this.uploadForm.id);
+                form.append("SmartReportId", this.uploadForm.id);
                     this.uploadForm.formdata = form;
                     this.uploadForm.audioname = hostfile.name;
                 } else {
@@ -610,7 +721,7 @@ export default {
                 return false;
             }
             this.uploadloading = true;
-            voiceupload(this.uploadForm.formdata).then((res) => {
+            apiSmartReport.voiceupload(this.uploadForm.formdata).then((res) => {
                 if (res.Ret === 200) {
                     this.$message.success("上传成功");
                     this.getReportList();