jwyu 1 жил өмнө
parent
commit
9c61580f3f

+ 2 - 1
src/api/index.js

@@ -13,7 +13,8 @@ import { showLoadingToast,showToast,closeToast } from "vant";
 const LOADINGWHITELIST=[
   '/public/wechat_warning',
   '/report/saveReportContent',
-  '/report/editDayWeekChapter'
+  '/report/editDayWeekChapter',
+  '/english_report/saveReportContent'
 ]
 // 请求数
 let LOADINGCOUNT = 0;

+ 48 - 0
src/api/reportEn.js

@@ -89,5 +89,53 @@ export default {
      */
     emailResend:params=>{
         return post('/english_report/email/resend',params)
+    },
+    /**
+     * 通过报告分类id获取报告内容(继承上一篇报告)
+     * @param ClassifyIdFirst
+     * @param ClassifyIdSecond
+     */
+    reportDetailByClassifyId(params){
+        return get('/english_report/classifyIdDetail',params)
+    },
+    // 获取研报作者列表
+    reportAuthorList(params){
+        return get('/english_report/author',params)
+    },
+    /**
+     * 新增英文报告
+     */
+    reportAdd(params){
+        return post('/english_report/add',params)
+    },
+    /**
+     * 编辑英文报告
+     * @param ReportId
+     */
+    reportEdit(params){
+        return post('/english_report/edit',params)
+    },
+    /**
+     * 报告mark
+     * @param ReportId
+     * @param Status
+     */
+    reportMark(params){
+        return post('/english_report/mark',params)
+    },
+    /**
+     * 保存报告内容
+     * @param ReportId
+     * @param Content
+     * @param NoChange 0内容没变 1内容变了
+     */
+    reportContentSave(params){
+        return post('/english_report/saveReportContent',params)
+    },
+    /**
+     * 策略同步过来的报告编辑
+     */
+    strategyReportEdit(params){
+        return post('/english_report/edit_policy',params)
     }
 }

+ 24 - 11
src/hooks/useFroalaEditor.js

@@ -1,7 +1,7 @@
 import { ref } from "vue";
 
 export function useInitFroalaEditor() {
-	let FroalaEditorIns = ref(null);
+	// let FroalaEditorIns = ref(null);
 	let frolaEditorContentChange=ref(false)
 
 	const options = {
@@ -46,29 +46,42 @@ export function useInitFroalaEditor() {
 		toolbarSticky: false, //操作栏是否自动吸顶
 		saveInterval: 0,
 		charCounterCount: false,
-		reportloadding: false,
-		lastsavetime: '',
-		isAddEnter: false, //是否已经添加过
-		timer: null,
-		ischange: false,
-		isPublishloading: false,
 		events:{
 			contentChanged:function (){
-
 				frolaEditorContentChange.value=true
 			}
 		}
 	};
 
+	/**
+	 * 初始化编辑器
+	 * @param  el domid
+	 * @param  opts 配置项
+	 * 由于要获取到富文本实例 要在new FroalaEditor(el,opt,callback)的callback中才能获取到
+	 * 方案一返回一个promise
+	 * 方案二直接返回富文本实例 无法在调用initFroalaEditor方法后立即执行实例上的一些方法或者读取属性
+	 * 一般写个settimeout 可以解决
+	 */
 	const initFroalaEditor = (el,opts) => {
-		console.log(opts);
+		// 方案一
+		// let ins=null
+		// return new Promise((resolve,reject)=>{
+		// 	options.height=opts?.height??500
+		// 	console.log(options);
+		// 	ins=new FroalaEditor(el, options,()=>{
+		// 		// console.log(ins);
+		// 		resolve(ins)
+		// 	})
+		// })
+
+		// 方案二
 		options.height=opts?.height??500
 		console.log(options);
-		FroalaEditorIns.value = new FroalaEditor(el, options);
+		return new FroalaEditor(el, options);
 	};
 
 	return {
-		FroalaEditorIns,
+		// FroalaEditorIns,
 		frolaEditorContentChange,
 		initFroalaEditor,
 	}

+ 10 - 10
src/router/report.js

@@ -42,16 +42,16 @@ export const reportRoutes=[
             hasBackTop:true
         },
     },
-    {
-        path:"/report/detail",
-        name:"reportDetail",
-        component: () => import("@/views/report/Detail.vue"),
-        meta: { 
-            title: "中文研报",
-            keepAlive:false,
-            hasBackTop:true
-        },
-    },
+    // {
+    //     path:"/report/detail",
+    //     name:"reportDetail",
+    //     component: () => import("@/views/report/Detail.vue"),
+    //     meta: { 
+    //         title: "中文研报",
+    //         keepAlive:false,
+    //         hasBackTop:true
+    //     },
+    // },
     {
         path:"/report/chapter/list",
         name:"ReportChapterList",

+ 17 - 1
src/router/reportEn.js

@@ -1,5 +1,21 @@
 // 英文研报路由模块
- export const reportEnRoutes=[
+export const reportEnRoutes=[
+    {
+        path:"/reportEn/edit",
+        name:"ReportEnEdit",
+        component: () => import("@/views/reportEn/AddReport.vue"),
+        meta: { 
+            title: "编辑研报"
+        },
+    },
+    {
+        path:"/reportEn/add",
+        name:"ReportEnAdd",
+        component: () => import("@/views/reportEn/AddReport.vue"),
+        meta: { 
+            title: "添加研报"
+        },
+    },
     {
         path:"/reportEn/list",
         name:"ReportEnList",

+ 8 - 6
src/views/report/AddReport.vue

@@ -1,4 +1,4 @@
-<script setup name="ReportAdd">
+<script setup>
 import {ref,onMounted,onUnmounted} from 'vue'
 import {useInitFroalaEditor} from '@/hooks/useFroalaEditor'
 import EditReportBaseInfo from './components/EditReportBaseInfo.vue'
@@ -16,9 +16,11 @@ const router=useRouter()
 
 const {FroalaEditorIns,initFroalaEditor}=useInitFroalaEditor()
 
+let reportContentEditorIns=null//报告内容编辑器实例
+
 onMounted(() => {
     const el=document.getElementById('editor')
-    initFroalaEditor('#editor',{height:el.offsetHeight-150})
+    reportContentEditorIns=initFroalaEditor('#editor',{height:el.offsetHeight-150})
 })
 
 
@@ -51,7 +53,7 @@ async function handleReportBaseInfoChange(e){
                 reportBaseInfoData.createtime=moment().format('YYYY-MM-DD')
                 reportBaseInfoData.title=res.Data.Title
                 reportBaseInfoData.abstract=res.Data.Abstract
-                FroalaEditorIns.value.html.set(res.Data.Content);
+                reportContentEditorIns.html.set(res.Data.Content);
             }
         }
     }
@@ -72,21 +74,21 @@ function handleInsert({list,type,chartType}){
         if(chartType==='chart'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/chartshow':'https://charttest.hzinsights.com/chartshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                reportContentEditorIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
 						<iframe src='${link}?code=${item}&fromPage=' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 					</p>`,false)
             });
         }else if(chartType==='sheet'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/sheetshow':'https://charttest.hzinsights.com/sheetshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                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>`,false)
             });
         }
     }else if(type==='img'){
         list.forEach(item=>{
-            FroalaEditorIns.value.html.insert(`<img style='width:100%' src='${item}' />`,false)
+            reportContentEditorIns.html.insert(`<img style='width:100%' src='${item}' />`,false)
         })
     }
 

