123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- <script setup>
- import {ref,onMounted,onUnmounted} from 'vue'
- import {useInitFroalaEditor} from '@/hooks/useFroalaEditor'
- import EditReportBaseInfo from './components/EditReportBaseInfo.vue'
- import ReportInsertContent from './components/reportInsert/Index.vue'
- import ReportPublishTimeSet from './components/ReportPublishTimeSet.vue'
- import apiReport from '@/api/report'
- import apiChart from '@/api/chart'
- import {getSystemInfo} from '@/api/common'
- import moment from 'moment'
- import { showToast,showDialog } from 'vant'
- import { useRouter } from 'vue-router'
- import {useCachedViewsStore} from '@/store/modules/cachedViews'
- import {reportManageBtn,useAuthBtn} from '@/hooks/useAuthBtn'
- import {usePublicSettingStore} from '@/store/modules/publicSetting'
- import {useReportApprove} from '@/hooks/useReportApprove'
- import {Base64} from 'js-base64'
- const cachedViewsStore=useCachedViewsStore()
- const publicSettingStore = usePublicSettingStore()
- const {isApprove,hasApproveFlow,getEtaConfig,checkClassifyNameArr} = useReportApprove()
- const router=useRouter()
- const {checkAuthBtn} = useAuthBtn()
- const {lastFocusPosition,initFroalaEditor}=useInitFroalaEditor()
- let reportContentEditorIns=null//报告内容编辑器实例
- let reportId=0//报告id
- let reportCode=0//报告id
- // 水印
- const waterMarkStr=ref('')
- onMounted(() => {
- const el=document.getElementById('editor')
- reportContentEditorIns=initFroalaEditor('#editor',{height:el.offsetHeight-150})
- getSystemInfoFun()
- })
- // 报告基本内容
- const showReportBaseInfo=ref(false)
- let reportBaseInfoData={
- addType:1,
- classifyName:[],
- author:['FICC团队'],
- frequency: ['日度'],
- createtime:moment().format('YYYY-MM-DD'),
- title:'',
- abstract:''
- }
- async function handleReportBaseInfoChange(e){
- reportBaseInfoData=e
- // 继承报告 覆盖一次
- if(e.addType===2&&e.classifyName.length===2){
- const res=await apiReport.reportDetailByClassifyId({
- ClassifyIdFirst:e.classifyName[0].id,
- ClassifyIdSecond:e.classifyName[1].id
- })
- if(res.Ret===200){
- if(res.Data===null){
- showToast('此分类暂无报告')
- }else{
- reportBaseInfoData.author=res.Data.Author ? res.Data.Author.split(',') : ['FICC团队']
- reportBaseInfoData.frequency=[res.Data.Frequency]
- reportBaseInfoData.createtime=moment().format('YYYY-MM-DD')
- reportBaseInfoData.title=res.Data.Title
- reportBaseInfoData.abstract=res.Data.Abstract
- reportContentEditorIns.html.set(res.Data.Content);
- }
- }
- }
- const classify = e.classifyName.map(i=>i.id)
- checkClassifyNameArr(1,classify)
- showReportBaseInfo.value=false
- }
- // 报告插入数据弹窗
- const showReportInsertPop=ref(false)
- /**
- * list:[UniqueCode] 图表code 如果是以 isETAForumChart_ 开头则说明是社区图表
- * type:iframe/img 插入的为iframe或者图片
- * chartType: chart-图表,sheet-表格
- */
- function handleInsert({list,type,chartType}){
- reportContentEditorIns.events.focus()
- if(lastFocusPosition.value){
- reportContentEditorIns.selection.get().removeAllRanges()
- reportContentEditorIns.selection.get().addRange(lastFocusPosition.value)
- }
- if(type==='iframe'){
- let link=publicSettingStore.publicSetting.ChartViewUrl;
- if(chartType==='chart'){
- // link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/chartshow':'https://charttest.hzinsights.com/chartshow'
- link=link+'/chartshow'
- list.forEach(item => {
- const isETAForumChart=item.startsWith('isETAForumChart_')?true:false
- reportContentEditorIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
- <iframe src='${link}?code=${isETAForumChart?item.replace(/^isETAForumChart_/, ''):item}&fromPage=&isETAForumChart=${isETAForumChart}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
- </p>`)
- });
- }else if(chartType==='sheet'){
- // link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/sheetshow':'https://charttest.hzinsights.com/sheetshow'
- link=link+'/sheetshow'
- list.forEach(item => {
- reportContentEditorIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
- <iframe src='${link}?code=${item}' class='iframe${item}' width='100%' style='border-width:0px;'></iframe>
- </p>`)
- });
- }
- }else if(type==='img'){
- list.forEach(item=>{
- reportContentEditorIns.html.insert(`<img style='width:100%' src='${item}' />`)
- })
- }
- showReportInsertPop.value=false
- }
- // 更新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+45}px`;
- });
- }
- onMounted(()=>{
- getEtaConfig()
- window.addEventListener('message',reInitSheetIframe)
- })
- onUnmounted(()=>{
- window.removeEventListener('message',reInitSheetIframe)
- })
- // 刷新所有图表
- async function handleRefreshAllChart(){
- let code_arr = [];
- $('iframe').each((k,i) => {
- try {
- let href = $(i).attr('src');
- code_arr.push(href.slice(href.indexOf('code=') + 5));
- } catch (err) {
- }
- });
- if(!code_arr.length) return showToast('请插入图表');
- const res=await apiChart.refreshChartMultiple({ChartInfoCode:code_arr})
- if(res.Ret===200){
- $('iframe').each((k,i) => {
- $(i).attr('src',$(i).attr('src'))
- });
- showToast('刷新成功')
- }
- }
- // 发布报告-fb;保存-cg;预览-yl
- const showPublishPop=ref(false)
- async function handleReportOpt(type){
- if(reportBaseInfoData.classifyName.length===0){
- showToast('请选择报告分类')
- return
- }
- if(!reportBaseInfoData.title){
- showToast('请填写报告标题')
- return
- }
- //如果富文本中有未上传完成的图片,去除这个dom
- $('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
- const params={
- AddType: reportBaseInfoData.addType,
- ClassifyIdFirst: reportBaseInfoData.classifyName[0].id,
- ClassifyNameFirst: reportBaseInfoData.classifyName[0].text,
- ClassifyIdSecond: reportBaseInfoData.classifyName[1].id,
- ClassifyNameSecond: reportBaseInfoData.classifyName[1].text,
- Title: reportBaseInfoData.title,
- Abstract: reportBaseInfoData.abstract,
- Author:reportBaseInfoData.author.join(','),
- Frequency: reportBaseInfoData.frequency[0],
- Content: $('.fr-element').html(),
- CreateTime: reportBaseInfoData.createtime,
- ReportVersion: 2,
- State:1
- }
- console.log(params);
- if(type==='yl'){
- sessionStorage.setItem('reportPreData',JSON.stringify(params))
- const routerEl=router.resolve({
- path:'/report/preview',
- query:{
- id:-1
- }
- })
- window.open(routerEl.href,'_blank')
- return
- }
- cachedViewsStore.removeCaches('ReportList')
- if(type==='cg'){
- // 存草稿
- const res=await apiReport.reportAdd(params)
- if(res.Ret===200){
- showToast('保存成功')
- router.replace({
- path:'/report/edit',
- query:{
- id:res.Data.ReportId
- }
- })
- }
- }
- if(type==='fb'){
- // 发布
- const hasTel=reportBaseInfoData.classifyName[1].HasTeleconference
- //有电话会的不提示推送客群
- if(hasTel==1){
- const res=await apiReport.reportAdd(params)
- if(res.Ret===200){
- reportPublish(res.Data.ReportId,res.Data.ReportCode)
- }
- }else{
- // 显示发布提示弹窗,提示推送客群
- //判断是否有推送权限
- if(!checkAuthBtn(reportManageBtn.reportManage_sendMsg)){
- handleConfirmPublish(1)
- return
- }
- showPublishPop.value=true
- }
- }
- if(type==='submit'){
- //提交
- handleReportSubmit(params)
- }
- if(type==='dsfb'){
- //定时发布
- const res=await apiReport.reportAdd(params)
- if(res.Ret===200){
- reportId=res.Data.ReportId
- reportCode=res.Data.ReportCode
- showDSFBTime.value=true
- }
- }
- }
- // 点击发布提示弹窗中的操作按钮
- async function handleConfirmPublish(e){
- const params={
- AddType: reportBaseInfoData.addType,
- ClassifyIdFirst: reportBaseInfoData.classifyName[0].id,
- ClassifyNameFirst: reportBaseInfoData.classifyName[0].text,
- ClassifyIdSecond: reportBaseInfoData.classifyName[1].id,
- ClassifyNameSecond: reportBaseInfoData.classifyName[1].text,
- Title: reportBaseInfoData.title,
- Abstract: reportBaseInfoData.abstract,
- Author:reportBaseInfoData.author.join(','),
- Frequency: reportBaseInfoData.frequency[0],
- Content: $('.fr-element').html(),
- CreateTime: reportBaseInfoData.createtime,
- ReportVersion: 2,
- State:1
- }
- const saveRes=await apiReport.reportAdd(params)
- if(e===1){//仅发布
- reportPublish(saveRes.Data.ReportId,saveRes.Data.ReportCode)
- }else if(e===2){
- const pubRes=await apiReport.reportPublish({ReportIds:saveRes.Data.ReportId.toString(),ReportUrl:generatePdfLinks(saveRes.Data.ReportCode)})
- if(pubRes.Ret!==200) return
- const msgRes=await apiReport.reportMessageSend({ReportId:saveRes.Data.ReportId})
- if(msgRes.Ret!==200) return
- router.back()
- }
- }
- function generatePdfLinks(Code){
- return `${publicSettingStore.publicSetting.ReportViewUrl}/reportshare_pdf?code=${Code}&flag=${waterMarkStr.value}`
- }
- async function reportPublish(id,code){
- const res=await apiReport.reportPublish({ReportIds:id.toString(),ReportUrl:generatePdfLinks(code)})
- if(res.Ret===200){
- console.log('back');
- router.back()
- }
- }
- // 定时发布报告选择时间
- const showDSFBTime=ref(false)
- function onConfirmDSFBTime(time){
- console.log(time);
- const isAuthPushMsg=checkAuthBtn(reportManageBtn.reportManage_sendMsg)
- console.log(isAuthPushMsg);
- showDialog({
- title: '提示',
- message:isAuthPushMsg?'是否发布定时报告,并推送模板消息?':'是否发布定时报告',
- confirmButtonText:isAuthPushMsg?'推送':'取消',
- cancelButtonText:isAuthPushMsg?'不推送':'确定',
- showCancelButton:true
- }).then(()=>{
- if(!isAuthPushMsg){
- apiReport.reportPublishTimeSet({
- ReportId:reportId,
- PrePublishTime:time,
- PreMsgSend:0,
- ReportUrl:generatePdfLinks(reportCode)
- }).then(res=>{
- if(res.Ret===200){
- showToast('定时发布成功!')
- setTimeout(() => {
- router.back()
- }, 1000);
- }
- })
- return
- }
- //推送
- apiReport.reportPublishTimeSet({
- ReportId:reportId,
- PrePublishTime:time,
- PreMsgSend:1,
- ReportUrl:generatePdfLinks(reportCode)
- }).then(res=>{
- if(res.Ret===200){
- showToast('定时发布成功!')
- setTimeout(() => {
- router.back()
- }, 1000);
- }
- })
- }).catch(()=>{
- if(!isAuthPushMsg) return
- //不推送
- apiReport.reportPublishTimeSet({
- ReportId:reportId,
- PrePublishTime:time,
- PreMsgSend:0,
- ReportUrl:generatePdfLinks(reportCode)
- }).then(res=>{
- if(res.Ret===200){
- showToast('定时发布成功!')
- setTimeout(() => {
- router.back()
- }, 1000);
- }
- })
- })
- }
- //提交
- async function handleReportSubmit(params){
- const res=await apiReport.reportAdd(params)
- if(res.Ret!==200) return
- showDialog({
- title: '提示',
- message: '是否确认提交该报告进入审批流程?',
- showCancelButton:true
- }).then(()=>{
- apiReport.reportCnSubmit({
- ReportId:Number(res.Data.ReportId)
- }).then(res=>{
- if(res.Ret!==200) return
- showToast('提交成功')
- router.back()
- }).catch(()=>{ //如果选择取消就和存草稿一样,转到编辑页
- router.replace({
- path:'/report/edit',
- query:{
- id:res.Data.ReportId
- }
- })
- })
- })
- }
- const getSystemInfoFun=()=>{
- getSystemInfo().then(res=>{
- if(res.Ret===200){
- const systemUserInfo=res.Data
- // 设置水印文案
- let waterMarkString=''
- if(systemUserInfo){
- waterMarkString=`${systemUserInfo.RealName}${systemUserInfo.Mobile?systemUserInfo.Mobile:systemUserInfo.Email}`
- waterMarkString=encodeURIComponent(waterMarkString)
- waterMarkStr.value=Base64.encode(waterMarkString)
- }
- }
- })
- }
- </script>
- <template>
- <div class="add-report-page">
- <van-cell title="基础信息" is-link @click="showReportBaseInfo=true"/>
- <div class="main-wrap">
- <div class="editor-box" id="editor"></div>
- </div>
- <!-- 底部操作 -->
- <div class="bot-action-box">
- <div class="left-box">
- <div class="item" @click="handleRefreshAllChart">
- <img src="@/assets/imgs/report/icon_refresh.png" alt="">
- <span>刷新</span>
- </div>
- <div class="item" @click="handleReportOpt('yl')" v-permission="reportManageBtn.reportManage_reportView">
- <img src="@/assets/imgs/report/icon_preview.png" alt="">
- <span>预览</span>
- </div>
- <div class="item" @click="handleReportOpt('cg')">
- <img src="@/assets/imgs/report/icon_save2.png" alt="">
- <span>保存</span>
- </div>
- <template v-if="!isApprove||!hasApproveFlow">
- <div class="item" @click="handleReportOpt('dsfb')" v-permission="reportManageBtn.reportManage_publish">
- <img src="@/assets/imgs/report/icon_time.png" alt="">
- <span>定时发布</span>
- </div>
- <div class="item" @click="handleReportOpt('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="handleReportOpt('submit')" v-permission="reportManageBtn.reportManage_publish">
- <img src="@/assets/imgs/report/icon_publish3.png" alt="">
- <span>提交</span>
- </div>
- </template>
-
- </div>
- <div class="right-btn" @click="showReportInsertPop=true">
- <svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
- <path d="M12.0499 15.9499V27.5H15.9499V15.9499H27.5V12.0499H15.9499V0.5H12.0499V12.0499H0.5V15.9499H12.0499Z" fill="white"/>
- </svg>
- </div>
- </div>
- </div>
- <!-- 报告基础信息 -->
- <van-popup
- v-model:show="showReportBaseInfo"
- position="bottom"
- :style="{ height: '100%' }"
- >
- <EditReportBaseInfo @close="showReportBaseInfo=false" @confirm="handleReportBaseInfoChange"/>
- </van-popup>
- <!-- 报告插入数据模块 -->
- <van-popup
- v-model:show="showReportInsertPop"
- position="bottom"
- round
- >
- <report-insert-content v-if="showReportInsertPop" @insert="handleInsert"/>
- </van-popup>
- <!-- 发布提示 -->
- <van-popup
- v-model:show="showPublishPop"
- >
- <div class="publish-report-pop-box">
- <div class="title">发布提示</div>
- <p class="tips">是否立即发布报告,并推送模板消息?</p>
- <div class="btns">
- <div class="btn blue" @click="handleConfirmPublish(2)">发布&推送</div>
- <div class="btn" @click="handleConfirmPublish(1)">仅发布</div>
- <div class="btn" @click="showPublishPop=false">取消</div>
- </div>
- </div>
- </van-popup>
- <!-- 定时发布选择时间 -->
- <ReportPublishTimeSet v-model="showDSFBTime" @confirm="onConfirmDSFBTime" />
- </template>
- <style lang="scss" scoped>
- .publish-report-pop-box{
- padding: 48px;
- .title{
- font-size: 36px;
- text-align: center;
- margin-bottom: 32px;
- }
- .tips{
- color: $font-grey;
- margin-bottom: 48px;
- }
- .btns{
- .btn{
- line-height: 96px;
- border-radius: 12px;
- text-align: center;
- font-size: 32px;
- font-weight: 600;
- margin-bottom: 24px;
- background-color: #F2F3FF;
- color: $theme-color;
- }
- .blue{
- background-color: $theme-color;
- color: #fff;
- }
- .disabled{
- background-color: #a8b0fc;
- }
- }
- }
- @media screen and (min-width:$media-width){
- .publish-report-pop-box{
- padding: 24px;
- .title{
- font-size: 18px;
- margin-bottom: 16px;
- }
- .tips{
- margin-bottom: 24px;
- }
- .btns{
- .btn{
- line-height: 48px;
- border-radius: 12px;
- font-size: 16px;
- margin-bottom: 12px;
- }
- }
- }
- }
- .add-report-page{
- height: 100dvh;
- min-height: 95vh;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
- @media screen and (min-width:$media-width){
- .add-report-page{
- height: calc(100dvh - 60px);
- min-height: calc(95vh - 60px);
- }
- }
- .van-cell{
- flex-shrink: 0;
- }
- .main-wrap{
- flex: 1;
- width: calc(100% - 32PX);
- margin: 0 auto;
- margin-top: 30px;
- .editor-box{
- width: 100%;
- height: 100%;
- }
- }
- @media screen and (min-width:$media-width){
- .main-wrap{
- margin-top: 15px;
- }
- }
- .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%);
- }
- }
- }
- @media screen and (min-width:$media-width){
- .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;
- }
- }
- }
- }
- </style>
|