+ 7 - 6
src/views/report/EditReport.vue

@@ -16,12 +16,13 @@ const route=useRoute()
 
 
 const {FroalaEditorIns,initFroalaEditor,frolaEditorContentChange}=useInitFroalaEditor()
+let reportContentEditorIns=null//报告内容编辑器实例
 
 let autoSaveTimer=null
 
 onMounted(() => {
     const el=document.getElementById('editor')
-    initFroalaEditor('#editor',{height:el.offsetHeight-150})
+    reportContentEditorIns=initFroalaEditor('#editor',{height:el.offsetHeight-150})
     getReportDetail()
     autoSaveTimer=setInterval(() => {
         autoSaveReportContent()
@@ -68,7 +69,7 @@ async function getReportDetail(){
         reportBaseInfoData.title=res.Data.Title
         reportBaseInfoData.abstract=res.Data.Abstract
 
-        FroalaEditorIns.value.html.set(res.Data.Content);
+        reportContentEditorIns.html.set(res.Data.Content);
 
         // 查找选中的分类是否有电话会
         const classifyRes=await apiReport.getClassifyList({
@@ -124,7 +125,7 @@ async function handleReportBaseInfoChange(e){
                 reportBaseInfoData.createtime=moment().format('YYYY-MM-DD')
                 reportBaseInfoData.title=res.Data.Title
                 reportBaseInfoData.abstract=res.Data.Abstract
-                FroalaEditorIns.value.html.set(res.Data.Content);
+                reportContentEditorIns.html.set(res.Data.Content);
             }
         }
     }
@@ -145,21 +146,21 @@ function handleInsert({list,type,chartType}){
         if(chartType==='chart'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/chartshow':'https://charttest.hzinsights.com/chartshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                reportContentEditorIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
 						<iframe src='${link}?code=${item}&fromPage=' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 					</p>`,false)
             });
         }else if(chartType==='sheet'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/sheetshow':'https://charttest.hzinsights.com/sheetshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                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>`,false)
             });
         }
     }else if(type==='img'){
         list.forEach(item=>{
-            FroalaEditorIns.value.html.insert(`<img style='width:100%' src='${item}' />`,false)
+            reportContentEditorIns.html.insert(`<img style='width:100%' src='${item}' />`,false)
         })
     }
 

+ 11 - 10
src/views/report/chapter/Detail.vue

@@ -13,12 +13,13 @@ import { showToast,showDialog } from 'vant'
 import {useUploadFileToOSS} from '@/hooks/useUploadFileToOSS'
 import MD5 from 'js-md5'
 
+const route=useRoute()
+const router=useRouter()
 
 const userInfo=useUserInfo()
 
-const {FroalaEditorIns,initFroalaEditor,frolaEditorContentChange}=useInitFroalaEditor()
-const route=useRoute()
-const router=useRouter()
+const {initFroalaEditor,frolaEditorContentChange}=useInitFroalaEditor()
+let reportContentEditorIns=null//报告内容编辑器实例
 
 let autoSaveTimer=null
 
@@ -99,9 +100,9 @@ function getChapterDetail(){
             // 由于周报有个上传音频区域 所以得在此处初始化富文本区域 不然高度有问题
             nextTick(()=>{
                 const el=document.getElementById('editor')
-                initFroalaEditor('#editor',{height:el.offsetHeight-150})
+                reportContentEditorIns=initFroalaEditor('#editor',{height:el.offsetHeight-150})
                 setTimeout(() => {
-                    FroalaEditorIns.value.html.set(res.Data.Content);
+                    reportContentEditorIns.html.set(res.Data.Content);
                 }, 100);
             })
             
@@ -155,14 +156,14 @@ async function handleChapterBaseInfoSave(e){
                 chapterBaseInfo.title=res.Data.Title
                 chapterBaseInfo.author=res.Data.Author||userInfo.RealName
                 chapterBaseInfo.createTime=moment(res.Data.CreateTime).format('YYYY-MM-DD')
-                FroalaEditorIns.value.html.set(res.Data.Content);
+                reportContentEditorIns.html.set(res.Data.Content);
                 // 晨报获取指标数据
 				if(res.data.ReportType=='day'){
 					getDayTicketList()
 				}
             }
         }else{
-            FroalaEditorIns.value.html.set('');
+            reportContentEditorIns.html.set('');
         }
     }
     
@@ -246,21 +247,21 @@ function handleInsert({list,type,chartType}){
         if(chartType==='chart'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/chartshow':'https://charttest.hzinsights.com/chartshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                reportContentEditorIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
 						<iframe src='${link}?code=${item}&fromPage=' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 					</p>`,false)
             });
         }else if(chartType==='sheet'){
             link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/sheetshow':'https://charttest.hzinsights.com/sheetshow'
             list.forEach(item => {
-                FroalaEditorIns.value.html.insert(`<p style='text-align:left; margin-top:10px;'>
+                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>`,false)
             });
         }
     }else if(type==='img'){
         list.forEach(item=>{
-            FroalaEditorIns.value.html.insert(`<img style='width:100%' src='${item}' />`,false)
+            reportContentEditorIns.html.insert(`<img style='width:100%' src='${item}' />`,false)
         })
     }
 

+ 449 - 0
src/views/reportEn/AddReport.vue

@@ -0,0 +1,449 @@
+<script setup name="ReportEnAdd">
+import {ref,onMounted,onUnmounted, nextTick} from 'vue'
+import EditReportBaseInfo from './components/EditReportBaseInfo.vue'
+import ReportInsertContent from '../report/components/reportInsert/Index.vue'
+import apiReportEn from '@/api/reportEn'
+import apiChart from '@/api/chart'
+import moment from 'moment'
+import { showToast } from 'vant'
+import { useRoute, useRouter } from 'vue-router'
+import {useInitFroalaEditor} from '@/hooks/useFroalaEditor'
+import {useCachedViewsStore} from '@/store/modules/cachedViews'
+
+const cachedViewsStore=useCachedViewsStore()
+const router=useRouter()
+const route=useRoute()
+
+const {frolaEditorContentChange,initFroalaEditor}=useInitFroalaEditor()
+
+let reportContentIns=null//报告内容编辑器实例
+let overviewContentIns=null//overview内容编辑器实例
+
+let autoSaveTimer=null//自动保存定时器
+
+onMounted(async () => {
+    const el=document.getElementById('editor')
+    reportContentIns=initFroalaEditor('#editor',{height:el.offsetHeight-150})
+    if(route.query.id>0){
+        //编辑时
+        getReportDetail()
+        autoSaveTimer=setInterval(() => {
+            autoSaveReportContent()
+        }, 6000);
+    }
+})
+onUnmounted(()=>{
+    clearInterval(autoSaveTimer)
+})
+
+// 自动保存报告
+async function autoSaveReportContent(){
+    const res=await apiReportEn.reportContentSave({
+        ReportId:Number(route.query.id),
+        Content:$('#editor .fr-element').html(),
+        NoChange:frolaEditorContentChange.value?0:1
+    })
+    frolaEditorContentChange.value=false
+}
+
+// 获取报告详情
+const reportData=ref(null)
+async function getReportDetail(){
+    const res=await apiReportEn.getReportDetail({ReportId:Number(route.query.id)})
+    if(res.Ret===200){
+        reportData.value=res.Data
+        reportBaseInfoData.addType=res.Data.AddType
+        reportBaseInfoData.classifyName=[
+            {
+                id:res.Data.ClassifyIdFirst,
+                text:res.Data.ClassifyNameFirst
+            },
+            {
+                id:res.Data.ClassifyIdSecond,
+                text:res.Data.ClassifyNameSecond
+            }
+        ]
+        reportBaseInfoData.author=res.Data.Author ? res.Data.Author.split(',') : ['Horizon Insights FICC Team']
+        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
+
+        reportContentIns.html.set(res.Data.Content);
+        temOverviewData.value=res.Data.Overview
+
+    }
+}
+
+// 报告基本内容
+const showReportBaseInfo=ref(false)
+let reportBaseInfoData={
+    addType:1,
+    classifyName:[],
+    author:['Horizon Insights FICC Team'],
+    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 apiReportEn.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
+                reportContentIns.html.set(res.Data.Content);
+                temOverviewData.value=res.Data.Overview
+            }
+        }
+    }
+    
+    showReportBaseInfo.value=false
+}
+
+// overview
+const showEditOverview=ref(false)
+const temOverviewData=ref('')
+function handleShowOverview(){
+    showEditOverview.value=true
+    nextTick(()=>{
+        const el=document.getElementById('editor-overview')
+        overviewContentIns=initFroalaEditor('#editor-overview',{height:el.offsetHeight-150})
+        if(temOverviewData.value){
+            setTimeout(() => {
+                overviewContentIns.html.set(temOverviewData.value)
+            }, 100);
+        }
+    })
+}
+function handleSaveOverview(){
+    temOverviewData.value=$('#editor-overview .fr-element').html()
+    showEditOverview.value=false
+}
+
+
+// 报告插入数据弹窗
+const showReportInsertPop=ref(false)
+/**
+ * list:[UniqueCode] 图表code
+ * type:iframe/img 插入的为iframe或者图片
+ * chartType: chart-图表,sheet-表格
+ */
+function handleInsert({list,type,chartType}){
+    if(type==='iframe'){
+        let link;
+        if(chartType==='chart'){
+            link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/chartshow':'https://charttest.hzinsights.com/chartshow'
+            list.forEach(item => {
+                reportContentIns.html.insert(`<p style='text-align:left; margin-top:10px;'>
+						<iframe src='${link}?code=${item}&fromPage=en' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+					</p>`,false)
+            });
+        }else if(chartType==='sheet'){
+            link=import.meta.env.MODE==='production'?'https://chartlib.hzinsights.com/sheetshow':'https://charttest.hzinsights.com/sheetshow'
+            list.forEach(item => {
+                reportContentIns.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>`,false)
+            });
+        }
+    }else if(type==='img'){
+        list.forEach(item=>{
+            reportContentIns.html.insert(`<img style='width:100%' src='${item}' />`,false)
+        })
+    }
+
+    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(()=>{
+    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('刷新成功')
+    }
+}
+
+
+// 报告操作
+async function handleReportOpt(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:$('#editor .fr-element').html(),
+        CreateTime:moment(reportBaseInfoData.createtime).format('YYYY.MM.DD'),
+        State: 1,
+        ReportVersion: 2,
+        Overview:temOverviewData.value
+    }
+    
+    if(reportBaseInfoData.classifyName.length!=2){
+        showToast('请选择分类')
+        return
+    }
+    if(!reportBaseInfoData.title){
+        showToast('请输入标题')
+        return
+    }
+    if(!params.Overview){
+        showToast('请输入overview')
+        return
+    }
+    if(!params.Content){
+        showToast('请输入content')
+        return
+    }
+    if(!params.Abstract){
+        showToast('请输入摘要')
+        return
+    }
+
+    if(e==='yl'){
+        sessionStorage.setItem('reportEnPreData',JSON.stringify(params))
+        const routerEl=router.resolve({
+            path:'/reportEn/detail',
+            query:{
+                id:-1
+            }
+        })
+        window.open(routerEl.href,'_blank')
+        return
+    }
+
+    const res=route.query.id
+    ?await apiReportEn.reportEdit({ReportId:Number(route.query.id),...params})
+    :await apiReportEn.reportAdd(params)
+    if(res.Ret!==200) return
+    cachedViewsStore.removeCaches('ReportEnList')
+    if(e==='cg'){
+        showToast('保存成功')
+        setTimeout(() => {
+            router.replace({
+                path:'/reportEn/edit',
+                query:{
+                    id:res.Data.ReportId
+                }
+            })
+        }, 1000);
+    }
+    if(e==='fb'){
+        reportPublish(res.Data.ReportId)
+    }
+    
+}
+
+// 发布报告
+function reportPublish(id){
+    apiReportEn.reportPublish({ReportIds:id.toString()}).then(res=>{
+        if(res.Ret===200){
+            showToast('发布成功')
+            setTimeout(() => {
+                router.back()
+            }, 1500);
+        }
+    })
+}
+
+</script>
+
+<template>
+    <div class="reporten-add-page">
+        <van-cell title="基础信息" is-link @click="showReportBaseInfo=true"/>
+        <van-cell title="Overview" is-link @click="handleShowOverview"/>
+        <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')">
+                    <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>
+                <div class="item" @click="handleReportOpt('fb')">
+                    <img src="@/assets/imgs/report/icon_publish3.png" alt="">
+                    <span>发布</span>
+                </div>
+            </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 v-if="showReportBaseInfo" :defaultData="reportBaseInfoData" @close="showReportBaseInfo=false" @confirm="handleReportBaseInfoChange"/>
+    </van-popup>
+
+    <!-- 报告overview -->
+    <van-popup
+        v-model:show="showEditOverview"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="overview-edit-wrap">
+            <h3>Overview</h3>
+            <div id="editor-overview"></div>
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="primary" @click="handleSaveOverview">保存</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 报告插入数据模块 -->
+    <van-popup
+        v-model:show="showReportInsertPop"
+        position="bottom"
+        round
+    >
+        <report-insert-content v-if="showReportInsertPop" @insert="handleInsert"/>
+    </van-popup>
+
+</template>
+
+<style lang="scss" scoped>
+.reporten-add-page{
+    height: 100dvh;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+}
+.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%;
+    }
+}
+.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%);
+        }
+    }
+}
+
+.overview-edit-wrap{
+    overflow: hidden;
+    padding: $page-padding;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    #editor-overview{
+        flex: 1;
+    }
+    .bot-btns{
+        text-align: center;
+        padding-top: $page-padding;
+        .bot-btn{
+            width: 90%;
+        }
+    }
+}
+
+</style>

+ 34 - 112
src/views/reportEn/Detail.vue

@@ -3,18 +3,26 @@ import {ref} from 'vue'
 import { useRoute, useRouter } from "vue-router";
 import apiReportEn from '@/api/reportEn'
 import { showToast,showDialog } from 'vant';
-import SendEmail from './components/SendEmail.vue';
-import {useCachedViewsStore} from '@/store/modules/cachedViews'
-const cachedViewsStore=useCachedViewsStore()
 
 const route=useRoute()
 const router=useRouter()
 
-const showSendEmail=ref(false)
-
 // 获取报告详情
 let reportInfo=ref(null)
 async function getReportDetail(){
+    if(route.query.id==-1){
+        //编辑时预览来的
+        const data=JSON.parse(sessionStorage.getItem('reportEnPreData'))
+        reportInfo.value={
+            Title:data.Title,
+            Author:data.Author,
+            PublishTime:data.CreateTime,
+            Abstract:data.Abstract,
+            Overview:data.Overview,
+            Content:data.Content
+        }
+        return
+    }
     const res=await apiReportEn.getReportDetail({ReportId:Number(route.query.id)})
     if(res.Ret===200){
         reportInfo.value=res.Data
@@ -23,101 +31,38 @@ async function getReportDetail(){
 }
 getReportDetail()
 
-// 发布报告
-async function handleReportPublish(){
-    showDialog({
-        title: '发布提示',
-        message: `是否发布报告?`,
-        showCancelButton:true
-    }).then(()=>{
-        apiReportEn.reportPublish({
-            ReportIds:route.query.id
-        }).then(res=>{
-            if(res.Ret===200){
-                showToast('发布成功')
-                cachedViewsStore.removeCaches('ReportEnList')
-                getReportDetail()
-            }
-        })
-    })
-}
-
-// 取消发布
-function handleReportPublishCancle(){
-    showDialog({
-        title: '提示',
-        message: `是否确认取消发布?`,
-        showCancelButton:true
-    }).then(()=>{
-        apiReportEn.reportPublishCancle({ReportIds:Number(route.query.id)}).then(res=>{
-            if(res.Ret===200){
-                showToast('取消发布成功')
-                cachedViewsStore.removeCaches('ReportEnList')
-                getReportDetail()
-            }
-        })
+//去编辑
+async function goEdit(){
+    // 先mark一下
+    const markRes=await apiReportEn.reportMark({
+        Status:1,
+        ReportId:reportInfo.value.Id
     })
-}
-
-// 删除报告
-function handleDelReport(){
-    showDialog({
-        title: '提示',
-        message: '删除操作不可恢复,确认删除吗?',
-        showCancelButton:true
-    }).then(() => {
-        // on close
-        apiReportEn.reportDel({ReportIds:Number(route.query.id)}).then(res=>{
-            if(res.Ret===200){
-                showToast('删除成功')
-                cachedViewsStore.removeCaches('ReportEnList')
-                router.back()
-            }
-        })
-    }).catch(()=>{})
-}
+    if(markRes.Ret===200){
+        if(markRes.Data.Status===1){
+            showToast(markRes.Data.Msg || '该研报正在编辑,不可重复编辑')
+            return
+        }
+    }else{
+        showToast(markRes.ErrMsg || '未知错误,请稍后重试')
+        return
+    }
 
-// 查看群发邮件日志
-function handleGoEmailLog(){
     router.push({
-        path:'/reportEn/sendemaillog',
+        path:'/reportEn/edit',
         query:{
-            id:route.query.id,
-            hasFail:reportInfo.value.EmailHasFail
+            id:reportInfo.value.Id
         }
     })
 }
+
 </script>
 
 <template>
     <div class="report-detail-page" v-if="reportInfo">
-        <div class="top-stage-box">
+        <div class="top-stage-box" v-if="route.query.id>0">
             <span class="stage">第{{reportInfo.Stage}}期 / {{reportInfo.Frequency}}</span>
-            <template v-if="reportInfo.State===1">
-                <!-- 删除 -->
-                <div class="btn-item red-bg" @click="handleDelReport">
-                    <img src="@/assets/imgs/icon_del.png" alt="">
-                </div>
-                <!-- 发布 -->
-                <div class="btn-item" @click="handleReportPublish">
-                    <img src="@/assets/imgs/report/icon_publish.png" alt="">
-                </div>
-            </template>
-            <template v-if="reportInfo.State===2">
-                <!-- 群发邮件 -->
-                <div class="btn-item"  @click="showSendEmail=true" v-if="reportInfo.EmailState===0&&reportInfo.EmailAuth">
-                    <img src="@/assets/imgs/report/icon_sendemail.png" alt="">
-                </div>
-                <!-- 群发日志 -->
-                <div class="btn-item"  @click="handleGoEmailLog" v-if="reportInfo.EmailState===1&&reportInfo.EmailAuth">
-                    <img src="@/assets/imgs/report/icon_sendemaillog.png" alt="">
-                </div>
-
-                <!-- 取消发布 -->
-                <div class="btn-item red-bg" @click="handleReportPublishCancle">
-                    <img src="@/assets/imgs/report/icon_publish_cancel2.png" alt="">
-                </div>
-            </template>
+            <img v-if="reportInfo.State==1" class="edit-icon" src="@/assets/imgs/report/icon_edit2.png" alt="" @click="goEdit">
         </div>
         <h1 class="report-title">{{reportInfo.Title}}</h1>
         <div class="auth-box">
@@ -129,16 +74,6 @@ function handleGoEmailLog(){
         
         <div class="report-html-wrap" v-html="reportInfo.Content"></div>
     </div>
-
-    <!-- 群发邮件弹窗 -->
-    <van-popup 
-        v-model:show="showSendEmail"
-        position="bottom"
-        :style="{ height: '100%' }"
-        closeable
-    >
-        <SendEmail :reportId="reportInfo.Id" :defaultThemeVal="reportInfo.Abstract" @close="showSendEmail=false;getReportDetail()"/>
-    </van-popup>
 </template>
 
 <style lang="scss" scoped>
@@ -196,23 +131,10 @@ function handleGoEmailLog(){
         padding: 0 20px;
         font-size: 28px;
     }
-    .btn-item{
+    .edit-icon{
         float: right;
         width: 70px;
         height: 70px;
-        border-radius: 50%;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        background-color: #F2F3FF;
-        margin-left: 40px;
-        img{
-            width: 48px;
-            height: 48px;
-        }
-    }
-    .red-bg{
-        background-color: #FFF2F2;
     }
 }
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 120 - 10
src/views/reportEn/List.vue


+ 337 - 0
src/views/reportEn/components/EditReportBaseInfo.vue

@@ -0,0 +1,337 @@
+<script setup>
+import moment from "moment"
+import { computed, reactive,ref } from "vue"
+import ListClassify from './ListClassify.vue'
+import apiReportEn from '@/api/reportEn'
+import {reportFrequencyOpts} from '@/views/report/utils/config'
+import { showToast } from "vant"
+import { useRoute } from "vue-router"
+
+const route=useRoute()
+
+const props=defineProps({
+    defaultData:null
+})
+
+const emits=defineEmits(['close','confirm'])
+
+// 基本数据
+const reportBaseInfo=reactive({
+    addType:props.defaultData?props.defaultData.addType:1,
+    classifyName:props.defaultData?props.defaultData.classifyName:[],
+    author:props.defaultData?props.defaultData.author:['Horizon Insights FICC Team'],
+    frequency: props.defaultData?props.defaultData.frequency:['日度'],
+    createtime:props.defaultData?props.defaultData.createtime:moment().format('YYYY-MM-DD'),
+    title:props.defaultData?props.defaultData.title:'',
+    abstract:props.defaultData?props.defaultData.abstract:''
+})
+
+// 报告新增类型
+const showAddTypePop=ref(false)
+const addTypeOpts=[
+    {
+        value:1,
+        name:'新增报告'
+    },
+    {
+        value:2,
+        name:'继承报告'
+    }
+]
+function handleShowAddType(){
+    // 编辑时不可操作
+    if(route.path=='/reportEn/edit') return
+    showAddTypePop.value=true
+}
+function getAddTypeName(value){
+    return addTypeOpts.filter(item=>item.value===value)[0].name
+}
+function selectAddType(e){
+    reportBaseInfo.addType=e.value
+}
+
+// 报告所属分类
+const showClassifyPop=ref(false)
+const setClassifyVal=computed(()=>{
+    if(reportBaseInfo.classifyName.length===2){
+        return `${reportBaseInfo.classifyName[0].text}/${reportBaseInfo.classifyName[1].text}`
+    }
+    return '请选择分类'
+})
+function handleShowClassify(){
+    showClassifyPop.value=true
+}
+function handleConfirmClassify({firstClassify,secondClassify}){
+    if(!firstClassify.id||!secondClassify.id){
+        showToast('请选择分类')
+        return
+    }
+    reportBaseInfo.classifyName=[firstClassify,secondClassify]
+    reportBaseInfo.title=secondClassify.text
+    showClassifyPop.value=false
+}
+
+// 研报作者
+const showAuthorPop=ref(false)
+const authorOpts=ref([])
+const temAuthorVal=ref([])
+function handleShowSelectAuthor(){
+    temAuthorVal.value=reportBaseInfo.author
+    showAuthorPop.value=true
+}
+function handleConfirmAuthor(){
+    reportBaseInfo.author=temAuthorVal.value
+    showAuthorPop.value=false
+}
+function getAuthorOpts(){
+    apiReportEn.reportAuthorList({}).then(res=>{
+        if(res.Ret===200){
+            authorOpts.value=res.Data?.List??[]
+        }
+    })
+}
+getAuthorOpts()
+
+// 报告频度
+const showFrequencyPop=ref(false)
+const temFrequencyVal=ref(['日度'])
+function handleShowFrequency(){
+    temFrequencyVal.value=reportBaseInfo.frequency
+    showFrequencyPop.value=true
+}
+function handleConfirmFrequency(){
+    reportBaseInfo.frequency=temFrequencyVal.value
+    showFrequencyPop.value=false
+}
+
+// 创建日期
+const minDate=new Date(2015, 0, 1)
+const defaultDate=ref(new Date())
+const showCreateTimePop=ref(false)
+function handleShowCreatetime(){
+    defaultDate.value=new Date(reportBaseInfo.createtime.replace(/-/g,'/'))
+    showCreateTimePop.value=true
+}
+function handleConfirmCreatime(e){
+    reportBaseInfo.createtime=moment(e).format('YYYY-MM-DD')
+    showCreateTimePop.value=false
+}
+
+// 报告标题
+const showReportTitlePop=ref(false)
+const temReportTitleVal=ref('')
+function handleShowReportTitle(){
+    temReportTitleVal.value=reportBaseInfo.title
+    showReportTitlePop.value=true
+}
+function handleConfirmReportTitle(){
+    reportBaseInfo.title=temReportTitleVal.value
+    showReportTitlePop.value=false
+}
+
+// 摘要
+const showReportAbsPop=ref(false)
+const temReportAbsVal=ref('')
+function handleShowReportAbs(){
+    temReportAbsVal.value=reportBaseInfo.abstract
+    showReportAbsPop.value=true
+}
+function handleConfirmReportAbs(){
+    reportBaseInfo.abstract=temReportAbsVal.value
+    showReportAbsPop.value=false
+}
+
+
+
+function close(){
+    emits('close')
+}
+
+function handleSave(){
+    emits('confirm',reportBaseInfo)
+}
+</script>
+
+<template>
+    <div class="report-baseinfo-wrap">
+        <van-cell-group>
+            <van-cell value-class="cell-con" required title="新增方式" :value="getAddTypeName(reportBaseInfo.addType)" :is-link="route.path!='/reportEn/edit'" @click="handleShowAddType"/>
+            <van-cell value-class="cell-con" required title="分类" :value="setClassifyVal" is-link @click="handleShowClassify"/>
+            <van-cell value-class="cell-con" title="作者" :value="reportBaseInfo.author.join(',')" is-link @click="handleShowSelectAuthor"/>
+            <van-cell value-class="cell-con" title="频度" :value="reportBaseInfo.frequency.join('')" is-link @click="handleShowFrequency"/>
+            <van-cell value-class="cell-con" title="创建时间" :value="reportBaseInfo.createtime" is-link @click="handleShowCreatetime"/>
+        </van-cell-group>
+
+        <van-cell-group style="margin:10px 0">
+            <van-cell required title="标题" :label="reportBaseInfo.title" is-link @click="handleShowReportTitle"/>
+        </van-cell-group>
+
+        <van-cell-group>
+            <van-cell required title="摘要" :label="reportBaseInfo.abstract" is-link @click="handleShowReportAbs"/>
+        </van-cell-group>
+
+        <div class="bot-btns">
+            <van-button class="bot-btn" type="default" @click="close">取消</van-button>
+            <van-button class="bot-btn" type="primary" @click="handleSave">保存</van-button>
+        </div>
+        
+    </div>
+
+    <!-- 新增方式 -->
+    <van-action-sheet 
+        v-model:show="showAddTypePop"
+        cancel-text="取消"
+        close-on-click-action
+        :actions="addTypeOpts" 
+        @select="selectAddType" 
+    />
+
+    <!-- 分类 -->
+    <van-popup
+        v-model:show="showClassifyPop"
+        position="bottom"
+        round
+    >
+        <ListClassify
+            v-if="showClassifyPop"
+            :defaultVal="reportBaseInfo.classifyName"
+            :noReset="true"
+            :firstClassifyDisabled="true" 
+            @close="showClassifyPop=false" 
+            @confirm="handleConfirmClassify"
+        />
+    </van-popup>
+
+    <!-- 作者 -->
+    <van-popup
+        v-model:show="showAuthorPop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="select-author-pop">
+            <van-checkbox-group v-model="temAuthorVal">
+                <van-checkbox
+                    v-for="item in authorOpts"
+                    :key="item.Id"
+                    :name="item.ReportAuthor"
+                >{{item.ReportAuthor}}</van-checkbox>
+            </van-checkbox-group>
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showAuthorPop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" @click="handleConfirmAuthor">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 报告频度 -->
+    <van-popup
+        v-model:show="showFrequencyPop"
+        position="bottom"
+        round
+    >
+        <van-picker 
+            v-model="temFrequencyVal" 
+            title="选择频度" 
+            :columns="reportFrequencyOpts"
+            @confirm="handleConfirmFrequency"
+            @cancel="showFrequencyPop=false"
+        />
+    </van-popup>
+
+    <!-- 创建日期 -->
+    <van-calendar
+        :min-date="minDate"
+        :default-date="defaultDate"
+        v-model:show="showCreateTimePop"
+        title="选择创建日期"
+        @confirm="handleConfirmCreatime" 
+    />
+
+    <!-- 标题 -->
+    <van-popup
+        v-model:show="showReportTitlePop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="input-report-title-pop">
+             <van-field v-model="temReportTitleVal" placeholder="请输入报告标题" />
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showReportTitlePop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" :disabled="!temReportTitleVal" @click="handleConfirmReportTitle">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 摘要 -->
+    <van-popup
+        v-model:show="showReportAbsPop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="input-report-title-pop">
+             <van-field type="textarea" autosize v-model="temReportAbsVal" placeholder="请输入报告摘要" />
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showReportAbsPop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" :disabled="!temReportAbsVal" @click="handleConfirmReportAbs">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+</template>
+
+<style lang="scss" scoped>
+.report-baseinfo-wrap{
+    height: 100%;
+    position: relative;
+    background: $page-bg-grey;
+    :deep(.cell-con){
+        flex: 2;
+    }
+    .bot-btns{
+        position: absolute;
+        bottom: 48px;
+        left: 0;
+        width: 100%;
+        text-align: center;
+    }
+}
+.bot-btn{
+    width: 315px;
+    margin: 0 10px;
+}
+
+.select-author-pop{
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    .van-checkbox-group{
+        padding: $page-padding;
+        flex: 1;
+        overflow-y: auto;
+        .van-checkbox{
+            :deep(.van-checkbox__label){
+                padding: 32px 0;
+                flex: 1;
+                border-bottom: 1px solid $border-color;
+            }
+        }
+    }
+    .bot-btns{
+        flex-shrink: 0;
+        padding: 20px 0;
+        text-align: center;
+    }
+}
+.input-report-title-pop{
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    background-color: $page-bg-grey;
+    
+    .bot-btns{
+        flex-shrink: 0;
+        padding: 20px 0;
+        text-align: center;
+    }
+}
+</style>

+ 270 - 0
src/views/reportEn/components/EditStrategyReport.vue

@@ -0,0 +1,270 @@
+<script setup>
+import moment from "moment"
+import { reactive,ref } from "vue"
+import apiReportEn from '@/api/reportEn'
+import {reportFrequencyOpts} from '@/views/report/utils/config'
+import { showToast } from "vant"
+
+
+const props=defineProps({
+    defaultData:null
+})
+
+const emits=defineEmits(['close','confirm'])
+
+const baseInfo=reactive({
+    author:props.defaultData?[props.defaultData.Author]:['Horizon Insights FICC Team'],
+    frequency: props.defaultData?[props.defaultData.Frequency]:['日度'],
+    createtime:props.defaultData?moment(props.defaultData.CreateTime).format('YYYY-MM-DD'):moment().format('YYYY-MM-DD'),
+    title:props.defaultData?props.defaultData.Title:'',
+    abstract:props.defaultData?props.defaultData.Abstract:''
+})
+
+// 研报作者
+const showAuthorPop=ref(false)
+const authorOpts=ref([])
+const temAuthorVal=ref([])
+function handleShowSelectAuthor(){
+    temAuthorVal.value=baseInfo.author
+    showAuthorPop.value=true
+}
+function handleConfirmAuthor(){
+    baseInfo.author=temAuthorVal.value
+    showAuthorPop.value=false
+}
+function getAuthorOpts(){
+    apiReportEn.reportAuthorList({}).then(res=>{
+        if(res.Ret===200){
+            authorOpts.value=res.Data?.List??[]
+        }
+    })
+}
+getAuthorOpts()
+
+// 报告频度
+const showFrequencyPop=ref(false)
+const temFrequencyVal=ref(['日度'])
+function handleShowFrequency(){
+    temFrequencyVal.value=baseInfo.frequency
+    showFrequencyPop.value=true
+}
+function handleConfirmFrequency(){
+    baseInfo.frequency=temFrequencyVal.value
+    showFrequencyPop.value=false
+}
+
+// 创建日期
+const minDate=new Date(2015, 0, 1)
+const defaultDate=ref(new Date())
+const showCreateTimePop=ref(false)
+function handleShowCreatetime(){
+    defaultDate.value=new Date(baseInfo.createtime.replace(/-/g,'/'))
+    showCreateTimePop.value=true
+}
+function handleConfirmCreatime(e){
+    baseInfo.createtime=moment(e).format('YYYY-MM-DD')
+    showCreateTimePop.value=false
+}
+
+// 报告标题
+const showReportTitlePop=ref(false)
+const temReportTitleVal=ref('')
+function handleShowReportTitle(){
+    temReportTitleVal.value=baseInfo.title
+    showReportTitlePop.value=true
+}
+function handleConfirmReportTitle(){
+    baseInfo.title=temReportTitleVal.value
+    showReportTitlePop.value=false
+}
+
+// 摘要
+const showReportAbsPop=ref(false)
+const temReportAbsVal=ref('')
+function handleShowReportAbs(){
+    temReportAbsVal.value=baseInfo.abstract
+    showReportAbsPop.value=true
+}
+function handleConfirmReportAbs(){
+    baseInfo.abstract=temReportAbsVal.value
+    showReportAbsPop.value=false
+}
+
+
+
+function close(){
+    emits('close')
+}
+
+async function handleSave(){
+    const res=await apiReportEn.strategyReportEdit({
+        ReportId:props.defaultData.Id,
+        Title:baseInfo.title,
+        Abstract:baseInfo.abstract,
+        Author:baseInfo.author.join(','),
+        Frequency:baseInfo.frequency[0],
+        CreateTime:baseInfo.createtime
+    })
+    if(res.Ret===200){
+        showToast('编辑成功')
+        emits('confirm')
+    }
+}
+</script>
+
+<template>
+    <div class="edit-strategy-report-wrap">
+        <van-cell-group>
+            <van-cell value-class="cell-con" required title="分类" :value="defaultData.ClassifyNameFirst+'/'+defaultData.ClassifyNameSecond" />
+            <van-cell value-class="cell-con" title="作者" :value="baseInfo.author.join(',')" is-link @click="handleShowSelectAuthor"/>
+            <van-cell value-class="cell-con" title="频度" :value="baseInfo.frequency.join('')" is-link @click="handleShowFrequency"/>
+            <van-cell value-class="cell-con" title="创建时间" :value="baseInfo.createtime" is-link @click="handleShowCreatetime"/>
+        </van-cell-group>
+
+        <van-cell-group style="margin:10px 0">
+            <van-cell required title="标题" :label="baseInfo.title" is-link @click="handleShowReportTitle"/>
+        </van-cell-group>
+
+        <van-cell-group>
+            <van-cell required title="摘要" :label="baseInfo.abstract" is-link @click="handleShowReportAbs"/>
+        </van-cell-group>
+
+        <div class="bot-btns">
+            <van-button class="bot-btn" type="default" @click="close">取消</van-button>
+            <van-button class="bot-btn" type="primary" @click="handleSave">保存</van-button>
+        </div>
+    </div>
+
+    <!-- 作者 -->
+    <van-popup
+        v-model:show="showAuthorPop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="select-author-pop">
+            <van-checkbox-group v-model="temAuthorVal">
+                <van-checkbox
+                    v-for="item in authorOpts"
+                    :key="item.Id"
+                    :name="item.ReportAuthor"
+                >{{item.ReportAuthor}}</van-checkbox>
+            </van-checkbox-group>
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showAuthorPop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" @click="handleConfirmAuthor">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 报告频度 -->
+    <van-popup
+        v-model:show="showFrequencyPop"
+        position="bottom"
+        round
+    >
+        <van-picker 
+            v-model="temFrequencyVal" 
+            title="选择频度" 
+            :columns="reportFrequencyOpts"
+            @confirm="handleConfirmFrequency"
+            @cancel="showFrequencyPop=false"
+        />
+    </van-popup>
+
+    <!-- 创建日期 -->
+    <van-calendar
+        :min-date="minDate"
+        :default-date="defaultDate"
+        v-model:show="showCreateTimePop"
+        title="选择创建日期"
+        @confirm="handleConfirmCreatime" 
+    />
+
+    <!-- 标题 -->
+    <van-popup
+        v-model:show="showReportTitlePop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="input-report-title-pop">
+             <van-field v-model="temReportTitleVal" placeholder="请输入报告标题" />
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showReportTitlePop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" :disabled="!temReportTitleVal" @click="handleConfirmReportTitle">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+
+    <!-- 摘要 -->
+    <van-popup
+        v-model:show="showReportAbsPop"
+        position="bottom"
+        :style="{ height: '100%' }"
+    >
+        <div class="input-report-title-pop">
+             <van-field type="textarea" autosize v-model="temReportAbsVal" placeholder="请输入报告摘要" />
+            <div class="bot-btns">
+                <van-button class="bot-btn" type="default" @click="showReportAbsPop=false">取消</van-button>
+                <van-button class="bot-btn" type="primary" :disabled="!temReportAbsVal" @click="handleConfirmReportAbs">确定</van-button>
+            </div>
+        </div>
+    </van-popup>
+</template>
+
+<style lang="scss" scoped>
+.edit-strategy-report-wrap{
+    height: 100%;
+    position: relative;
+    background: $page-bg-grey;
+    :deep(.cell-con){
+        flex: 2;
+    }
+    .bot-btns{
+        position: absolute;
+        bottom: 48px;
+        left: 0;
+        width: 100%;
+        text-align: center;
+    }
+}
+.bot-btn{
+    width: 315px;
+    margin: 0 10px;
+}
+
+.select-author-pop{
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    .van-checkbox-group{
+        padding: $page-padding;
+        flex: 1;
+        overflow-y: auto;
+        .van-checkbox{
+            :deep(.van-checkbox__label){
+                padding: 32px 0;
+                flex: 1;
+                border-bottom: 1px solid $border-color;
+            }
+        }
+    }
+    .bot-btns{
+        flex-shrink: 0;
+        padding: 20px 0;
+        text-align: center;
+    }
+}
+.input-report-title-pop{
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    background-color: $page-bg-grey;
+    
+    .bot-btns{
+        flex-shrink: 0;
+        padding: 20px 0;
+        text-align: center;
+    }
+}
+</style>

+ 35 - 6
src/views/reportEn/components/ListClassify.vue

@@ -2,6 +2,12 @@
 import {ref} from 'vue'
 import apiReportEn from '@/api/reportEn'
 
+const props=defineProps({
+    defaultVal:null,
+    noReset:false,
+    firstClassifyDisabled:false,//一级分类是否要判断禁用
+})
+
 const emits=defineEmits(['close','confirm'])
 
 const list=ref([])
@@ -9,7 +15,7 @@ function getClassifyList(){
     apiReportEn.getClassifyList({
         CurrentIndex:1,
         PageSize:1000,
-        KeyWord:''
+        KeyWord:'',
     }).then(res=>{
         if(res.Ret===200){
             const arr=res.Data.List||[]
@@ -17,14 +23,24 @@ function getClassifyList(){
                 const child=item.Child?item.Child.map(e=>{
                     return {
                         text:e.ClassifyName,
-                        id:e.ClassifyName
+                        id:e.Id
                     }
                 }):[]
                 return {
                     text:item.ClassifyName,
-                    children:child
+                    id:item.Id,
+                    children:child,
+                    disabled:props.firstClassifyDisabled&&child.length===0?true:false,
                 }
             })
+            if(props.defaultVal&&props.defaultVal[1]){
+                activeId.value=props.defaultVal[1].id
+                list.value.forEach((item,index)=>{
+                    if(item.id===props.defaultVal[0].id){
+                        activeIndex.value=index
+                    }
+                })
+            }
         }
     })
 }
@@ -44,8 +60,19 @@ function handleReset(){
 }
 
 function handleConfirm(){
-    const firstClassify=list.value[activeIndex.value].text
-    const secondClassify=activeId.value||''
+    const firstClassify={
+        text:list.value[activeIndex.value].text,
+        id:list.value[activeIndex.value].id
+    }
+    let secondClassify={text:'',id:''}
+    if(activeId.value){
+        list.value[activeIndex.value].children.forEach(e => {
+            if(e.id===activeId.value){
+                secondClassify.text=e.text
+                secondClassify.id=e.id
+            }
+        });
+    }
     emits('confirm',{firstClassify,secondClassify})
 }
 </script>
@@ -53,7 +80,8 @@ function handleConfirm(){
 <template>
     <div class="report-list-classify-wrap">
         <div class="top-box">
-            <span style="color:#666666" @click="handleReset">重置</span>
+            <span style="color:#666666" @click="handleCancle" v-if="props.noReset">取消</span>
+            <span style="color:#666666" @click="handleReset" v-else>重置</span>
             <span style="font-size:18px;font-weight:bold">选择分类</span>
             <span style="color:#0052D9" @click="handleConfirm">确定</span>
         </div>
@@ -61,6 +89,7 @@ function handleConfirm(){
             v-model:active-id="activeId"
             v-model:main-active-index="activeIndex"
             :items="list"
+            @click-nav="activeId=null"
         />
     </div>
 </template>

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно