浏览代码

Merge branch 'eta1.8.3'

Karsa 10 月之前
父节点
当前提交
7cae6df5f1
共有 73 个文件被更改,包括 11715 次插入109 次删除
  1. 429 0
      src/api/modules/reportV2.js
  2. 二进制
      src/assets/img/data_m/move_ico.png
  3. 1 0
      src/assets/img/icons/baseinfo_ico.svg
  4. 4 0
      src/assets/img/icons/preview_ico.svg
  5. 4 0
      src/assets/img/icons/publish_ico.svg
  6. 5 0
      src/assets/img/icons/save_ico.svg
  7. 4 0
      src/assets/img/icons/submit_ico.svg
  8. 4 0
      src/assets/img/icons/timing_ico.svg
  9. 14 0
      src/assets/img/icons/wx_round.svg
  10. 16 0
      src/lang/commonLang.js
  11. 4 4
      src/lang/modules/ReportManagement/CategoryList.js
  12. 112 8
      src/lang/modules/ReportManagement/ReportList.js
  13. 4 4
      src/lang/modules/ReportManagement/SmartReport.js
  14. 2 2
      src/lang/modules/systemManage/ReportApprove.js
  15. 5 2
      src/mixins/reportApproveConfig.js
  16. 28 16
      src/routes/modules/oldRoutes.js
  17. 8 1
      src/utils/buttonConfig.js
  18. 12 0
      src/utils/common.js
  19. 1 1
      src/views/Login.vue
  20. 4 4
      src/views/approve_manage/approveDetail.vue
  21. 14 8
      src/views/approve_manage/approveEdit.vue
  22. 2 2
      src/views/approve_manage/components/flowNode/approveNode.vue
  23. 1 1
      src/views/approve_manage/mixins/approveMixins.js
  24. 28 14
      src/views/classify_manage/chapterSettingV2.vue
  25. 1 0
      src/views/classify_manage/classifyEnlistV2.vue
  26. 137 28
      src/views/classify_manage/classifylistV2.vue
  27. 4 2
      src/views/ppt_manage/mixins/pptMixins.js
  28. 3 4
      src/views/ppt_manage/newVersion/components/catalog/transReport.vue
  29. 8 2
      src/views/ppt_manage/newVersion/pptCatalog.vue
  30. 1 1
      src/views/report_manage/addreportNew.vue
  31. 1 1
      src/views/report_manage/editChapterReport.vue
  32. 1 1
      src/views/report_manage/editreportNew.vue
  33. 869 0
      src/views/report_manage/reportV2/components/chapterEditWrapper.vue
  34. 201 0
      src/views/report_manage/reportV2/components/chooseCooperaUserDia.vue
  35. 195 0
      src/views/report_manage/reportV2/components/chooseInherReportDia.vue
  36. 585 0
      src/views/report_manage/reportV2/components/reportBaseInfoDia.vue
  37. 167 0
      src/views/report_manage/reportV2/components/reportEditHeader.vue
  38. 168 0
      src/views/report_manage/reportV2/components/reportPreview.vue
  39. 178 0
      src/views/report_manage/reportV2/components/smartTerritorSetDia.vue
  40. 1218 0
      src/views/report_manage/reportV2/list.vue
  41. 86 0
      src/views/report_manage/reportV2/normalReport/components/ETAChart.vue
  42. 144 0
      src/views/report_manage/reportV2/normalReport/components/ETAPriceChart.vue
  43. 137 0
      src/views/report_manage/reportV2/normalReport/components/ETASandBox.vue
  44. 123 0
      src/views/report_manage/reportV2/normalReport/components/ETASheet.vue
  45. 121 0
      src/views/report_manage/reportV2/normalReport/components/ImportETAChart.vue
  46. 138 0
      src/views/report_manage/reportV2/normalReport/components/SemanticAnalysis.vue
  47. 225 0
      src/views/report_manage/reportV2/normalReport/components/StatisticAnalysis.vue
  48. 165 0
      src/views/report_manage/reportV2/normalReport/components/importMyChart.vue
  49. 104 0
      src/views/report_manage/reportV2/normalReport/components/insertContent.vue
  50. 711 0
      src/views/report_manage/reportV2/normalReport/editReport.vue
  51. 115 0
      src/views/report_manage/reportV2/normalReport/mixins/messagePush.js
  52. 368 0
      src/views/report_manage/reportV2/normalReport/mixins/reportMixin.js
  53. 229 0
      src/views/report_manage/reportV2/normalReport/reportdtl.vue
  54. 316 0
      src/views/report_manage/reportV2/smartReport/components/BaseInfo.vue
  55. 20 0
      src/views/report_manage/reportV2/smartReport/components/ChartComp.vue
  56. 106 0
      src/views/report_manage/reportV2/smartReport/components/ETAChart.vue
  57. 180 0
      src/views/report_manage/reportV2/smartReport/components/ETAPriceChart.vue
  58. 172 0
      src/views/report_manage/reportV2/smartReport/components/ETASandBox.vue
  59. 173 0
      src/views/report_manage/reportV2/smartReport/components/ETASheet.vue
  60. 16 0
      src/views/report_manage/reportV2/smartReport/components/ImgComp.vue
  61. 141 0
      src/views/report_manage/reportV2/smartReport/components/ImgEdit.vue
  62. 223 0
      src/views/report_manage/reportV2/smartReport/components/ImgSource.vue
  63. 166 0
      src/views/report_manage/reportV2/smartReport/components/ImportETAChart.vue
  64. 171 0
      src/views/report_manage/reportV2/smartReport/components/ImportMyETAChart.vue
  65. 172 0
      src/views/report_manage/reportV2/smartReport/components/SemanticAnalysis.vue
  66. 48 0
      src/views/report_manage/reportV2/smartReport/components/SheetComp.vue
  67. 258 0
      src/views/report_manage/reportV2/smartReport/components/StatisticAnalysis.vue
  68. 20 0
      src/views/report_manage/reportV2/smartReport/components/TextComp.vue
  69. 168 0
      src/views/report_manage/reportV2/smartReport/components/TextEdit.vue
  70. 1857 0
      src/views/report_manage/reportV2/smartReport/editReport.vue
  71. 392 0
      src/views/report_manage/reportV2/smartReport/reportDetail.vue
  72. 6 2
      src/views/smartReport/editReport.vue
  73. 1 1
      src/views/system_manage/etaBaseConfig.vue

+ 429 - 0
src/api/modules/reportV2.js

@@ -0,0 +1,429 @@
+//研报改版  一些接口复用以前的 一些新增的 都捞过来放一块
+import http from "@/api/http.js"
+
+
+/* 新增的接口 */
+export const reportV2Interface = {
+
+  /**
+   * 获取有权限的列表 
+   * @param {
+   *  CurrentIndex PageSize KeyWord ClassifyIdFirst ClassifyIdSecond ClassifyIdThird
+   * } params 
+   * @returns 
+   */
+  getAuthReportList: params => {
+    return http.get('/report/list/authorized',params)
+  },
+
+  /**
+   * 报告基础信息
+   * @param {*ReportId} params 
+   * @returns 
+   */
+  getRportBase: params => {
+    return http.get('/report/detail/base',params)
+  },
+
+  /**
+   * 修改章节基础信息
+   * @param {*} params 
+   * @returns 
+   */
+  editChapterBase: params => {
+    return http.post('/report/chapter/base_info/edit',params)
+  },
+
+  /**
+   * 章节拖动排序
+   * @param {*ReportChapterId PrevReportChapterId NextReportChapterId} params 
+   * @returns 
+   */
+  moveChapter: params => {
+    return http.post('/report/chapter/move',params)
+  },
+
+	/**
+	 * 删除章节
+	 * @param {*ReportChapterId} params 
+	 * @returns 
+	 */
+	removeChapter: params => {
+		return http.post('/report/chapter/del',params)
+	},
+
+	/**
+	 * 添加章节
+	 * 
+	 * @param {* Title  ReportId PermissionIdList AdminIdList} params 
+	 * @returns 
+	 */
+	addChapter: params => {
+		return http.post('/report/chapter/add',params)
+	},
+
+	/**
+	 * 上传章节音频
+	 * @param {*ReportChapterId File} params 
+	 * @returns 
+	 */
+	uploadChpterAudio: params => {
+		return http.post('/report/chapter/voice/upload',params)
+	},
+
+	/**
+	 * 校验所有章节是否发布
+	 * @param {*ReportId} params 
+	 * @returns 
+	 */
+	checkChaterPublishState: params => {
+		return http.get('/report/chapter/un_publish/list',params)
+	},
+
+	/**
+	 * 设置版图
+	 * @param {*ReportId HeadImg HeadResourceId EndImg EndResourceId CanvasColor} params 
+	 * @returns 
+	 */
+	setReportLayoutImg: params => {
+		return http.post('/report/layout_img/edit',params)
+	},
+
+	/**
+	 * 获取分类关联的品种列表
+	 * @param {*ClassifyId} params 
+	 * @returns 
+	 */
+	getClassifyPermissionList: params => {
+		return	http.get('/classify/permission/list',params)
+	},
+
+	/**
+	 * 保存章节标题 
+	 * @param {*ReportChapterId Title} params 
+	 * @returns 
+	 */
+	saveChapterTitle: params => {
+		return http.post('/report/chapter/title/edit',params)
+	}
+
+}
+
+
+const reportlist = params => { return http.get('/report/list',params); };  //获取报告列表
+
+const classifylist = params => { return http.get('/classify/list',params); };  //获取分类列表
+
+ const reportpublish = params => { return http.post('/report/publish',params); };  //批量发布报告
+ const reportpublishcancle = params => { return http.post('/report/publish/cancle',params); };  //取消发布报告
+ const voiceupload = params => { return http.post('/voice/upload',params); };  //上传音频
+ const resourceVoiceupload = params => { return http.post('/resource/voice/upload',params); };  //上传音频
+ const reportadd = params => { return http.post('/report/add',params); };  //新增报告
+ const reportedit = params => { return http.post('/report/edit',params); };  //编辑报告
+ const reportdelete = params => { return http.post('/report/delete',params); };  //删除报告
+ const reportdetail = params => { return http.get('/report/detail',params); };  //获取报告详情
+ const classifyIdDetail = params => { return http.get('/report/classifyIdDetail',params); };  //通过二级分类id获取报告详情
+ const sendTemplateMsg = params => { return http.post('/report/sendTemplateMsg',params); };  //推送消息
+ const reportauthor = params => { return http.get('/report/author',params); };  //获取作者
+ const getDraft = params => { return http.get('/report/getDraft',params); };  //获取草稿
+ const autosave = params => { return http.post('/report/saveReportContent',params); };  //保存
+ const reportSetPrepublish=params=>{return http.post('/report/pre_publish',params);};//报告设置定时发布
+
+ const classifyparent = params => { return http.get('/classify/parent',params); };  //获取父级分类
+ const classifyadd = params => { return http.post('/classify/add',params); };  //新增分类
+ const classifydelete = params => { return http.post('/classify/delete',params); };  //删除分类
+ const classifyedit = params => { return http.post('/classify/edit',params); };  //编辑分类
+ const checkDeleteClassify = params => { return http.get('/classify/checkDeleteClassify',params); };  //检测分类
+ const classifyTelList = params=>{return http.get('/classify/tel_list',params)};//电话会分类
+
+
+
+ /* 客群消息推送接口 */
+const messagePushPost= params => {
+	return http.post('/report/ths/sendTemplateMsg',params)
+}
+
+// 晨周报章节类型列表
+const dayWeekReportChapterList=params=>{
+	return http.get('/report/getDayWeekReportChapterTypeList',params)
+}
+
+//新增晨周报
+const addDayWeekReport=params=>{
+	return http.post('/report/addDayWeekReport',params)
+}
+
+//编辑晨周报
+const editDayWeekReport=params=>{
+	return http.post('/report/editDayWeekReport',params)
+}
+
+// 晨周报章节列表
+const dayWeekChapterList=params=>{
+	return http.get('/report/getReportChapterList',params)
+}
+
+//章节标签列表
+const chapterTrendTagList=()=>{
+	return http.get('/report/getChapterTrendTag',{})
+}
+
+//编辑章节标签
+const editChapterTrendTag=params=>{
+	return http.post('/report/editChapterTrendTag',params)
+}
+
+//晨报周报章节详情
+const chapterDetail=params=>{
+	return http.get('/report/getDayWeekChapter',params)
+}
+
+//晨报数据指标列表
+const dayTicketList=params=>{
+	return http.get('/report/getDayReportTickerList',params)
+}
+
+//保存晨报周报章节报告
+const saveChapterReport=params=>{
+	return http.post('/report/editDayWeekChapter',params)
+}
+
+//获取晨报/周报上一篇内容
+const getChapterReportBefore=params=>{
+	return http.get('/report/getLastDayWeekReportChapter',params)
+}
+
+//判断晨报周报当前章节是否为最后一篇发布的
+const getChapterReportIsLast=params=>{
+	return http.get('/report/isLastDayWeekReportChapter',params)
+}
+
+//发布晨报周报章节
+const publishChapterReport=params=>{
+	return http.post('/report/publishDayWeekReportChapter',params)
+}
+
+//发布晨报周报
+const publishDayOrWeekReport=params=>{
+	return http.post('/report/publishDayWeekReport',params)
+}
+
+//晨报周报更新暂停的时间
+const dayWeekPauseTime=params=>{
+	return http.get('/report/getDayWeekReportPauseTime',{})
+}
+
+//晨报周报设置更新规则
+const dayWeekUpdateRule=params=>{
+	return http.post('/report/setDayWeekReportUpdateRule',params)
+}
+
+// 周报校验音频
+const weekReportValidAudio=params=>{
+	return http.get('/report/CheckDayWeekReportChapterVideo',params)
+}
+
+
+const chapterQRCodeImg=params=>{
+	return http.post('/report/getSunCode',params)
+}
+
+/* 推送客户群设置 */
+// 获取待推送报告类型
+/**
+ * @returns 
+ * List - 报告类型列表
+ * 
+ */
+const getBeingPushedReportType=()=>{
+	return http.get('/yb/ths_send/report_type',{})
+}
+// 获取待推送列表
+/**
+ * 
+ * @param {
+ * Title 推送标题
+ * ReportType 内容类型
+ * CreateTimeStart 创建开始日期
+ * CreateTimeEnd 创建结束日期
+ * PushTimeStart 推送开始日期
+ * PushTimeEnd 推送结束日期
+ * PageSize 每页条数
+ * CurrentIndex 当前页数
+ * } params 
+ * @returns 
+ */
+const getBeingPushedReportList=params=>{
+	return http.get('/yb/ths_send/list',params)
+}
+// 设置推送时间
+/** 
+ * @param {
+ * SendId 序号
+ * PushTime 新的推送时间
+ * } params 
+ * @returns 
+ */
+const setPushingTime=params=>{
+	return http.post('/yb/ths_send/modify_push_time',params)
+}
+
+//研报标记状态
+/**
+ * 
+ * @param {
+ * Status 编辑状态
+ * ReportId 报告ID
+ * } params
+ * @returns 
+ */
+const markReport = params =>{
+  return http.post('/report/mark',params)
+}
+
+// 获取章节类型列表
+/**
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.PageSize Integer-每页条数
+ * @param params.CurrentIndex Integer-当前页数
+ * @returns 章节类型列表
+ */
+const getchapterTypeList=params=>{
+ return http.get('/report/chapter_type/list',params)
+}
+
+// 新增章节类型
+/**
+ * @param params.ReportChapterTypeName String-章节名称
+ * @param params.Sort Integer-排序
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.SelectedImage String-选中的icon
+ * @param params.UnselectedImage String-未选中的icon
+ * @param params.WordsImage String-带字的icon
+ * @param params.EditImgUrl String-后台-章节列表封面图
+ * @param params.IsShow Enum-小程序端是否展示:0-隐藏;1-显示
+ */
+const addChapterType=params=>{
+	return http.post('/report/chapter_type/add',params)
+ }
+
+ // 编辑章节类型
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @param params.ReportChapterTypeName String-章节名称
+ * @param params.Sort Integer-排序
+ * @param params.ReportType Enum-报告类型:day-晨报;week-周报
+ * @param params.SelectedImage String-选中的icon
+ * @param params.UnselectedImage String-未选中的icon
+ * @param params.WordsImage String-带字的icon
+ * @param params.EditImgUrl String-后台-章节列表封面图
+ * @param params.IsShow Enum-小程序端是否展示:0-隐藏;1-显示
+ */
+const editChapterType=params=>{
+	return http.post('/report/chapter_type/edit',params)
+ }
+ 
+// 删除章节
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ */
+const deleteChapterType=params=>{
+	return http.post('/report/chapter_type/del',params)
+}
+
+// 获取章节类型的权限列表
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @returns 权限列表
+ */
+const getchapterTPermissionList=params=>{
+	return http.get('/report/chapter_type/permission_list',params)
+ }
+
+// 设置章节类型的权限
+/**
+ * @param params.ReportChapterTypeId Integer-章节ID
+ * @param params.ChartPermissionIdList Array<Integer>-权限IDs
+ */
+const setchapterTPermission=params=>{
+	return http.post('/report/chapter_type/auth_setting',params)
+}
+
+//章节启用\禁用
+const setChapterEnable=params=>{
+	return http.post('/report/chapter_type/enabled/set',params)
+}
+
+//章节拖动排序
+const setChapterSort=params=>{
+	return http.post('/report/chapter_type/move',params)
+}
+
+// 同时推送客群和模板消息
+const reportMessageSend=params=>{
+	return http.post('/report/sendMsg',params)
+}
+
+// 中英文研报、智能研报转pdf和长图
+const report2PdfImg=params=>{
+	return http.post('/smart_report/get_pdf_url',params)
+}
+
+
+
+export {
+	reportlist,
+	reportpublish,
+	reportpublishcancle,
+	voiceupload,
+	resourceVoiceupload,
+	reportadd,
+	reportedit,
+	reportdelete,
+	reportdetail,
+	classifyIdDetail,
+	sendTemplateMsg,
+	reportauthor,
+	getDraft,
+	autosave,
+	reportSetPrepublish,
+	classifylist,
+	classifyparent,
+	classifyadd,
+	classifydelete,
+	classifyedit,
+	checkDeleteClassify,
+	messagePushPost,
+	dayWeekReportChapterList,
+	addDayWeekReport,
+	dayWeekChapterList,
+	chapterTrendTagList,
+	editChapterTrendTag,
+	editDayWeekReport,
+	chapterDetail,
+	dayTicketList,
+	saveChapterReport,
+	getChapterReportBefore,
+	getChapterReportIsLast,
+	publishChapterReport,
+	publishDayOrWeekReport,
+	dayWeekPauseTime,
+	dayWeekUpdateRule,
+	chapterQRCodeImg,
+  classifyTelList,
+	getBeingPushedReportType,
+	getBeingPushedReportList,
+	setPushingTime,
+  markReport,
+	getchapterTypeList,
+	addChapterType,
+	editChapterType,
+	deleteChapterType,
+	getchapterTPermissionList,
+	setchapterTPermission,
+	reportMessageSend,
+	weekReportValidAudio,
+	setChapterEnable,
+	setChapterSort,
+	report2PdfImg
+}

二进制
src/assets/img/data_m/move_ico.png


文件差异内容过多而无法显示
+ 1 - 0
src/assets/img/icons/baseinfo_ico.svg


+ 4 - 0
src/assets/img/icons/preview_ico.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.93819 5.46945V3.40708C2.93819 3.14802 3.14818 2.93806 3.40728 2.93806H5.46994C5.72904 2.93806 5.93903 2.72809 5.93903 2.46903C5.93903 2.20996 5.72904 2 5.46994 2H2.46909C2.20999 2 2 2.20996 2 2.46903V5.46945C2 5.72852 2.20999 5.93848 2.46909 5.93848C2.7265 5.93848 2.93819 5.72852 2.93819 5.46945ZM10.5334 2.93806H12.5927C12.8518 2.93806 13.0618 3.14802 13.0618 3.40708V5.46945C13.0618 5.72852 13.2718 5.93848 13.5309 5.93848C13.79 5.93848 14 5.72852 14 5.46945V2.46903C14 2.20996 13.79 2 13.5309 2H10.5334C10.2743 2 10.0644 2.20996 10.0644 2.46903C10.0644 2.72809 10.276 2.93806 10.5334 2.93806ZM5.46825 13.0603H3.40728C3.14818 13.0603 2.93819 12.8503 2.93819 12.5912V10.5322C2.93819 10.2732 2.7282 10.0632 2.46909 10.0632C2.20999 10.0632 2 10.2732 2 10.5322V13.5293C2 13.7883 2.20999 13.9983 2.46909 13.9983H5.46825C5.72735 13.9983 5.93734 13.7883 5.93734 13.5293C5.93734 13.2702 5.72735 13.0603 5.46825 13.0603ZM13.0618 10.5322V12.5929C13.0618 12.852 12.8518 13.0619 12.5927 13.0619H10.5334C10.2743 13.0619 10.0644 13.2719 10.0644 13.531C10.0644 13.79 10.2743 14 10.5334 14H13.5309C13.79 14 14 13.79 14 13.531V10.5339C14 10.2749 13.79 10.0649 13.5309 10.0649C13.2718 10.0632 13.0618 10.2732 13.0618 10.5322Z" fill="#0052D9"/>
+<path d="M8 5.59888C9.5061 5.59888 10.8019 6.58141 11.4093 8H12C11.3605 6.2408 9.81237 5 8 5C6.18931 5 4.64114 6.2408 4 8H4.59066C5.19815 6.58328 6.49558 5.59888 8 5.59888ZM8 10.4011C6.4939 10.4011 5.19815 9.41859 4.59066 8H4C4.64114 9.7592 6.18931 11 8 11C9.81069 11 11.3605 9.75733 12 8H11.4093C10.8035 9.41859 9.5061 10.4011 8 10.4011ZM6.56121 8C6.56121 8.88334 7.20572 9.60012 8 9.60012C8.79428 9.60012 9.43879 8.88334 9.43879 8C9.43879 7.11666 8.79428 6.39988 8 6.39988C7.20572 6.39988 6.56121 7.11666 6.56121 8ZM8.90029 8C8.90029 8.55209 8.49811 9.00125 8 9.00125C7.50358 9.00125 7.10139 8.55396 7.10139 8C7.10139 7.44791 7.50358 6.99875 8 6.99875C8.49811 7.00062 8.90029 7.44791 8.90029 8Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/publish_ico.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.74769 17.4324C4.19134 17.4317 3.658 17.2233 3.2646 16.8528C2.8712 16.4823 2.64985 15.98 2.64908 15.4561C2.64908 14.3664 3.59054 13.4798 4.74769 13.4798H10.1965C10.2716 13.0217 10.4212 12.5773 10.6401 12.1622H7.85772L9.28769 8.59764C9.3011 8.58447 9.31451 8.55921 9.3285 8.53451C9.36916 8.46974 9.39556 8.39792 9.40613 8.32334C9.41669 8.24876 9.4112 8.17294 9.38999 8.1004C9.36877 8.02785 9.33226 7.96008 9.28264 7.90111C9.23301 7.84213 9.17129 7.79318 9.10115 7.75715C8.63788 7.50327 8.25371 7.13905 7.98725 6.70107C7.72079 6.26309 7.58142 5.76679 7.58315 5.26202C7.58315 3.68204 8.94142 2.40346 10.6063 2.40346C12.2835 2.40346 13.6411 3.69357 13.6411 5.27464C13.6405 5.77884 13.5002 6.27415 13.2342 6.71171C12.9682 7.14927 12.5857 7.51396 12.1243 7.76978C12.0975 7.78185 12.0707 7.79448 12.0573 7.81918C11.8183 7.99486 11.7512 8.30778 11.9115 8.55921C11.9244 8.58447 11.9506 8.60862 11.964 8.63388L12.5983 10.2122C12.9629 10.0179 13.3529 9.86893 13.7583 9.76917L13.2162 8.43405C13.6411 8.12561 13.9983 7.74225 14.2678 7.30534C14.6541 6.68603 14.8562 5.98024 14.8531 5.26202C14.8564 4.73596 14.7487 4.21452 14.5361 3.72802C14.3236 3.24153 14.0104 2.79968 13.6149 2.42816C12.8157 1.66343 11.7512 1.25005 10.6063 1.25005C10.0467 1.24751 9.49211 1.35043 8.97532 1.55276C8.45853 1.75508 7.98994 2.05273 7.59714 2.42816C6.80253 3.18152 6.3573 4.20072 6.35896 5.26257C6.35896 5.97734 6.55891 6.69212 6.94424 7.30588C7.22405 7.74507 7.58315 8.13375 8.00987 8.44722L6.50819 12.1622H4.74769C4.28837 12.1622 3.83354 12.2474 3.40918 12.4129C2.98482 12.5785 2.59924 12.8211 2.27445 13.127C1.94966 13.4328 1.69202 13.7959 1.51625 14.1956C1.34047 14.5952 1.25 15.0235 1.25 15.4561C1.25 15.8887 1.34047 16.317 1.51625 16.7166C1.69202 17.1163 1.94966 17.4794 2.27445 17.7852C2.59924 18.0911 2.98482 18.3337 3.40918 18.4993C3.83354 18.6648 4.28837 18.75 4.74769 18.75H15C13.7211 18.7511 12.4932 18.2778 11.5822 17.4324H4.74769Z" fill="#0052D9"/>
+<path d="M14.3747 10C12.0124 10 10 11.6502 10 13.7503C10 15.7751 11.9252 17.5 14.3747 17.5C16.8248 17.5 18.75 15.8504 18.75 13.7503C18.75 11.6502 16.7376 10 14.3747 10ZM16.3871 13.3004H14.9002V16.225H13.9376V13.3004H12.4501L14.3747 11.2003L16.3871 13.3004Z" fill="#0052D9"/>
+</svg>

+ 5 - 0
src/assets/img/icons/save_ico.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.7723 1.1297C15.0455 1.3226 15.0776 1.6633 14.8429 1.88887L10.1474 6.41202C10.0917 6.4657 10.0237 6.50979 9.94727 6.54177C9.87088 6.57375 9.78761 6.593 9.70221 6.59842C9.61681 6.60383 9.53095 6.59531 9.44954 6.57334C9.36813 6.55137 9.29276 6.51637 9.22773 6.47036C9.1627 6.42434 9.10929 6.3682 9.07054 6.30514C9.0318 6.24209 9.00848 6.17335 9.00192 6.10285C8.99535 6.03236 9.00568 5.96148 9.0323 5.89428C9.05891 5.82708 9.10131 5.76486 9.15705 5.71118L13.8535 1.18804C13.9092 1.13434 13.9772 1.09024 14.0536 1.05825C14.13 1.02625 14.2133 1.007 14.2987 1.00158C14.3841 0.996165 14.47 1.00469 14.5514 1.02667C14.6328 1.04866 14.7082 1.08366 14.7732 1.1297H14.7723Z" fill="#0052D9"/>
+<path d="M3.01946 1.00082C2.48401 1.00082 1.97047 1.21872 1.59177 1.60661C1.21307 1.9945 1.00021 2.52063 1 3.0693V12.9299C0.999896 13.2017 1.05205 13.4709 1.15349 13.722C1.25493 13.9732 1.40367 14.2014 1.59121 14.3936C1.77874 14.5859 2.0014 14.7384 2.24646 14.8424C2.49153 14.9464 2.7542 15 3.01946 15H11.9789C12.2443 15.0002 12.5071 14.9468 12.7522 14.843C12.9974 14.7391 13.2203 14.5867 13.4079 14.3945C13.5956 14.2023 13.7445 13.9741 13.8461 13.723C13.9477 13.4718 14 13.2026 14 12.9307V5.63025C14 5.4805 13.9419 5.33689 13.8386 5.23101C13.7353 5.12512 13.5951 5.06563 13.449 5.06563C13.3028 5.06563 13.1627 5.12512 13.0594 5.23101C12.956 5.33689 12.898 5.4805 12.898 5.63025V12.9307C12.898 13.4501 12.4866 13.8708 11.9797 13.8708H3.02026C2.77687 13.8708 2.54343 13.7718 2.37126 13.5955C2.19908 13.4192 2.10224 13.1801 2.10203 12.9307V3.07012C2.10203 2.54994 2.51261 2.12923 3.01946 2.12923H11.1355C11.2817 2.12923 11.4218 2.06974 11.5251 1.96386C11.6285 1.85797 11.6865 1.71436 11.6865 1.56461C11.6865 1.41487 11.6285 1.27126 11.5251 1.16537C11.4218 1.05949 11.2817 1 11.1355 1H3.01946V1.00082Z" fill="#0052D9"/>
+<path d="M3.52554 5C3.38626 5 3.25268 5.05824 3.1542 5.16191C3.05571 5.26558 3.00038 5.40619 3.00038 5.5528C3.00038 5.69941 3.05571 5.84002 3.1542 5.94369C3.25268 6.04736 3.38626 6.1056 3.52554 6.1056H6.25562C6.3949 6.1056 6.52848 6.04736 6.62697 5.94369C6.72545 5.84002 6.78078 5.69941 6.78078 5.5528C6.78078 5.40619 6.72545 5.26558 6.62697 5.16191C6.52848 5.05824 6.3949 5 6.25562 5H3.52554ZM3 8.4996C3 8.19466 3.23509 7.9472 3.52554 7.9472H6.88506C7.02434 7.9472 7.15791 8.00544 7.2564 8.10911C7.35489 8.21278 7.41022 8.35339 7.41022 8.5C7.41022 8.64661 7.35489 8.78722 7.2564 8.89089C7.15791 8.99456 7.02434 9.0528 6.88506 9.0528H3.52554C3.4565 9.0529 3.38811 9.03867 3.32431 9.0109C3.2605 8.98314 3.20253 8.9424 3.15371 8.89101C3.10488 8.83962 3.06618 8.77859 3.0398 8.71142C3.01343 8.64426 2.9999 8.57228 3 8.4996ZM3.52554 10.8944C3.38626 10.8944 3.25268 10.9526 3.1542 11.0563C3.05571 11.16 3.00038 11.3006 3.00038 11.4472C3.00038 11.5938 3.05571 11.7344 3.1542 11.8381C3.25268 11.9418 3.38626 12 3.52554 12H9.47484C9.61412 12 9.7477 11.9418 9.84618 11.8381C9.94467 11.7344 10 11.5938 10 11.4472C10 11.3006 9.94467 11.16 9.84618 11.0563C9.7477 10.9526 9.61412 10.8944 9.47484 10.8944H3.52554Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/submit_ico.svg

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9 3V5H10V2.5C10 2.22386 9.77614 2 9.5 2H1.5C1.22386 2 1 2.22386 1 2.5V13.5C1 13.7761 1.22386 14 1.5 14H9.5C9.77614 14 10 13.7761 10 13.5V11H9V13H2V3H9Z" fill="#0052D9"/>
+<path d="M11.2316 5.25423L13.4774 7.50001L5.99994 7.49999L5.99994 8.49999L13.4774 8.50001L11.2316 10.7458L11.9387 11.4529L15.038 8.35356C15.2333 8.1583 15.2333 7.84172 15.038 7.64646L11.9387 4.54712L11.2316 5.25423Z" fill="#0052D9"/>
+</svg>

+ 4 - 0
src/assets/img/icons/timing_ico.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.375 5V10.4862L12.5003 13.75L13.3842 12.8661L10.625 9.96839V5H9.375Z" fill="#0052D9"/>
+<path d="M18.75 10C18.75 14.8325 14.8325 18.75 10 18.75C5.16751 18.75 1.25 14.8325 1.25 10C1.25 5.16751 5.16751 1.25 10 1.25C14.8325 1.25 18.75 5.16751 18.75 10ZM17.5 10C17.5 5.85786 14.1421 2.5 10 2.5C5.85786 2.5 2.5 5.85786 2.5 10C2.5 14.1421 5.85786 17.5 10 17.5C14.1421 17.5 17.5 14.1421 17.5 10Z" fill="#0052D9"/>
+</svg>

+ 14 - 0
src/assets/img/icons/wx_round.svg

@@ -0,0 +1,14 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_6030_16278)">
+<path d="M6.23633 7.52735C6.23633 7.70094 6.30529 7.86743 6.42804 7.99018C6.55079 8.11293 6.71728 8.18189 6.89087 8.18189C7.06447 8.18189 7.23096 8.11293 7.35371 7.99018C7.47646 7.86743 7.54542 7.70094 7.54542 7.52735C7.54542 7.35375 7.47646 7.18727 7.35371 7.06451C7.23096 6.94176 7.06447 6.8728 6.89087 6.8728C6.71728 6.8728 6.55079 6.94176 6.42804 7.06451C6.30529 7.18727 6.23633 7.35375 6.23633 7.52735Z" fill="#50B674"/>
+<path d="M9.16357 7.50904C9.16357 7.68263 9.23253 7.84912 9.35529 7.97187C9.47804 8.09462 9.64452 8.16358 9.81812 8.16358C9.99172 8.16358 10.1582 8.09462 10.281 7.97187C10.4037 7.84912 10.4727 7.68263 10.4727 7.50904C10.4727 7.33544 10.4037 7.16896 10.281 7.0462C10.1582 6.92345 9.99172 6.85449 9.81812 6.85449C9.64452 6.85449 9.47804 6.92345 9.35529 7.0462C9.23253 7.16896 9.16357 7.33544 9.16357 7.50904Z" fill="#50B674"/>
+<path d="M10.7998 10.4365C10.7998 10.557 10.8477 10.6726 10.9329 10.7579C11.0182 10.8431 11.1338 10.891 11.2543 10.891C11.3749 10.891 11.4905 10.8431 11.5758 10.7579C11.661 10.6726 11.7089 10.557 11.7089 10.4365C11.7089 10.3159 11.661 10.2003 11.5758 10.1151C11.4905 10.0298 11.3749 9.98193 11.2543 9.98193C11.1338 9.98193 11.0182 10.0298 10.9329 10.1151C10.8477 10.2003 10.7998 10.3159 10.7998 10.4365Z" fill="#50B674"/>
+<path d="M13.1089 10.4726C13.1089 10.5932 13.1568 10.7088 13.242 10.794C13.3273 10.8793 13.4429 10.9272 13.5634 10.9272C13.684 10.9272 13.7996 10.8793 13.8848 10.794C13.9701 10.7088 14.018 10.5932 14.018 10.4726C14.018 10.3521 13.9701 10.2364 13.8848 10.1512C13.7996 10.066 13.684 10.0181 13.5634 10.0181C13.4429 10.0181 13.3273 10.066 13.242 10.1512C13.1568 10.2364 13.1089 10.3521 13.1089 10.4726Z" fill="#50B674"/>
+<path d="M10 0C4.47273 0 0 4.47273 0 10C0 15.5273 4.47273 20 10 20C15.5273 20 20 15.5273 20 10C20 4.47273 15.5273 0 10 0ZM8.29091 12.3091C7.76364 12.3091 7.34545 12.2 6.81818 12.0909L5.34545 12.8182L5.76364 11.5636C4.70909 10.8364 4.09091 9.89091 4.09091 8.72727C4.09091 6.72727 5.98182 5.16364 8.29091 5.16364C10.3455 5.16364 12.1636 6.41818 12.5273 8.10909C12.4 8.09091 12.2545 8.09091 12.1273 8.09091C10.1273 8.09091 8.56364 9.58182 8.56364 11.4182C8.56364 11.7273 8.61818 12.0182 8.69091 12.2909C8.54545 12.2909 8.41818 12.3091 8.29091 12.3091ZM14.4364 13.7818L14.7455 14.8364L13.6 14.2C13.1818 14.3091 12.7636 14.4182 12.3455 14.4182C10.3455 14.4182 8.78182 13.0545 8.78182 11.3818C8.78182 9.70909 10.3455 8.34545 12.3455 8.34545C14.2364 8.34545 15.9091 9.70909 15.9091 11.3818C15.9091 12.3091 15.2909 13.1455 14.4364 13.7818Z" fill="#50B674"/>
+</g>
+<defs>
+<clipPath id="clip0_6030_16278">
+<rect width="20" height="20" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 16 - 0
src/lang/commonLang.js

@@ -208,6 +208,10 @@ export default {
       en: "Entry Successful",
       zh: "录入成功",
     },
+    submit_msg: {
+      en: "Submit Successful",
+      zh: "提交成功",
+    },
     delete_info_msg: {
       en: "Are you sure you want to permanently delete this file?",
       zh: "删除后不可恢复,是否确认删除?",
@@ -402,6 +406,10 @@ export default {
       en: 'No Charts',
       zh: '暂无图表'
     },
+    no_cont_msg: {
+      en: 'No Content',
+      zh: '暂无内容'
+    },
     exp_excel: {
       en: ' Export Excel',
       zh: '导出excel',
@@ -449,6 +457,14 @@ export default {
     fixed:{
       en:'fixed',
       zh:'固定'
+    },  
+    yes_text: {
+      en: 'Yes',
+      zh: '是'
+    },
+    no_text: {
+      en: 'No',
+      zh: '否'
     },
   },
   Edb,

+ 4 - 4
src/lang/modules/ReportManagement/CategoryList.js

@@ -104,8 +104,8 @@ export const CategoryListEn = {
     section_settings: "Section Settings",
     add_section: "Add Section",
     edit_section: "Edit Section",
-    section_name: "Section Name",
-    section_name_hint: "Enter Section Name",
+    section_name: "Section Type",
+    section_name_hint: "Enter Section Type",
     parent_category: "Parent Category",
     parent_none: "none",
     related_variety: "Related Variety",
@@ -225,8 +225,8 @@ export const CategoryListZh = {
     section_settings: "章节设置",
     add_section: "添加章节",
     edit_section: "编辑章节",
-    section_name: "章节名称",
-    section_name_hint: "请输入章节名称",
+    section_name: "章节类型",
+    section_name_hint: "请输入章节类型",
     parent_category: "上级分类",
     parent_none:'无',
     related_variety: "关联品种",

+ 112 - 8
src/lang/modules/ReportManagement/ReportList.js

@@ -24,8 +24,8 @@ export const ReportListEn = {
   information_title: "Basic information",
   new_report_radio: "New report",
   inherit_report_radio: "Inherit report",
-  please_select_category: "Please select a category",
-  input_title_please: "Please input title",
+  please_select_category: "Please select a Report category",
+  input_title_please: "Please input Report title",
   please_input_abstract: "Please input abstract",
   please_select_author: "Please select the author",
   please_select_frequency: "Please select the frequency",
@@ -36,10 +36,12 @@ export const ReportListEn = {
   no_reports_msg: "There are currently no reports for this category",
   chart_insertion_progress: "Batch chart insertion in progress",
   last_save_time: "Last save time",
+  click_clear_btn: "Clear Content",
   click_refresh_btn: "Rfrsh",
   preview_btn: "Preview",
   save_draft_btn: "Draft",
   scheduled_publish_btn: "Schedule",
+  submit_chapter_btn:'Submit Section',
   publish_btn: "Publish",
   submission_btn: "Submission",
   new_method_btn: "New method",
@@ -57,7 +59,7 @@ export const ReportListEn = {
   intercommodity_analysis_radio: "Cross-Comm",
   just_mine_radio: "Just Mine",
   insert_sandbox_tabs: "Insert Sandbox",
-  no_reports_msg: "Sandbox Name/Commodity",
+  no_sandbox_msg: "Sandbox Name/Commodity",
   insert_table_tabs: "Insert Table",
   table_name_tabs: "Table Name",
   bulk_insertion_tabs: "My gallery batch insert",
@@ -87,7 +89,7 @@ export const ReportListEn = {
   img_uplaod_title: "Image Upload",
   click_img_upload: "Click to Upload Image",
   select_img_card: "Select Image",
-  img_name_ipt: "Please input image name",
+  img_name_ipt: "Please input layout name",
   select_img_type: "Please select an image type",
   page_header_op: "Page Header",
   page_trailer_op: "Page Trailer",
@@ -105,6 +107,7 @@ export const ReportListEn = {
   recorded_audio: "The recording has been uploaded.",
   not_recorded_audio: "The recording has not been uploaded.",
   weChat_share: "WeChat share",
+  copy_share_link:'Copy Link',
   set_tags_title: "Set tags",
   select_ipt_pld: "Enter or select",
   input_email_subject: "Please input email subject",
@@ -120,6 +123,55 @@ export const ReportListEn = {
   upload_img_error_msg: "Some images have not finished uploading, please wait.",
   all_update_publish_msg: "This report's varieties have all been updated. Clicking 'Publish' will also release the weekly report. Are you sure you want to publish both simultaneously?",
   is_publish_report_msg: "You have not uploaded an audio recording file yet. Are you sure you want to publish the report?",
+
+
+
+  tab_public:'Public Research Report',
+  tab_share:'Shared Research Report',
+  tab_mine:'My Research Report',
+  /* 添加报告弹窗 */
+  label_add_way:'Addition Method',
+  label_report_tit:'Report Title',
+  choose_inherit_report: 'Select Inherited Report',
+  label_report_classify:'Report Category',
+  label_relation_variety: 'Associated Varieties',
+  label_report_abstract:'Report Abstract',
+  label_report_author:'Report Author',
+  label_frequency:'Frequency',
+  label_createtime:'CreateTime',
+  label_coop:'Collaboration Method',
+  choose_cooper:'Select Collaborators',
+  coop_own: 'Individual',
+  coop_more: 'Collaborative (Multiple People)',
+  label_report_layout:'Report Layout',
+  layout_default:'Standard Layout',
+  layout_smart:'Intelligent Layout',
+  label_public:'Public Release',
+
+  tit_report_chap:'Research Report Section',
+  btn_add_chap: 'Add Section',
+  /* 添加章节弹窗 */
+  label_chap_name:'Section Name',
+  label_chap_editor:'Editor',
+  tit_choose_inher:'Select Report',
+  ph_report_tit: 'Please input the report title',
+  check_report_len: 'Only one report can be selected',
+  ph_select_user: 'Please select user',
+  del_chapter_msg: 'Are you sure you want to delete this section?',
+  report_empty_msg:'Please input the report content',
+  img_set_btn: 'Layout Settings',
+  no_chapter_msg:'No section information available',
+  chapter_nosubmit_msg:'{name},the content of the section has not been submitted',
+
+  choose_head_img:'Select Header',
+  choose_end_img:'Select Footer',
+  canvas_set:'Canvas Settings',
+  choose_layout_img:'Select Layout',
+  variety_tip:`If a section is associated with a variety, then the reading permissions for the section are controlled by the permissions of the associated variety;<br>
+  If a section is not associated with any variety, then the reading permissions for the section are controlled by the permissions of the category-associated varieties;`,
+  chapter_has_submit:'Submitted',
+  chapter_no_submit:'Not Submitted',
+  choose_msg: 'Choose'
 };
 
 /* 中文 */
@@ -144,8 +196,8 @@ export const ReportListZh = {
   information_title: "基础信息",
   new_report_radio: "新增报告",
   inherit_report_radio: "继承报告",
-  please_select_category: "请选择分类",
-  input_title_please: "请输入标题",
+  please_select_category: "请选择报告分类",
+  input_title_please: "请输入报告标题",
   please_input_abstract: "请输入摘要",
   please_select_author: "请选择作者",
   please_select_frequency: "请选择频度",
@@ -156,10 +208,12 @@ export const ReportListZh = {
   no_reports_msg: "此分类暂无报告",
   chart_insertion_progress: "图表批量插入中...",
   last_save_time: "最近保存时间",
+  click_clear_btn: "一键清空内容",
   click_refresh_btn: "一键刷新",
   preview_btn: "预览",
   save_draft_btn: "存草稿",
   scheduled_publish_btn: "定时发布",
+  submit_chapter_btn:'提交章节',
   publish_btn: "发布",
   submission_btn: "提交",
   new_method_btn: "新增方式",
@@ -178,7 +232,7 @@ export const ReportListZh = {
   intercommodity_analysis_radio: "跨品种分析",
   just_mine_radio: "只看我的",
   insert_sandbox_tabs: "沙盘插入",
-  no_reports_msg: "沙盘名称/品种",
+  no_sandbox_msg: "沙盘名称/品种",
   insert_table_tabs: "表格插入",
   table_name_tabs: "表格名称",
   bulk_insertion_tabs: "我的图库批量插入",
@@ -208,7 +262,7 @@ export const ReportListZh = {
   img_uplaod_title: "图片上传",
   click_img_upload: "点击上传图片",
   select_img_card: "选择图片",
-  img_name_ipt: "请输入图名称",
+  img_name_ipt: "请输入图名称",
   select_img_type: "请选择图片类型",
   page_header_op: "版头",
   page_trailer_op: "版尾",
@@ -226,6 +280,7 @@ export const ReportListZh = {
   recorded_audio: "已传录音",
   not_recorded_audio: "未传录音",
   weChat_share: "微信分享",
+  copy_share_link:'复制链接',
   set_tags_title: "设置标签",
   select_ipt_pld: "输入或者选择",
   input_email_subject: "请输入邮件主题",
@@ -240,4 +295,53 @@ export const ReportListZh = {
   upload_img_error_msg: "有图片未上传完成,请稍等",
   all_update_publish_msg: "本期报告品种已全部更新,点击发布将同时发布周报,确认同时发布吗?",
   is_publish_report_msg: "您还未上传录音文件,确定发布报告吗?",
+
+
+
+  tab_public:'公共研报',
+  tab_share:'共享研报',
+  tab_mine:'我的研报',
+  /* 添加报告弹窗 */
+  label_add_way:'新增方式',
+  label_report_tit:'报告标题',
+  choose_inherit_report: '选择继承报告',
+  label_report_classify:'报告分类',
+  label_relation_variety: '关联品种',
+  label_report_abstract:'报告摘要',
+  label_report_author:'报告作者',
+  label_frequency:'频度',
+  label_createtime:'创建时间',
+  label_coop:'协作方式',
+  choose_cooper:'选择协作人',
+  coop_own: '个人',
+  coop_more: '多人协作',
+  label_report_layout:'报告布局',
+  layout_default:'常规布局',
+  layout_smart:'智能布局',
+  label_public:'公开发布',
+
+  tit_report_chap:'研报章节',
+  btn_add_chap: '添加章节',
+  /* 添加章节弹窗 */
+  label_chap_name:'章节名称',
+  label_chap_editor:'编辑人',
+  tit_choose_inher:'选择报告',
+  ph_report_tit: '请输入报告标题',
+  check_report_len: '只能选择一篇报告',
+  ph_select_user: '请选择用户',
+  del_chapter_msg: '是否确认删除该章节?',
+  report_empty_msg:'请输入报告内容',
+  img_set_btn: '版图设置',
+  no_chapter_msg:'暂无章节信息',
+  chapter_nosubmit_msg:'{name}内容未提交',
+
+  choose_head_img:'选择版头',
+  choose_end_img:'选择版尾',
+  canvas_set:'画布设置',
+  choose_layout_img:'选择版图',
+  variety_tip:`若章节关联品种,则章节阅读权限受章节关联品种的权限控制;<br>
+  若章节不关联品种,则章节阅读权限受分类关联品种的权限控制;`,
+  chapter_has_submit:'已提交',
+  chapter_no_submit:'未提交',
+  choose_msg: '选择'
 };

+ 4 - 4
src/lang/modules/ReportManagement/SmartReport.js

@@ -35,7 +35,7 @@ export const SmartReportEn = {
   smart_notification_pushed: "Notification Pushed",
   smart_filtering_criteria_btn: "Filter options",
   smart_title_creator_btn: "Title/Creator",
-  smart_report_type: "Report type",
+  smart_report_type: "Category",
   smart_creator_btn: "Creator",
   table_col02:'Operator',
   smart_release_approval_time: "Release/Approval Time",
@@ -52,7 +52,7 @@ export const SmartReportEn = {
   smart_release_prompt_btn: "Release prompt",
   smart_template_msg: "The report has been set to be released regularly. Do you want to publish the report immediately and push the template message?",
   smart_push_template_btn: "Do you want to publish the report immediately and push template messages?",
-  smart_status_table: "status",
+  smart_status_table: "Report status",
   smart_abstract_table: "Abstract",
   smart_select_file: "Select file",
   smart_sync_policy_report: "Sync Policy Report",
@@ -163,7 +163,7 @@ export const SmartReportZh = {
   smart_notification_pushed: "已推送消息",
   smart_filtering_criteria_btn: "筛选条件",
   smart_title_creator_btn: "标题 / 创建人",
-  smart_report_type: "报告类型",
+  smart_report_type: "分类",
   smart_creator_btn: "创建人",
   table_col02:'更新人',
   smart_release_approval_time: "发布/审批时间",
@@ -180,7 +180,7 @@ export const SmartReportZh = {
   smart_release_prompt_btn: "发布提示",
   smart_template_msg: "该报告已设置定时发布,是否立即发布报告并推送模板消息?",
   smart_push_template_btn: "是否立即发布报告,并推送模板消息?",
-  smart_status_table: "状态",
+  smart_status_table: "报告状态",
   smart_abstract_table: "摘要",
   smart_select_file: "选择文件",
   smart_sync_policy_report: "同步策略报告",

+ 2 - 2
src/lang/modules/systemManage/ReportApprove.js

@@ -30,7 +30,7 @@ export const ReportApproveEn = {
     approval_type03:'Or Sign (Approval or rejection by any one approver is sufficient)',
     des01:'Multiple approvers review and approve in sequence; The node passes only when all approvers agree; Approve in order of selection',
     des02:'The node passes only when all approvers agree; There is no sequence in approval.',
-    des03:'If any approver agrees, the node wil pass; There is no sequence in approval.',
+    des03:'Approval by one reviewer is sufficient.',
     warning_msg01:'Please select at least one person',
     search_btn:'Search',
     has_selected:'has been selected',
@@ -65,7 +65,7 @@ export const ReportApproveZh = {
     approval_type03:'或签(一名审批人同意或拒绝即可)',
     des01:'多个审批人依次进行审批;只有当所有审批人同意,该节点才能通过;按选择顺序审批',
     des02:'所有审批人同意,该节点才能通过;审批无先后顺序',
-    des03:'任意一名审批人同意,该节点即通过;审批无先后顺序',
+    des03:'一名审批人同意即可',
     warning_msg01:'请至少选择一人',
     search_btn:'搜索',
     has_selected:'项',

+ 5 - 2
src/mixins/reportApproveConfig.js

@@ -43,14 +43,17 @@ export default{
             const {IsReportApprove='',ReportApproveType=''} = res.Data
             this.IsReportApprove = IsReportApprove==='true'?true:false,
             this.ReportApproveType = ReportApproveType
+
+            console.log(this.isApprove)
         },
         //检查是否有审批流
         checkClassifyNameArr(type=1,classify=[]){
             this.checkLoading=true
             let params = {
                 ReportType:type,
-                ClassifyFirstId:classify[classify.length-2]||0,
-                ClassifySecondId:classify[classify.length-1]||0,
+                ClassifyFirstId:classify[0]||0,
+                ClassifySecondId:classify[1]||0,
+                ClassifyThirId:classify[2]||0,
             }
             approveInterence.checkClassifyApprove(params).then(res=>{
                 this.checkLoading=false

+ 28 - 16
src/routes/modules/oldRoutes.js

@@ -62,7 +62,26 @@ export default [
   {
     path: "/smartReportDetail",
     name: "智能报告",
-    component: () => import("@/views/smartReport/reportDetail.vue"),
+    component: () => import("@/views/report_manage/reportV2/smartReport/reportDetail.vue"),
+  },
+
+
+  {
+    path: '/reportEditV2',
+    name:'编辑研报',
+    component: () => import("@/views/report_manage/reportV2/normalReport/editReport.vue")
+  },
+  {
+    path: '/smpartReportEditV2',
+    name:'编辑研报',
+    component: () => import("@/views/report_manage/reportV2/smartReport/editReport.vue")
+  },
+
+  {
+    path: "/reportdtlV2",
+    component: () => import("@/views/report_manage/reportV2/normalReport/reportdtl.vue"),
+    name: "预览报告",
+    hidden: true,
   },
 
   // 主页
@@ -200,21 +219,6 @@ export default [
           pathName_en:"Add/Edit Day or Week Report"
         },
       },
-      // {
-      //   path: "reportupdate",
-      //   component: () => import("@/views/report_manage/dayWeekUpdate.vue"),
-      //   name: "更新管理",
-      //   hidden: true,
-      //   meta: {
-      //     keepAlive: false,
-      //   },
-      // },
-      // {
-      //   path: "reportlabel",
-      //   component: () => import("@/views/report_manage/tagLib.vue"),
-      //   name: "标签库",
-      //   hidden: true,
-      // },
       {
         path: "reportEnList",
         component: () =>
@@ -306,6 +310,14 @@ export default [
             name_en:"Smart Report"
         }
       },
+      {
+        path: 'reportNew',
+        name:'研报中心',
+        component: () => import("@/views/report_manage/reportV2/list.vue"),
+        meta:{
+          name_en:"Report Center"
+        }
+      }
     ],
   },
 

+ 8 - 1
src/utils/buttonConfig.js

@@ -33,8 +33,15 @@ export const reportManageBtn={
     reportManage_reportList:'reportManage:reportList',//研报列表的选项
     reportManage_reportList_uv:'reportManage:reportList:uv',//研报列表-PV/UV
     reportManage_reportList_sendTime:'reportManage:reportList:sendTime',//研报列表-报告推送时间
-    reportManage_dayWeekReportAdd:'reportManage:dayWeekReportAdd',//添加晨报周报
+    // reportManage_dayWeekReportAdd:'reportManage:dayWeekReportAdd',//添加晨报周报
     reportManage_reportAdd:'reportManage:reportAdd',//添加研报
+
+    reportManage_clearCont:'reportMange:clearCont',//一键清空内容
+
+    reportMange_chapter_add: 'reportMange:chapter:add',//章节添加
+    reportMange_chapter_sort: 'reportMange:chapter:sort',//章节排序
+    reportMange_chapter_share: 'reportMange:chapter:share',//章节分享
+    reportMange_chapter_editTag: 'reportMange:chapter:editTag',//章节添加标签
 }
 /*
  *--------智能研报列表----------- 

+ 12 - 0
src/utils/common.js

@@ -355,4 +355,16 @@ export const waitRequestReturn=(flag,callBack,timeout)=>{
   }else{
     callBack()
   }
+}
+
+/* 获取url的query */
+export function GetQueryString(url) {
+  let urlStr=url.split('?')[1]
+  let obj={}
+  let paramsArr=urlStr.split('&')
+  for (let index = 0; index < paramsArr.length; index++) {
+      let arr=paramsArr[index].split('=')
+      obj[arr[0]]=arr[1]
+  }
+  return obj
 }

+ 1 - 1
src/views/Login.vue

@@ -608,7 +608,7 @@ export default {
                 case "rai_researcher":
                 case "ficc_researcher":
                 case "researcher":
-                    path = "/reportlist";
+                    path = "/reportNew";
                     break;
                 // case "compliance": //合规
                 //     path = "/contractapprovallist";

+ 4 - 4
src/views/approve_manage/approveDetail.vue

@@ -58,8 +58,8 @@
 </template>
 
 <script>
-import ReportDetail from '@/views/smartReport/reportDetail.vue';
-import Reportdtl from '@/views/report_manage/reportdtl.vue'
+import ReportDetail from '@/views/report_manage/reportV2/smartReport/reportDetail.vue';
+import Reportdtl from '@/views/report_manage/reportV2/normalReport/reportdtl.vue'
 import TimeLine from './components/timeLine.vue';
 import RejectDialog from './components/rejectDialog.vue';
 import {approveInterence} from '@/api/modules/approve.js';
@@ -116,8 +116,8 @@ export default {
                     title:Report.ReportTitle||'',
                     classify:Report.ReportClassify||'',
                     approver:Approve.ApplyUserName||'',
-                    componentName:Report.ReportType===3?'ReportDetail':'Reportdtl',
-                    type:Report.ReportType
+                    componentName:Report.ReportLayout===2?'ReportDetail':'Reportdtl',
+                    type:Report.ReportLayout===2?3:Report.ReportType
                 }
                 this.formType = type||'detail'
                 this.approveInfo.state=Approve.State

+ 14 - 8
src/views/approve_manage/approveEdit.vue

@@ -5,7 +5,7 @@
             <el-form :inline="true" :model="approveForm" ref="approve-form" :rules="formRules"
                 label-width="180px" label-position="left">
                 <el-form-item :label="$t('SystemManage.ReportApprove.table_col01')" prop="name">
-                    <el-input v-model="approveForm.name" :disabled="this.$route.query.flowId" :placeholder="$t('ApprovalEdit.name_placeholder')"></el-input>
+                    <el-input v-model="approveForm.name" :placeholder="$t('ApprovalEdit.name_placeholder')"></el-input>
                 </el-form-item>
                 <el-form-item :label="$t('SystemManage.ReportApprove.table_col02')" prop="classify">
                     <el-cascader v-model="approveForm.classify"
@@ -116,8 +116,9 @@ export default {
             const params = {
                 FlowName:name,
                 ReportType:classify[0],
-                ClassifyFirstId:classify[classify.length-2]||0,
-                ClassifySecondId:classify[classify.length-1]||0,
+                ClassifyFirstId:classify[1]||0,
+                ClassifySecondId:classify[2]||0,
+                ClassifyThirdId:classify[3]||0,
                 Nodes
             }
             let res
@@ -141,13 +142,18 @@ export default {
                     ReportApproveFlowId:Number(id)
                 }).then(res=>{
                     if(res.Ret!==200) return 
-                    const {FlowName,ReportType,ClassifySecondId,Nodes} = res.Data||{}
+                    const {FlowName,ReportType,ClassifyFirstId,ClassifySecondId,Nodes,ClassifyThirdId} = res.Data||{}
                     this.approveForm.name = FlowName||''
                     //递归获取所有父级id
-                    const classify = this.classifyTree.find(i=>i.ClassifyId===ReportType)||{}
-                    const tempArr = findParentNode(classify.Children||[],ClassifySecondId)
-                    tempArr.push(ReportType)
-                    this.approveForm.classify = tempArr.reverse()
+                    // const classify = this.classifyTree.find(i=>i.ClassifyId===ReportType)||{}
+                    // const tempArr = findParentNode(classify.Children||[],ClassifySecondId)
+                    // tempArr.push(ReportType)
+                    // this.approveForm.classify = tempArr.reverse()
+                    this.approveForm.classify = ClassifyThirdId 
+                        ? [ReportType,ClassifyFirstId,ClassifySecondId,ClassifyThirdId]
+                        : ClassifySecondId
+                        ? [ReportType,ClassifyFirstId,ClassifySecondId]
+                        : [ReportType,ClassifyFirstId]
                     this.approveForm.flowNodes = Nodes||[]
                 })
             }

+ 2 - 2
src/views/approve_manage/components/flowNode/approveNode.vue

@@ -57,14 +57,14 @@
                     <div class="block" style="margin-top:30px;">
                         <p>{{$t('SystemManage.ReportApprove.mutl_person')}}</p>
                         <el-radio-group v-model="approveType">
-                            <el-radio :label="1">
+                            <!-- <el-radio :label="1">
                                 {{$t('SystemManage.ReportApprove.approval_type01')}}
                                 <el-tooltip effect="dark" placement="top" :content="$t('SystemManage.ReportApprove.des01')" >
                                     <span class="hint-text">
                                         <i class="el-icon-info"></i>
                                     </span>
                                 </el-tooltip>
-                            </el-radio>
+                            </el-radio> -->
                             <el-radio :label="2">
                                 {{$t('SystemManage.ReportApprove.approval_type02')}}
                                 <el-tooltip effect="dark" placement="top" :content="$t('SystemManage.ReportApprove.des02')" >

+ 1 - 1
src/views/approve_manage/mixins/approveMixins.js

@@ -1,7 +1,7 @@
 import {approveInterence} from '@/api/modules/approve.js'
 const filterNodes = (arr,hasDisabled)=>{
     arr.length &&arr.forEach((item) => {
-        hasDisabled&&(item.disabled = item.HasFlow)
+        hasDisabled&&(item.disabled = (item.Children&&item.Children.length)?false:item.HasFlow)
         item.Children.length && filterNodes(item.Children,hasDisabled);
         if (!item.Children.length) {
             delete item.Children;

+ 28 - 14
src/views/classify_manage/chapterSettingV2.vue

@@ -15,7 +15,7 @@
                     children: 'Child'
                 }"
 				check-strictly
-				:empty-text="$t('Common.no_classify_msg')"
+				:empty-text="$t('ReportManage.ReportList.no_chapter_msg')"
                 draggable
                 :allow-drop="canDropHandle"
                 @node-drop="dropOverHandle"
@@ -65,11 +65,11 @@
                 </el-form-item>
                 <!-- 上级分类 -->
                 <el-form-item :label="$t('ReportManage.CategoryList.parent_category')">
-                    <el-input  disabled :value="researchType=='day'?'晨报':'周报'" style="width: 317px;" 
+                    <el-input  disabled :value="parentClassifyName" style="width: 317px;" 
                     :placeholder="$t('ReportManage.CategoryList.related_variety_inputhint')"></el-input>
                 </el-form-item>
                 <!-- 关联品种 -->
-                <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')">
+                <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="reportVarietyList.length">
                     <template slot="label">
                         <el-tooltip class="item" effect="dark" :content="$t('ReportManage.CategoryList.related_variety_hint')">
                             <div>
@@ -104,15 +104,12 @@ import { getchapterTypeList,addChapterType,editChapterType,} from 'api/api.js';
 import {setChapterEnable,setChapterSort} from '@/api/modules/oldApi.js'
 import {reportVarietyInterence} from '@/api/modules/reportVariety'
 import {classifyPermissionInterface} from '@/api/modules/classifyApi.js'
+import { reportV2Interface } from '@/api/modules/reportV2.js'
 export default {
     name:"chapterSetting",
     components:{mDialog},
     beforeRouteEnter(to, from, next) {
-        if(to.query.reportType=='day'){
-            to.matched[1].name='晨报章节设置'
-        }else{
-            to.matched[1].name='周报章节设置'
-        }
+        to.matched[1].name='章节设置'
         next()
     },
     data() {
@@ -123,23 +120,23 @@ export default {
             addDialogShow:false,
             addForm:{
                 ReportChapterTypeName:"",
-                ResearchType:"",
+                // ResearchType:"",.
                 ChartPermissionIdList:''
             },
             researchType:'',// day-晨报;week-周报
+            parentClassifyName: '',
 
             reportVarietyList:[],//中文品种列表
         }
     },
     mounted(){
-        // 类型 周报-晨报
-        this.addForm.ResearchType=this.researchType=this.$route.query.reportType=='week'?'week':'day'
+        this.parentClassifyName = this.$route.query.classifyName || ''
         this.getList()
         this.getReportVarietyList()
     },
     methods: {
         getList(type){
-            getchapterTypeList({ReportType:this.researchType}).then(res=>{
+            getchapterTypeList({ClassifyId:Number(this.$route.query.id)}).then(res=>{
                 if(res.Ret == 200){
                     this.list=res.Data.List || []
                 }
@@ -151,6 +148,7 @@ export default {
             this.addDialogShow=true
             this.addForm.ReportChapterTypeName=''
             this.addForm.ChartPermissionIdList=''
+            this.addForm.ReportChapterTypeId=0
             console.log(this.addForm);
         },
 
@@ -171,7 +169,11 @@ export default {
         this.$refs.addForm.validate((valid)=>{
           if(valid){
             // 添加小程序是否显示参数 0显示,1隐藏
-            let params={...this.addForm,ChartPermissionIdList:this.addForm.ChartPermissionIdList||[]}
+            let params={
+                ...this.addForm,
+                ClassifyId: Number(this.$route.query.id),
+                ChartPermissionIdList:this.addForm.ChartPermissionIdList||[]
+            }
             // 请求方法
             let requestMethod;
             // console.log(params);
@@ -197,12 +199,24 @@ export default {
         })
       },
 
+
+        filterNodes(arr) {
+            arr.length && arr.forEach(item => {
+                item.Child && item.Child.length && this.filterNodes(item.Child)
+                if((item.Child && !item.Child.length)) {
+                    delete item.Child
+                }
+            })
+        },
         
 
         // 获取品种数据
         getReportVarietyList(){
-            reportVarietyInterence.filterVarietyOpts().then(res=>{
+            reportV2Interface.getClassifyPermissionList({
+                ClassifyId: Number(this.$route.query.id),
+            }).then(res=>{
                 this.reportVarietyList=res.Data||[]
+                this.filterNodes(this.reportVarietyList)
             })
         },
 

+ 1 - 0
src/views/classify_manage/classifyEnlistV2.vue

@@ -313,6 +313,7 @@ export default {
 .classify-page{
     .content-box{
         .el-tree-node__content{
+            height: fit-content;
             padding-top: 10px;
             padding-bottom: 10px;
             border-bottom: 1px solid #C8CDD9;

+ 137 - 28
src/views/classify_manage/classifylistV2.vue

@@ -18,6 +18,7 @@
                 </div>
             </div>
             <div style="display:flex;padding:10px;gap:10px">
+                <!-- <el-button type="primary" @click="transferReport">分类报告转移</el-button> -->
                 <!-- 添加分类 -->
                 <el-button 
                     type="primary"
@@ -62,7 +63,7 @@
                     <div class="opt-box">
                         <!-- 章节设置 -->
                         <span class="editsty" 
-                            v-if="['晨报','周报'].includes(data.ClassifyName)" 
+                            v-if="!data.Child || (data.Child&&!data.Child.length)" 
                             @click="chapterSetting(data)" 
                             v-permission="permissionBtn.classifyBtn.classifyList_cnClassify_chapterSetting">
                             {{ $t('ReportManage.CategoryList.section_settings') }}
@@ -99,14 +100,27 @@
                     </el-form-item>
                     <!-- 上级分类 -->
                     <el-form-item prop="parent_id" :label="$t('ReportManage.CategoryList.parent_category')">
-                        <el-select v-model="classifyForm.parent_id" 
-                            :placeholder="$t('ReportManage.CategoryList.related_variety_inputhint')" style="width:400px;">
-                            <el-option :label="$t('ReportManage.CategoryList.parent_none')" :value="0"></el-option>
-                            <el-option v-for="(item,index) in classifyparentArr" :key="index" :label="item.ClassifyName" :value="item.Id"></el-option>
-                        </el-select>
+
+                        <el-cascader
+                            v-model="classifyForm.parent_id" 
+                            :options="classifyparentArr"
+                            :disabled="classifyForm.classify_id"
+                            style="width:400px;"
+                            ref="classifyRef"
+                            :props="{ 
+                                checkStrictly: true,
+                                value: 'Id',
+                                label: 'ClassifyName',
+                                children:'Child',
+                                emitPath:false
+                            }"
+                            clearable
+                            @change="changeClassify"
+                        >
+                        </el-cascader>
                     </el-form-item>
                     <!-- 关联品种 -->
-                    <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="classifyForm.parent_id&&permissionBtn.classifyBtn.classifyList_cnClassify_connect_variety">
+                    <el-form-item prop="variety" :label="$t('ReportManage.CategoryList.related_variety')" v-if="canSetPermission">
                         <template slot="label">
                             <el-tooltip class="item" effect="dark" :content="$t('ReportManage.CategoryList.related_variety_hint')">
                                 <div>
@@ -125,6 +139,7 @@
                         ></el-cascader>
                     </el-form-item>
                 </el-form>
+                <div v-html="tips" style="color:#999;"></div>
             </div>
             <div slot="footer" style="margin-top: 20px;">
                 <el-button
@@ -138,6 +153,59 @@
                 >{{ $t('Dialog.confirm_save_btn') }}</el-button>
             </div>
         </m-dialog>
+
+        <!-- 转移报告弹窗 -->
+        <m-dialog
+            title="分类报告转移"
+            :show.sync="isTransferReport"
+            width="650px"
+        >
+
+            <div>
+                <el-form
+                    :model="transferForm"
+                    hide-required-asterisk
+                    label-width="auto"
+                >
+                    <el-form-item prop="classify_name" label="原分类">
+                        <el-cascader
+                          v-model="transferForm.oldClassify"
+                          @change="filterChange"
+                          :options="classifyparentArr"
+                          clearable
+                          placeholder="请选择分类"
+                          style="width:100%;"
+                      ></el-cascader>
+                    </el-form-item>
+                    <!-- 上级分类 -->
+                    <el-form-item prop="parent_id" label="转移至分类">
+
+                        <el-cascader
+                          v-model="transferForm.newClassify"
+                          @change="filterChange"
+                          :options="classifyparentArr"
+                          clearable
+                          placeholder="请选择分类"
+                          style="width:100%;"
+                      ></el-cascader>
+                    </el-form-item>
+                    
+                </el-form>
+            </div>
+
+            <div slot="footer" style="margin-top: 20px;">
+                <el-button
+                @click="isTransferReport=false"
+                style="width: 132px; height: 40px"
+                >{{ $t('Dialog.cancel_btn') }}</el-button>
+                <el-button
+                @click="handleSaveTransferReport"
+                type="primary"
+                style="width: 132px; height: 40px"
+                >{{ $t('Dialog.confirm_save_btn') }}</el-button>
+            </div>
+
+        </m-dialog>
     </div>
 </template>
 
@@ -146,8 +214,21 @@ import mDialog from '@/components/mDialog.vue';
 import { classifylist,classifyparent,classifyadd,classifyedit } from 'api/api.js';
 import {reportVarietyInterence} from '@/api/modules/reportVariety'
 import {classifyPermissionInterface} from '@/api/modules/classifyApi.js'
+import { reportV2Interface } from '@/api/modules/reportV2.js'
 export default {
     components:{mDialog},
+    computed: {
+        canSetPermission() {
+            /* 编辑最小级分类可设置品种 新增分类可设置跑品种 */
+            if(!this.permissionBtn.classifyBtn.classifyList_cnClassify_connect_variety) return false
+            
+            if(this.classifyForm.classify_id) {
+                return this.classifyForm.isLastLevel?true:false
+            }else {
+                return true
+            }
+        }
+    },
     data() {
         return {
             typeVal:1,
@@ -167,6 +248,13 @@ export default {
             classifyparentArr:[],
 
             reportVarietyList:[],//中文品种列表
+
+            /* 转移报告弹窗 */
+            isTransferReport: false,
+            transferForm: {},
+
+            tips: `注:若上级分类已关联报告,则新建的第一个子分类默认继承上级分类(父分类)关联的品种、报告、审批流,且关联品种支持编辑。  `
+
         }
     },
     mounted(){
@@ -174,32 +262,59 @@ export default {
         this.getReportVarietyList()
     },
     methods: {
+        /* 报告转移 */
+        transferReport() {
+            this.isTransferReport = true;
+            this.transferForm = {
+                oldClassify: '',
+                newClassify: ''
+            }
+        },
+        
+        handleSaveTransferReport() {
+            
+        },
+
+
         async getList(type){
             const res=await classifylist({
                 KeyWord:this.searchVal,
             })
             if(res.Ret===200){
                 this.list=res.Data.List||[]
+                
+                this.classifyparentArr=_.cloneDeep(this.list)
+                this.filterNodes(this.classifyparentArr)
             }
         },
 
-        // 晨报周报 去设置章节
+        /* 添加分类默认关联父级品种 */
+        async changeClassify(id) {
+            if(!this.classifyForm.classify_id) {
+                let item = this.$refs.classifyRef.getCheckedNodes(true)
+                console.log(item)
+                if(item&&item.length) {
+                    this.classifyForm.variety = item[0].data.ChartPermissionIdList
+                }
+            }
+        },
+
+        // 去设置章节
 		chapterSetting(row){
-			let reportType;
-			if(row.ClassifyName=='周报'){
-				reportType='week'
-			}else{
-				reportType='day'
-			}
-			this.$router.push({path:'chapterSetting',query:{reportType}})
+			this.$router.push({path:'chapterSetting',query:{ id:row.Id,classifyName: row.ClassifyName }})
 		},
 
+        filterNodes(arr) {
+            arr.length && arr.forEach(item => {
+                item.Child && item.Child.length && this.filterNodes(item.Child)
+                if(!item.Child || (item.Child&&!item.Child.length)  || item.Level===2) {
+                    delete item.Child
+                }
+            })
+        },
+
         async addClassify(){
-            this.classifyparentArr=[];
-            const res=await classifyparent()
-            if(res.Ret===200){
-                this.classifyparentArr=res.Data||[]
-            }
+
             this.classifyForm={
                 show:true,
                 classify_id:0,
@@ -209,14 +324,6 @@ export default {
             }
         },
         async handleEdit(item){
-            this.classifyparentArr=[];
-            const res=await classifyparent()
-            if(res.Ret===200){
-                // 编辑的是子分类或者没有子分类的才能选择上级分类
-                if(!item.Child){
-                    this.classifyparentArr=res.Data||[]
-                }
-            }
             
             this.classifyForm={
                 show:true,
@@ -224,6 +331,7 @@ export default {
                 classify_name:item.ClassifyName,
                 parent_id: item.ParentId,
                 variety:item.ChartPermissionIdList||'',//关联的品种
+                isLastLevel: !item.Child
             }
         },
         async setClassifyHandle(){
@@ -335,6 +443,7 @@ export default {
 .classify-page{
     .content-box{
         .el-tree-node__content{
+            height: fit-content;
             padding-top: 10px;
             padding-bottom: 10px;
             border-bottom: 1px solid #C8CDD9;

+ 4 - 2
src/views/ppt_manage/mixins/pptMixins.js

@@ -216,7 +216,8 @@ export default {
             PublishTime,
             Editor,
             CoverContent,
-            TitleSetting
+            TitleSetting,
+            AdminId
         } = res.Data
         const pptDate = formatPPTDate(this.currentLang, PptDate)
         let legalContent = JSON.parse(Content)
@@ -248,7 +249,8 @@ export default {
             PublishTime,
             Editor,
             CoverContent,
-            TitleSetting:legalTitleSetting
+            TitleSetting:legalTitleSetting,
+            AdminId
         }
       }else{
         this.result = {status:'',content:'获取ppt数据失败!'}

+ 3 - 4
src/views/ppt_manage/newVersion/components/catalog/transReport.vue

@@ -40,6 +40,7 @@
 
 <script>
 import {classifyTelList} from 'api/api.js';
+import { classifylist } from '@/api/modules/reportV2.js';
 import * as reportEnInterface from '@/api/modules/reportEnApi';
 export default {
   props:{
@@ -85,12 +86,10 @@ export default {
   methods: {
     async getClassifylist(){
       const res = this.$parent.currentLang!=='en'
-                  ?await classifyTelList()
+                  ?await classifylist({CurrentIndex:0,PageSize:1000,KeyWord:''})
                   :await reportEnInterface.classifyList({CurrentIndex:0,PageSize:1000,KeyWord:''})
       if(res.Ret===200){
-        this.reportList = this.$parent.currentLang!=='en'
-                          ?res.Data
-                          :res.Data.List
+        this.reportList = res.Data.List || []
       }
       this.getListLoading = false
     },

+ 8 - 2
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -419,6 +419,11 @@ export default {
       ]
     },
 
+    // 登录账号id
+    RoleId() {
+      return  Number(localStorage.getItem('AdminId'))
+    }
+
   },
   watch:{
     searchTitle(newVal){
@@ -623,6 +628,7 @@ export default {
     },
     //设置操作按钮
     setToolList(pptDetail={}){
+      console.log(pptDetail)
       //公共目录:显示除 删除, 编辑 外的全部按钮
       if(this.treeName==='public'){
         this.pptToolList = toolList.filter((i)=>{
@@ -654,7 +660,7 @@ export default {
           'publish':checkPermissionBtn(pptPermission.ppt_publish),
           'present':checkPermissionBtn(pptPermission.ppt_show),
           'download':checkPermissionBtn(pptPermission.ppt_download),
-          'transform':checkPermissionBtn(pptPermission.ppt_toReport),
+          'transform':checkPermissionBtn(pptPermission.ppt_toReport)&&this.RoleId===pptDetail.AdminId,
           'transEn':checkPermissionBtn(pptPermission.ppt_toEn),
           'edit':checkPermissionBtn(pptPermission.ppt_save),
           'copy':checkPermissionBtn(pptPermission.ppt_copy),
@@ -1223,7 +1229,7 @@ export default {
     getTransSet(data){
       pptInterface.transReport({
         PptId:this.pptItem.PptId,
-        ClassifyIdSecond:data.type,
+        ClassifyId:data.type,
         Title:data.title
       }).then(res=>{
         if(res.Ret===200){

+ 1 - 1
src/views/report_manage/addreportNew.vue

@@ -825,7 +825,7 @@ export default {
 				const t=new Date().getTime()
 				item.domId=item.UniqueCode+t //避免多次添加同一图表 id相同
 				htmlStr=htmlStr+`<p style='text-align:left; margin-top:10px;'>
-							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${this.currentLang}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 						</p>`
 			})
 			this.$nextTick(()=>{

+ 1 - 1
src/views/report_manage/editChapterReport.vue

@@ -796,7 +796,7 @@ export default {
         htmlStr =
           htmlStr +
           `<p style='text-align:left; margin-top:10px;'>
-							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${this.currentLang}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 						</p>`;
       });
       this.$nextTick(() => {

+ 1 - 1
src/views/report_manage/editreportNew.vue

@@ -832,7 +832,7 @@ export default {
 				const t=new Date().getTime()
 				item.domId=item.UniqueCode+t //避免多次添加同一图表 id相同
 				htmlStr=htmlStr+`<p style='text-align:left; margin-top:10px;'>
-							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${this.currentLang}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
 						</p>`
 			})
 			this.$nextTick(()=>{

+ 869 - 0
src/views/report_manage/reportV2/components/chapterEditWrapper.vue

@@ -0,0 +1,869 @@
+<template>
+  <div class="left-chapter-box">
+    <div class="box-top">
+      <h3>{{reportBase.Title}}</h3>
+
+      <ul class="handle-list">
+        <li v-if="reportBase.ReportLayout===2&&isCreator" @click="openTerritorySet">
+          <el-tooltip
+            effect="dark" 
+            :content="$t('ReportManage.ReportList.img_set_btn')" 
+            placement="top"
+          >
+            <i class="el-icon-setting" style="color:#0052D9;font-size:20px;"></i>
+          </el-tooltip>
+        </li>
+
+        <li @click="$emit('openBaseInfo')" v-if="isCreator">
+          <el-tooltip
+            effect="dark" 
+            :content="$t('ReportManage.ReportList.information_title')" 
+            placement="top"
+          >
+            <img src="~@/assets/img/icons/baseinfo_ico.svg" class="handle-icon" alt="">
+          </el-tooltip>
+        </li>
+        <li @click="$emit('handlePreviewReport')">
+          <el-tooltip
+            effect="dark" 
+            :content="$t('ReportManage.ReportList.preview_btn')" 
+            placement="top"
+          >
+            <img src="~@/assets/img/icons/preview_ico.svg" class="handle-icon" alt="">
+          </el-tooltip>
+        </li>
+        
+        <template v-if="!isApprove||!hasApproveFlow">
+            <li 
+                class="action-item" 
+                :class="{'disabled':puiblishLoading}"
+                @click="handlePublishReport('dsfb')"
+                v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+                >
+                  <el-tooltip
+                    effect="dark" 
+                    :content="$t('ReportManage.ReportList.scheduled_publish_btn')" 
+                    placement="top"
+                  >
+                    <img src="~@/assets/img/icons/timing_ico.svg" class="handle-icon" alt="">
+                  </el-tooltip>
+            </li>
+            <li 
+                class="action-item" 
+                :class="{'disabled':puiblishLoading}"
+                @click="handlePublishReport('fb')"
+                v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+            >
+                <el-tooltip
+                  effect="dark" 
+                  :content="$t('ReportManage.ReportList.publish_btn')" 
+                  placement="top"
+                >
+                  <img src="~@/assets/img/icons/publish_ico.svg" class="handle-icon" alt="">
+                </el-tooltip>
+            </li>
+        </template>
+        <template v-if="isApprove&&hasApproveFlow">
+            <li 
+                class="action-item" 
+                :class="{'disabled':puiblishLoading}"
+                @click="handlePublishReport('submit')"
+                v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+            >
+              <el-tooltip
+                effect="dark" 
+                :content="$t('ReportManage.ReportList.submission_btn')" 
+                placement="top"
+              >
+                <img src="~@/assets/img/icons/submit_ico.svg" class="handle-icon" alt="">
+              </el-tooltip>
+            </li>
+        </template>
+      </ul>
+    </div>
+
+    <div class="box-main">
+      <div class="main-top">
+        <h3><!-- 研报章节 -->{{$t('ReportManage.ReportList.tit_report_chap')}}</h3>
+        <el-button 
+          type="primary" 
+          size="small" 
+          @click="openAddChapter"
+          v-if="isCreator"
+        ><!-- 添加章节 -->{{$t('ReportManage.ReportList.btn_add_chap')}}</el-button>
+      </div>
+      
+      <ul class="chapter-list" v-if="chapterList.length">
+        <draggable
+            v-model="chapterList"
+            animation="300"
+            :group="{ name: 'chapter', pull: false, put: false }"
+            @start="dragStartHandler"
+            @update="dragenter"
+            @end="dragOverHandler"
+            :disabled="!isCreator"
+          >
+          <li 
+            v-for="item in chapterList" 
+            :key="item.ReportChapterId" 
+            @click="chooseChapter(item)"
+            :class="selectChapterId===item.ReportChapterId&&'act'"
+          >
+            <div class="card-top" v-if="item.TypeName">
+              <div class="type-name" >{{item.TypeName}}</div>
+            </div>
+
+            <div class="card-top">
+              <span style="font-size: 16px;">{{item.Title}}</span>
+            </div>
+            
+            <div class="card-bottom">
+              <span 
+                :style="{color:item.PublishState===2?'#67C23A':'#000'}" 
+                v-if="item.CanEdit"
+              >
+                {{item.PublishState===2 ? $t('ReportManage.ReportList.chapter_has_submit') : $t('ReportManage.ReportList.chapter_no_submit') }}
+                <el-popover
+                    placement="top"
+                    trigger="click"
+                >   
+                    <img style="width:150px" :src="item.QRCodeImg" alt="">
+
+                    <img 
+                      src="~@/assets/img/icons/wx_round.svg" 
+                      class="handle-icon"
+                      slot="reference"
+                      v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportMange_chapter_share)&&item.PublishState===2"
+                      style="font-size:18px;color:#0052D9;cursor:pointer;"
+                      @click.stop="handleGetWechatImg(item)"
+                    />
+                </el-popover>
+              </span>
+              <span v-else style="color:#E37318">{{item.Editor}}<!-- 编辑中... -->{{$t('ReportManage.smart_btn.editing')}}</span>
+              <div>
+                <img
+                  src="~@/assets/img/data_m/move_ico.png"
+                  alt=""
+                  style="width: 16px; height: 16px;margin-right:5px;"
+                />
+
+                
+                <el-dropdown 
+                  trigger="click" 
+                  @command="handleChapterItem"
+                  v-if="item.IsAuth"
+                >
+                  <span class="el-dropdown-link">
+                    <i class="el-icon-s-operation editsty" style="font-size: 18px;"></i>
+                  </span>
+
+                  <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item 
+                      :command="{type:'beseInfo',item}"
+                      v-if="isCreator"
+                    ><!-- 基础信息 -->{{$t('ReportManage.ReportList.information_title')}}</el-dropdown-item>
+                    <el-dropdown-item 
+                      :command="{type:'del',item}"
+                      v-if="isCreator"
+                    ><!-- 删除 -->{{$t('Table.delete_btn')}}</el-dropdown-item>
+                    <el-dropdown-item 
+                      :command="{type:'adTag',item}" 
+                      v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportMange_chapter_editTag)"><!-- 添加标签 -->{{$t('ReportManage.ReportList.add_labels_section')}}</el-dropdown-item>
+                    <el-dropdown-item :command="{type:'upAudio',item}"><!-- 上传录音 -->{{$t('ReportManage.ReportList.up_recording_lable')}}</el-dropdown-item>
+                  </el-dropdown-menu>
+                </el-dropdown>
+              </div>
+            </div>
+          </li>
+        </draggable>  
+      </ul>
+
+      <div class="chapter-list" v-else>
+       <tableNoData :text="$t('ReportManage.ReportList.no_chapter_msg')" size="mini"/>
+      </div>
+    </div>
+
+    <!-- 添加章节弹窗 -->
+    <m-dialog
+      :title="chapterInfo.id?'编辑章节':'添加章节'" 
+      :show.sync="isOpenChapterDia" 
+      width="650px"
+      @close="isOpenChapterDia=false"
+    >
+      <div class="chapter-dialog-main">
+        <el-form 
+          :model="chapterInfo" 
+          :rules="chapterRules" 
+          ref="formRef" 
+          label-position="left"
+          hide-required-asterisk
+          label-width="120px"
+        >
+          <el-form-item prop="chapterName" :label="$t('ReportManage.ReportList.label_chap_name')">
+              <el-input
+                type="text" 
+                v-model="chapterInfo.chapterName"
+                style="width:350px;"
+                placeholder="请输入章节名称"
+              />
+          </el-form-item>
+          <el-form-item prop="varietys">
+              <template slot="label">
+                  <el-tooltip class="item" effect="dark">
+                      <div slot="content" v-html="varietyTip"></div>
+                      <div>
+                          <span>{{ $t('ReportManage.CategoryList.related_variety') }}</span>
+                          <i class="el-icon-info"></i>
+                      </div>
+                  </el-tooltip>
+              </template>
+
+              <el-cascader
+                  :options="reportVarietyOpts" 
+                  v-model="chapterInfo.varietys" 
+                  placeholder="请选择关联品种"
+                  collapse-tags
+                  :show-all-levels="false"
+                  :props="{
+                    value:'PermissionId',
+                    label:'PermissionName',
+                    children:'Child',
+                    multiple: true,
+                    emitPath:false
+                  }" 
+                  style="width:350px;"
+                  clearable
+              ></el-cascader>
+          </el-form-item>
+          <el-form-item prop="editors" :label="$t('ReportManage.ReportList.label_chap_editor')">
+            <el-cascader
+              v-model="chapterInfo.editors"
+              :options="userOpts"
+              :show-all-levels="false"
+              collapse-tags
+              filterable
+              :props="{
+                value:'AdminId',
+                label:'AdminName',
+                children:'Children',
+                emitPath: false,
+                multiple: true
+              }"
+              clearable
+              placeholder="请选择编辑人"
+              style="width:350px;"
+            />
+
+          </el-form-item>
+        </el-form>
+      </div>
+      <div slot="footer" style="margin-top: 20px;">
+        <el-button
+          @click="$refs.formRef.resetFields();isOpenChapterDia=false"
+          style="width: 132px; height: 40px"
+        ><!-- 取消 -->{{$t('Dialog.cancel_btn')}}</el-button>
+        <el-button
+          @click="handleSaveChapter"
+          type="primary"
+          style="width: 132px; height: 40px"
+        ><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button>
+      </div>
+
+    </m-dialog>
+
+    <!-- 添加标签弹窗 -->
+    <m-dialog
+      :show.sync="isOpenChapterTag"
+      :title="$t('ReportManage.ReportList.set_tags_title')"
+      width="450px"
+    >
+      <div class="edit-tag-wrap">
+          <span style="margin-right: 20px">{{chapterInfo.chapterName}}</span>
+          <el-select
+            v-model="chapterInfo.tags"
+            filterable
+            allow-create
+            default-first-option
+            :placeholder="$t('ReportManage.ReportList.select_ipt_pld')">
+            <el-option
+                v-for="item in tagOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+            </el-option>
+          </el-select>
+          <div style="margin:30px 0;text-align:center">
+              <el-button type="primary" plain @click="isOpenChapterTag=false">{{$t('Dialog.cancel_btn')}}</el-button>
+              <el-button type="primary" @click="handleSaveChapterTag">{{$t('Dialog.confirm_btn')}}</el-button>
+          </div>
+      </div>
+    </m-dialog>
+
+
+    <!-- 上传音频弹窗 -->
+    <m-dialog
+      :show.sync="isOpenUploadAudio"
+      :title="$t('ReportManage.smart_audio_upload_btn')"
+      width="450px"
+      @close="isOpenUploadAudio=false;uploadAudioLoading=false;"
+    >
+        <div class="edit-tag-wrap">
+            <div>
+              <el-input
+                v-model="chapterInfo.audioName"
+                readonly
+                style="width: 65%"
+                :placeholder="$t('ReportManage.ReportList.upload_audio_file')"
+              ></el-input>
+              <el-upload
+                style="display: inline-block; margin-left: 10px"
+                action=""
+                accept=".mp3,.m4a"
+                :http-request="handleUpload"
+                :before-upload="handelBeforeUploadAudio"
+                :show-file-list="false"
+                :disabled="startUploadAudio"
+              >
+                <el-button type="primary" :loading="startUploadAudio"
+                  >{{$t('ReportManage.ReportList.up_recording_lable')}}</el-button
+                >
+              </el-upload>
+
+              <p style="color: #999; font-size: 12px;margin-top: 10px;">
+                {{$t('ReportManage.ReportList.note_audio_minutes')}}
+              </p>
+            </div>
+            <div style="margin-top:30px;text-align:center">
+                <el-button type="primary" plain @click="isOpenUploadAudio=false;uploadAudioLoading=false;">{{$t('Dialog.cancel_btn')}}</el-button>
+                <el-button type="primary" @click="handleSaveAudio" :loading="uploadAudioLoading">{{uploadAudioLoading ? $t('ReportManage.smart_btn.uploading') :$t('Dialog.confirm_btn')}}</el-button>
+            </div>
+        </div>
+    </m-dialog>
+
+    <!-- 版图设置弹窗 -->
+    <smartTerritorSet 
+      :isShow.sync="isOpenTerritorDia"
+      :info="reportBase"
+      @change="handleChangeImgSet"
+    />
+
+  </div>
+</template>
+<script>
+import draggable from 'vuedraggable';
+import mDialog from '@/components/mDialog.vue';
+import smartTerritorSet from './smartTerritorSetDia.vue'
+import { chapterTrendTagList } from '@/api/api.js';
+import { 
+  dayWeekChapterList,
+  reportV2Interface,
+  chapterQRCodeImg,
+  editChapterTrendTag,
+  markReport
+} from '@/api/modules/reportV2'
+export default {
+  components: { draggable,mDialog,smartTerritorSet },
+  props: {
+    isApprove: {
+      type: Boolean
+    },
+    hasApproveFlow: {
+      type: Boolean
+    }
+  },
+  computed: {
+    isCreator() {
+      let roleId = Number(localStorage.getItem('AdminId'))
+      return roleId === this.reportBase.AdminId;
+    },
+    RoleId() {
+      return Number(localStorage.getItem('AdminId'))
+    }
+  },
+  data() {
+    return {
+      chapterList: [],
+
+      startIndex: 0,
+      preIndex: 0,
+      nextIndex: 0,
+
+      reportBase: {},
+      selectChapterId: 0, //选中章节Id
+      editChapterId: 0,//编辑章节Id
+
+      /* 章节弹窗 */
+      isOpenChapterDia: false,
+      reportVarietyOpts: [],
+      userOpts: [],
+      chapterInfo: {
+        id: 0,
+        varietys:[],
+        editors:[],
+        chapterName:'',
+        tags: '',
+        audioName:'',
+        audioFile: ''
+      },
+      chapterRules: {
+        chapterName: [{
+          required:true,message:'章节名称不能为空',trigger:'blur'
+        }]
+      },
+
+      varietyTip:`若章节关联品种,则章节阅读权限受章节关联品种的权限控制;<br>
+        若章节不关联品种,则章节阅读权限受分类关联品种的权限控制;
+      `,
+
+      /* 标签弹窗 */
+      isOpenChapterTag: false,
+      tagOptions: [],
+
+      /* 上传录音弹窗 */
+      isOpenUploadAudio: false,
+      uploadAudioLoading: false,
+
+      /* 版图设置弹窗 */
+      isOpenTerritorDia: false
+    }
+  },
+  mounted(){
+    this.getChapterList(true);
+    this.getReportBaseInfo();
+    this.getChapterTrendTagList()
+  },
+  methods:{
+    /* 发布总报告 */
+    async handlePublishReport(tp) {
+      //校验章节是否都已发布
+      let res = await reportV2Interface.checkChaterPublishState({
+        ReportId: Number(this.$route.query.id)
+      })
+      if(res.Data&&res.Data.length>0){
+        let str = res.Data.map(_ =>_.Title).join(',')
+        return this.$message.warning(this.$t('ReportManage.ReportList.chapter_nosubmit_msg',{name: str}))
+      } 
+
+      this.$emit('handlePublish',tp)
+    },
+
+    /* 版图设置 */
+    openTerritorySet() {
+      this.isOpenTerritorDia = true;
+    },
+    /* 版图设置保存 */
+    async handleChangeImgSet(info) {
+      console.log(info)
+      
+      const res = await reportV2Interface.setReportLayoutImg({
+        ReportId: Number(this.$route.query.id),
+        HeadImg: info.headImg,
+        EndImg: info.endImg,
+        HeadResourceId: info.headImgId,
+        EndResourceId: info.endImgId,
+        CanvasColor: info.bgColor,
+      })
+
+      if(res.Ret !== 200) return 
+       
+      this.$message.success(this.$t('MsgPrompt.set_success_msg'))
+      
+      this.reportBase.HeadImg = info.headImg;
+      this.reportBase.EndImg = info.endImg;
+      this.reportBase.HeadResourceId = info.headImgId;
+      this.reportBase.EndResourceId = info.endImgId;
+      this.reportBase.CanvasColor = info.bgColor;
+    },
+
+    async handleMarkOver(ReportChapterId=0) {
+      await markReport({
+        Status: 3,
+        ReportId: Number(this.$route.query.id),
+        ReportChapterId,
+      });
+    },
+
+    //选择章节 预览
+    async chooseChapter(item) {
+      this.editChapterId && this.handleMarkOver(this.editChapterId);
+
+      if(item.IsAuth) {
+         //编辑前标记一下
+          const res = await markReport({
+            Status: 1,
+            ReportId: Number(this.$route.query.id),
+            ReportChapterId: item.ReportChapterId
+          });
+          
+          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;
+          }
+
+        this.editChapterId = item.ReportChapterId;
+        this.selectChapterId = item.ReportChapterId;
+      }else {
+        this.selectChapterId = item.ReportChapterId;
+        this.editChapterId = 0;
+      }
+
+      this.$emit('change',{ selectChapterId: this.selectChapterId,editChapterId:this.editChapterId })
+    },
+
+    //添加章节弹窗
+    openAddChapter(item=null) {
+      console.log(item)
+      if(item.ReportChapterId) {
+        this.chapterInfo = {
+          id: item.ReportChapterId,
+          varietys:item.PermissionIdList,
+          editors:item.GrandAdminIdList,
+          chapterName:item.Title,
+          tags: ''
+        }
+      }else {
+        this.chapterInfo = {
+          id: 0,
+          varietys:[],
+          editors:[],
+          chapterName:'',
+          tags: ''
+        }
+      }
+
+      this.isOpenChapterDia = true;
+    },
+
+    /* 保存章节编辑 */
+    async handleSaveChapter() {
+      await this.$refs.formRef.validate()
+
+      let params = {
+        Title: this.chapterInfo.chapterName,
+        PermissionIdList: this.chapterInfo.varietys,
+        AdminIdList: this.chapterInfo.editors
+      }
+
+      const res = this.chapterInfo.id 
+        ? await reportV2Interface.editChapterBase({
+          ReportChapterId: this.chapterInfo.id,
+          ...params
+        })
+        : await reportV2Interface.addChapter({
+            ReportId: this.reportBase.Id,
+            ...params
+          })
+      if(res.Ret !== 200) return
+
+      this.$message.success(res.Msg)
+      this.isOpenChapterDia = false;
+      this.getChapterList();
+      this.$emit('update',{ Title: this.chapterInfo.chapterName })
+    },
+
+    /* 删除章节 */
+    handleDelChapter(item) {
+      this.$confirm(this.$t('ReportManage.ReportList.del_chapter_msg'),this.$t('Confirm.prompt'),{
+        type: 'warning'
+      }).then( async() => {
+          const res = await reportV2Interface.removeChapter({
+            ReportChapterId: item.ReportChapterId
+          })
+    
+          if(res.Ret!==200) return
+          this.$message.success(this.$t('MsgPrompt.delete_msg'))
+          this.chapterList.splice(this.chapterList.findIndex(_=>_.ReportChapterId===item.ReportChapterId),1)
+
+          this.selectChapterId = 0;
+          this.editChapterId = 0;
+          this.$emit('change',{ selectChapterId: this.selectChapterId,editChapterId:this.editChapterId })
+
+      }).catch(() =>{})
+
+    },
+
+    /* 获取章节分享太阳码 */
+    async handleGetWechatImg(item) {
+      if(item.QRCodeImg) return
+      
+      const res=await chapterQRCodeImg({
+        CodeScene:JSON.stringify({chapterId:item.ReportChapterId.toString()}),
+        CodePage:'pages-report/chapterDetail'
+      })
+      if(res.Ret!==200) return
+
+      this.$set(this.chapterList,this.chapterList.findIndex(_ => _.ReportChapterId===item.ReportChapterId),{...item,QRCodeImg:res.Data})
+    },
+
+    //添加章节标签
+    openAddChapterTag(item) {
+      this.chapterInfo = {
+        id: item.ReportChapterId,
+        varietys:[],
+        editors:[],
+        chapterName: item.Title,
+        tags: item.Trend
+      }
+      this.isOpenChapterTag = true;
+    },
+
+    /* 保存关联章节标签 */
+    async handleSaveChapterTag() {
+      const res = await editChapterTrendTag({
+          ReportChapterId:Number(this.chapterInfo.id),
+          Trend: this.chapterInfo.tags
+      })
+
+      if(res.Ret!==200) return
+
+      this.$message.success(res.Msg)
+      this.isOpenChapterTag=false
+
+      this.getChapterList()
+    },
+
+    /* 上传音频 */
+    openUploadAudio(item) {
+      this.chapterInfo.id= item.ReportChapterId,
+      this.chapterInfo.audioName = item.VideoName,
+      this.chapterInfo.audioFile = '',
+        
+      this.isOpenUploadAudio = true;
+    },
+
+    handelBeforeUploadAudio(e) {
+      if (
+        e.name.indexOf(".mp3") == -1 &&
+        e.name.indexOf(".wav") == -1 &&
+        e.name.indexOf(".wma") == -1 &&
+        e.name.indexOf(".m4a") == -1
+      ) {
+        // this.$message.warning("上传失败,上传音频格式不正确");
+        this.$message.warning(this.$t('ReportManage.ReportList.upload_audio_error_msg'));
+        upload_audio_error_msg
+        return false;
+      }
+    },
+
+    async handleUpload(e) {
+      this.chapterInfo.audioName = e.file.name;
+      this.chapterInfo.audioFile  = e.file;
+    },
+
+    async handleSaveAudio() {
+      
+      this.uploadAudioLoading = true;
+      let params = new FormData();
+        params.append("file", this.chapterInfo.audioFile);
+        params.append("ReportChapterId", this.chapterInfo.id);
+      const res = await reportV2Interface.uploadChpterAudio(params)
+
+      this.uploadAudioLoading = false;
+      if(res.Ret !== 200) return
+      this.isOpenUploadAudio = false;
+
+      this.getChapterList()
+    },
+
+    /* 章节操作 */
+    handleChapterItem({type,item}) {
+      console.log(type,item)
+      switch(type) {
+        case 'beseInfo': 
+          this.openAddChapter(item);
+          break
+        case 'del':
+          this.handleDelChapter(item)
+          break
+        case 'adTag': 
+          this.openAddChapterTag(item)
+          break
+        case 'upAudio': 
+          this.openUploadAudio(item)
+          break
+        case 'wxShare':
+          this.handleGetWechatImg(item)
+          break
+      }
+    },
+
+    /* 获取章节列表 */
+    async getChapterList(isInit=false) {
+      if(!this.$route.query.id) return 
+
+      const res = await dayWeekChapterList({
+        ReportId: Number(this.$route.query.id)
+      })
+      if(res.Ret !== 200) return 
+
+      this.chapterList = res.Data || []
+
+      isInit && this.selectDefaultChapter()
+    },
+
+
+    selectDefaultChapter() {
+      let firstChapter = this.chapterList.find(_ => _.CanEdit || !_.IsAuth)
+      if(firstChapter) {
+        this.chooseChapter(firstChapter)
+      }
+    },
+
+
+     /* 获取报告基础信息用户范围 品种范围 */
+    async getReportBaseInfo(type='init') {
+      if(!this.$route.query.id) return 
+
+      const res = await reportV2Interface.getRportBase({
+         ReportId: Number(this.$route.query.id)
+      })
+
+      if(res.Ret!==200) return
+      this.reportBase = res.Data;
+
+      if(res.Data.PrePublishTime) this.$parent.taskTime = res.Data.PrePublishTime;
+
+      if(type!=='notCheck') {
+        let classify = [res.Data.ClassifyIdFirst,res.Data.ClassifyIdSecond,res.Data.ClassifyIdThird]
+        this.$emit('checkClassifyNameArr',classify)
+      }
+
+      this.reportVarietyOpts = res.Data.PermissionList||[];
+      this.userOpts = res.Data.GrandAdminList||[];
+
+    },
+    
+
+     //获取章节标签数据(仅在获取章节列表成功后获取一次)
+    async getChapterTrendTagList(){
+        const res=await chapterTrendTagList()
+        if(res.Ret!==200) return
+        
+        let arr=res.Data||[]
+
+        this.tagOptions=arr.map(item=>({value:item.KeyWord,label:item.KeyWord}))
+    },
+
+    /* 拖动开始 记录位置 */
+    dragStartHandler({ oldIndex }) {
+      this.startIndex = this.chapterList[oldIndex].ReportChapterId;
+    },
+
+    /* 拖动结束 替换  */
+    async dragOverHandler() {
+      const res = await reportV2Interface.moveChapter({
+          ReportChapterId: this.startIndex,
+          PrevReportChapterId: this.preIndex,
+          NextReportChapterId: this.nextIndex
+      })
+      
+      if (res.Ret !== 200) return;
+      this.$message.success(res.Msg)
+    },
+
+    /* 移动后的上一个位置id 若移到第一位则取0 获取后一个id 若是最后一个取0*/
+    dragenter({ newIndex }) {
+      console.log(newIndex)
+      this.preIndex = newIndex > 0 ? this.chapterList[newIndex - 1].ReportChapterId : 0;
+      this.nextIndex = newIndex ===  this.chapterList.length - 1 ? 0 : this.chapterList[newIndex + 1].ReportChapterId
+    },
+  },
+}
+</script>
+<style scoped lang='scss'>
+*{box-sizing: border-box;}
+.left-chapter-box {
+  width: 350px;
+  margin-right: 20px;
+  background: #fff;
+  .box-top,.box-main {
+    padding: 15px;
+  }
+
+  .box-top {
+    padding-bottom: 0;
+    .handle-list {
+      margin: 30px 0 10px;
+      display: flex;
+      gap: 0 20px;
+      li { 
+        cursor: pointer;display: flex;align-items: center;
+          &.disabled {
+              pointer-events: none;
+              cursor: not-allowed;
+              color:#999;
+          }
+          .handle-icon {
+            width: 18px;
+            height: 18px;
+          }
+      }
+    }
+  }
+  .box-main {
+    padding-right: 0;
+    border-top: 1px solid #DCDFE6;
+    .main-top {
+      padding-right: 15px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+    }
+  }
+
+  .chapter-list {
+    margin-top: 20px;
+    padding-right: 15px;
+    height: calc(100vh - 210px);
+    overflow-y: auto;
+    li {
+      padding: 15px;
+      background: #F8F8F8;
+      border-radius: 6px;
+      margin-bottom: 15px;
+      border: 1px solid #C8CDD9;
+      &.act {
+        background: #ECF2FE;
+        border: 1px solid #0052D9;
+      }
+
+      .type-name {
+        background: #0052D9;
+        padding: 2px 12px;
+        color: #fff;
+        border-radius: 10px;
+        width: fit-content;
+        margin-bottom: 10px;
+      }
+
+      .card-top {
+        display: flex;
+        justify-content: space-between;
+      }
+
+      .card-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 30px;
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.chapter-dialog-main {
+  .el-cascader .el-input {
+    width: 100%;
+  }
+}
+</style>

+ 201 - 0
src/views/report_manage/reportV2/components/chooseCooperaUserDia.vue

@@ -0,0 +1,201 @@
+<template>
+  <el-dialog
+    v-dialogDrag
+    :title="$t('ReportManage.ReportList.choose_cooper')"
+    width="650px"
+    :visible.sync="isShow"
+    :modal-append-to-body="false"
+    :close-on-click-modal="false"
+    :append-to-body="false"
+    @close="closeDia"
+  >
+      <div class="dialog-wrap">
+        <div class="before-transfer transfer">
+            <div class="search">
+                <el-input 
+                  :placeholder="'搜索'" 
+                  suffix-icon="el-icon-search" 
+                  style="width:100%;"
+                  v-model="searchText" 
+                  @input="$refs['trans-tree'].filter(searchText)"
+                ></el-input>
+            </div>
+            <div class="content">
+                <el-tree 
+                    node-key="NodeIdKey"
+                    ref="trans-tree"
+                    show-checkbox
+                    :data="treeData"
+                    :props="{
+                        label:'NodeName',
+                        children:'Children'
+                    }"
+                    :filter-node-method="filterNode"
+                    @check-change="handleCheckChange"
+                ></el-tree>
+            </div>
+        </div>
+        <div class="after-transfer transfer">
+            <div class="head">
+                <span>已选{{choosedList.length}}项</span>
+                <span class="btn-text delete" @click="clearUser">{{$t('SystemManage.ReportApprove.clear_btn')}}</span>
+            </div>
+            <ul
+              class="content"
+            >
+                <li class="list-item" v-for="item in choosedList" :key="item.NodeIdKey">
+                    <span class="name">{{item.NodeName}}</span>
+                    <span class="icon-btn" style="color:#C0C4CC;">
+                        <i class="el-icon-close" @click.stop="removeItem(item)"></i>
+                    </span>
+                </li>
+            </ul>
+        </div>
+      </div>
+      <div class="dialog-btn">
+          <el-button type="primary" plain @click="closeDia">{{$t('Dialog.cancel_btn')}}</el-button>
+          <el-button type="primary" @click="handleSaveChecked">{{$t('Dialog.confirm_btn')}}</el-button>
+      </div>
+  </el-dialog>
+</template>
+<script>
+import { departInterence } from "@/api/api.js";
+import { traverseTree } from "@/utils/commonOptions"
+export default {
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    users: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      searchText: '',
+      treeData: [],
+      choosedList: []
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+
+      this.getTreeData()
+    }
+  },
+  methods:{
+    closeDia() {
+      this.choosedList = [];
+      this.searchText = '';
+      this.$emit('update:isShow',false)
+    },
+
+    handleSaveChecked() {
+      if(!this.choosedList) return this.$message.warning('请选择用户')
+
+      this.$emit('save',this.choosedList.map(_ => ({
+        NodeId: _.NodeId,
+        NodeName: _.NodeName
+      })))
+
+      this.closeDia()
+    },
+
+    async getTreeData() {
+      const res = await departInterence.getSystemUser({
+                KeyWord: ''
+      })
+
+      if(res.Ret !== 200) return
+      this.treeData = res.Data||[];
+      //遍历加上唯一的key
+      traverseTree(
+          {Children:this.treeData},
+          {
+              childKey:'Children',
+              nodeKey:'NodeIdKey',
+              cb:(node)=>node.NodeType===3,
+              cb2:(node)=>node.NodeId+''
+          }
+      )
+      
+      this.$nextTick(()=>{
+          const keys = this.users.map(i=>{
+              return i.NodeId
+          })
+          this.$refs["trans-tree"].setCheckedKeys(keys)
+          this.choosedList = _.cloneDeep(this.users)
+      })
+    },
+
+    filterNode(value,data) {
+      if(!value) return true
+
+      return data.NodeName.indexOf(value)!==-1
+    },
+
+    handleCheckChange() {
+      this.choosedList = this.$refs['trans-tree'].getCheckedNodes(true).filter(_ => _.NodeType===3)
+    },
+
+    clearUser() {
+      this.$refs["trans-tree"].setCheckedKeys([])
+      this.choosedList = []
+    },
+
+    //清除已选
+    removeItem(item) {
+      const {NodeIdKey} = item
+      this.$refs["trans-tree"].setChecked(NodeIdKey,false,false)
+      const index = this.choosedList.findIndex(i=>i.NodeIdKey===NodeIdKey)
+      index!==-1&&this.choosedList.splice(index,1)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.dialog-wrap {
+  display: flex;
+  align-items: center;
+  gap:12px;
+    .transfer{
+        display: flex;
+        flex-direction: column;
+        width:254px;
+        height: 400px;
+        border:1px solid #DCDCDC;
+        border-radius: 6px;
+        padding:8px;
+        .head,.search,.content{
+            padding:10px;
+        }
+        .head{
+            display: flex;
+            justify-content: space-between;
+            .btn-text{
+                cursor: pointer;
+                &.delete{
+                    color:red;
+                }
+            }
+        }
+        .content{
+            flex:1;
+            overflow-y: scroll;
+            margin-bottom: 10px;
+            .list-item{
+                cursor: pointer;
+                padding:6px 0;
+                display: flex;
+                justify-content: space-between;
+            }
+        }
+    }
+}
+.dialog-btn{
+    margin:40px 0;
+    text-align: center;
+}
+</style>

+ 195 - 0
src/views/report_manage/reportV2/components/chooseInherReportDia.vue

@@ -0,0 +1,195 @@
+<template>
+  <el-dialog
+    v-dialogDrag
+    :title="$t('ReportManage.ReportList.tit_choose_inher')"
+    width="650px"
+    :visible.sync="isShow"
+    :modal-append-to-body="false"
+    :append-to-body="false"
+    @close="closeDia"
+  >
+      <div class="dialog-wrap">
+        <div style="margin-bottom: 20px;">
+          <el-input
+              @input="filterChange"
+              :placeholder="$t('ReportManage.ReportList.ph_report_tit')"
+              v-model="searchTxt"
+              clearable
+              size="medium"
+              style="width:250px"
+              prefix-icon="el-icon-search"
+          />
+        </div>
+        <el-table
+          :data="reportList"
+          style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2)"
+          border
+          @selection-change="handleSelectionChange"
+        >
+          <el-table-column
+            type="selection"
+            width="55">
+          </el-table-column>
+          <el-table-column
+            v-for="item in tableColums"
+            :key="item.label"
+            :label="item.label"
+            :width="item.widthsty"
+            :min-width="item.minwidthsty"
+            align="center"
+          >
+            <template slot-scope="{row}">
+              <span v-if="item.key==='Title'">
+                <span
+                >{{ row.Title }}</span
+                >
+                <span
+                  v-if="row.MsgSendTime"
+                  >({{ row.MsgSendTime.substring(5, 7)
+                  }}{{ row.MsgSendTime.substring(8, 10) }})</span
+                >
+                <span
+                  v-else-if="row.PublishTime"
+                  >({{ row.PublishTime.substring(5, 7)
+                  }}{{ row.PublishTime.substring(8, 10) }})</span
+                >
+                <span
+                  v-else-if="row.CreateTime"
+                  >({{ row.CreateTime.substring(5, 7)
+                  }}{{ row.CreateTime.substring(8, 10) }})</span
+                >
+              </span>
+
+              <span v-else-if="item.key==='Classify'">
+                {{ row.ClassifyNameFirst }}
+                <span v-if="row.ClassifyNameSecond">/ {{ row.ClassifyNameSecond }}</span>
+                <span v-if="row.ClassifyNameThird">/ {{ row.ClassifyNameThird }}</span>
+              </span>
+
+              <span v-else-if="item.key==='CreateTime'">
+                {{ $moment(row.CreateTime).format('YYYY-MM-DD') }}
+              </span>
+
+              <span v-else>{{ row[item.key] }}</span>
+            </template>
+          </el-table-column>
+          <div slot="empty" style="padding: 30px 0;">
+            <tableNoData text="暂无数据" size="mini"/>
+          </div>
+        </el-table>
+        <div style="margin-top:10px;height:40px;">
+          <m-page 
+              class="table-page"
+              :total="total" 
+              :pageSize="pageSize"
+              :page_no="pageNo"
+              :pagercount="5"
+              @handleCurrentChange="pageNumberChange"
+          />
+
+        </div>
+       
+      </div>
+      <div class="dialog-btn">
+          <el-button type="primary" plain @click="closeDia">{{$t('Dialog.cancel_btn')}}</el-button>
+          <el-button type="primary" @click="handleSave">{{$t('Dialog.confirm_btn')}}</el-button>
+      </div>
+  </el-dialog>
+</template>
+<script>
+import { reportV2Interface } from '@/api/modules/reportV2.js';
+import mPage from '@/components/mPage.vue'
+export default {
+  components: { mPage },
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    id: {
+      type: Number,
+      default: 0
+    }
+  },
+  computed: {
+    tableColums() {
+      return [
+        { label: this.$t('ReportManage.smart_report_title'),key: 'Title' },
+        { label: this.$t('ReportManage.smart_report_type'),key: 'Classify' },
+        { label: '创建时间',key: 'CreateTime' },
+      ]
+    }
+  },
+  data() {
+    return {
+      reportList: [],
+      pageNo: 1,
+      pageSize: 5,
+      total: 0,
+      searchTxt: '',
+      checkList: []
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+    }
+  },
+  methods:{
+    closeDia() {
+      this.reportList = [];
+      this.pageNo = 1;
+      this.total = 0
+      this.searchTxt = '';
+      this.checkList = [];
+
+      this.$emit('update:isShow',false)
+    },
+
+    handleSave() {
+      if(this.checkList.length!==1) return this.$message.warning(/* '只能选择一篇报告' */this.$t('ReportManage.ReportList.check_report_len'))
+
+      this.$emit('success',this.checkList[0])
+      this.closeDia();
+    },
+
+    handleSelectionChange(val) {
+      this.checkList = val;
+    },
+
+    filterChange() {
+      this.pageNo = 1;
+      this.getReportList()
+    },
+
+    pageNumberChange(page) {
+      this.pageNo = page;
+      this.getReportList()
+    },
+
+    getReportList() {
+      reportV2Interface.getAuthReportList({
+          CurrentIndex: this.pageNo,
+          PageSize:this.pageSize,
+          Keyword:this.searchTxt
+        })
+        .then((res) => {
+          if (res.Ret !== 200) return;
+          
+          this.reportList = res.Data.List || [];
+          this.total = res.Data.Paging.Totals;
+        })
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.dialog-wrap {
+
+}
+.dialog-btn{
+    margin:40px 0;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+}
+</style>

+ 585 - 0
src/views/report_manage/reportV2/components/reportBaseInfoDia.vue

@@ -0,0 +1,585 @@
+<template>
+  <div>
+    <el-dialog
+      :title="$t('ReportManage.ReportList.information_title')"
+      :visible.sync="show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="800px"
+      top="5vh"
+      @close="handleClose"
+    >
+      <el-form
+        :model="formData"
+        :rules="rules"
+        ref="baseinfoForm"
+        class="baseinfo-form-wrap"
+        label-width="125px"
+      >
+        <el-form-item prop="type" :label="$t('ReportManage.ReportList.label_add_way')">
+          <el-radio-group
+            v-model="formData.type"
+            :disabled="id"
+            @change="handleUpdateBaseInfo"
+          >
+            <el-radio :label="1">{{
+              $t("ReportManage.ReportList.new_report_radio")
+            }}</el-radio>
+            <el-radio :label="2">{{
+              $t("ReportManage.ReportList.inherit_report_radio")
+            }}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item prop="classify" :label="$t('ReportManage.ReportList.label_report_classify')">
+          <el-cascader
+            ref="cascader"
+            :options="classifyArr"
+            :disabled="id"
+            v-model="formData.classify"
+            :props="{
+              value: 'Id',
+              label: 'ClassifyName',
+              children: 'Child'
+            }"
+            :placeholder="$t('ReportManage.ReportList.please_select_category')"
+            size="medium"
+            style="width: 400px"
+            @change="handleChangeClassify"
+          />
+        </el-form-item>
+
+        <el-form-item prop="relationVariety" :label="$t('ReportManage.ReportList.label_relation_variety')" v-if="formData.relationVariety.length">
+          <div class="permission-wrap">
+            <el-tag v-for="item in formData.relationVariety" :key="item.ChartPermissionId">{{item.PermissionName}}</el-tag>
+          </div>
+        </el-form-item>
+
+        <el-form-item prop="title" :label="$t('ReportManage.ReportList.label_report_tit')">
+          <el-input
+            :placeholder="$t('ReportManage.ReportList.input_title_please')"
+            v-model="formData.title"
+            style="width:400px"
+          >
+            <el-button slot="append" type="primary" v-if="formData.type===2&&!id" @click="isChooseInherReport=true"><!-- 选择继承报告 -->{{$t('ReportManage.ReportList.choose_inherit_report')}}</el-button>
+          </el-input>
+
+        </el-form-item>
+        
+        <el-form-item prop="abstract" :label="$t('ReportManage.ReportList.label_report_abstract')">
+          <el-input
+            type="textarea"
+            :placeholder="$t('ReportManage.ReportList.please_input_abstract')"
+            v-model="formData.abstract"
+            style="width: 400px"
+          ></el-input>
+        </el-form-item>
+
+        <el-form-item prop="author" :label="$t('ReportManage.ReportList.label_report_author')">
+          <el-select
+            v-model="formData.author"
+            multiple
+            :placeholder="$t('ReportManage.ReportList.please_select_author')"
+            size="medium"
+            style="width: 400px"
+          >
+            <el-option
+              v-for="(item, i) in authorlist"
+              :key="i"
+              :label="item.ReportAuthor"
+              :value="item.ReportAuthor"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+
+        <el-form-item prop="time" :label="$t('ReportManage.ReportList.label_createtime')">
+          <el-date-picker
+            v-model="formData.time"
+            type="date"
+            value-format="yyyy-MM-dd"
+            :placeholder="$t('ReportManage.ReportList.please_select_date')"
+            size="medium"
+            :clearable="false"
+            style="width: 400px"
+          ></el-date-picker>
+        </el-form-item>
+
+        <el-form-item prop="cooperationType" :label="$t('ReportManage.ReportList.label_coop')">
+          <el-radio-group
+            v-model="formData.cooperationType"
+            :disabled="id||formData.type===2"
+            @change="formData.cooperationUsers=[]"
+          >
+            <el-radio :label="1"><!-- 个人 -->{{$t('ReportManage.ReportList.coop_own')}}</el-radio>
+            <el-radio :label="2"><!-- 多人协作 -->{{$t('ReportManage.ReportList.coop_more')}}</el-radio>
+          </el-radio-group>
+
+          <el-button 
+            type="text" 
+            v-if="formData.cooperationType===2"
+            style="margin-left: 20px"
+            @click="handleChooseCooper"
+          ><!-- 选择协作人 -->{{$t('ReportManage.ReportList.choose_cooper')}}</el-button>
+          
+          <div class="choosed-cooper" v-if="formData.cooperationUsers.length">
+            <el-tag
+              v-for="(item,index) in formData.cooperationUsers"
+              :key="item.NodeId"
+              size="mini"
+              effect="dark"
+              closable
+              @close="removeCooper(index)"
+            >
+              {{ item.NodeName }}
+            </el-tag>
+          </div>
+        </el-form-item>
+        <el-form-item prop="reportLayout" :label="$t('ReportManage.ReportList.label_report_layout')">
+          <el-radio-group
+            v-model="formData.reportLayout"
+            :disabled="id||formData.type===2"
+          >
+            <el-radio :label="1"><!-- 常规布局 -->{{$t('ReportManage.ReportList.layout_default')}}</el-radio>
+            <el-radio :label="2"><!-- 智能布局 -->{{$t('ReportManage.ReportList.layout_smart')}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item prop="isPublcPublish">
+          <template slot="label">
+            <span><!-- 公开发布 -->{{$t('ReportManage.ReportList.label_public')}}</span>
+            <el-tooltip class="item" effect="dark" placement="top">
+              <div slot="content" v-html="publishTip"></div>
+              <i class="el-icon-info"/>
+            </el-tooltip>
+          </template>
+
+          <el-radio-group
+            v-model="formData.isPublcPublish"
+          >
+            <el-radio :label="1">{{$t('Common.yes_text')}}</el-radio>
+            <el-radio :label="2">{{$t('Common.no_text')}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+      </el-form>
+      <div style="text-align: center; margin-top: 60px; margin-bottom: 40px">
+        <el-button
+          type="primary"
+          plain
+          style="width: 120px"
+          @click="handleClose"
+          >{{ $t("Dialog.cancel_btn") }}</el-button
+        >
+        <el-button type="primary" style="width: 120px" @click="handleConfirm">{{
+          $t("Dialog.confirm_btn")
+        }}</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 选择协作人弹窗 -->
+    <chooseCooperaUserDia
+      :isShow.sync="isChooseCooperaUser"
+      :users="formData.cooperationUsers"
+      @save="getChooseCooperaUser"
+    />
+
+    <!-- 选择继承报告弹窗 -->
+    <chooseInherReportDia
+      :isShow.sync="isChooseInherReport"
+      @success="chooseInheritReport"
+    />
+  </div>
+</template>
+
+<script>
+import { apiSmartReport } from "@/api/modules/smartReport";
+import { reportV2Interface,classifylist,reportadd } from '@/api/modules/reportV2.js';
+import { classifyPermissionInterface } from '@/api/api.js';
+import chooseCooperaUserDia from './chooseCooperaUserDia.vue';
+import chooseInherReportDia from './chooseInherReportDia.vue';
+export default {
+  name: "BaseInfo",
+  components: { chooseCooperaUserDia,chooseInherReportDia },
+  model: {
+    prop: "show",
+    event: "showChange",
+  },
+  props: {
+    show: {
+      type: Boolean,
+      default: false,
+    },
+    id: {
+      type: Number,
+      default: 0,
+    },
+    reportInfo: {
+      type: Object
+    }
+  },
+  watch: {
+    show(n) {
+      if (!n) return
+      
+      this.getclassifylist();
+      this.getreportauthor();
+      
+      if (this.reportInfo) {
+          this.formData = {
+            type: this.reportInfo.AddType,
+            inheritId: 0,
+            classify: this.reportInfo.ClassifyIdThird
+              ? [this.reportInfo.ClassifyIdFirst,this.reportInfo.ClassifyIdSecond,this.reportInfo.ClassifyIdThird]
+              : this.reportInfo.ClassifyIdSecond 
+              ? [this.reportInfo.ClassifyIdFirst,this.reportInfo.ClassifyIdSecond]
+              : [this.reportInfo.ClassifyIdFirst],
+            relationVariety: [],
+            title: this.reportInfo.Title,
+            abstract: this.reportInfo.Abstract,
+            author: this.reportInfo.Author?this.reportInfo.Author.split(","):[],
+            frequency: this.reportInfo.Frequency,
+            time: this.reportInfo.CreateTime,
+            cooperationType: this.reportInfo.CollaborateType,//协作方式
+            cooperationUsers: this.reportInfo.GrandAdminList
+              ? this.reportInfo.GrandAdminList.map(_ => ({
+                  NodeId: _.AdminId,
+                  NodeName: _.AdminName
+                }))
+              : [],
+            reportLayout: this.reportInfo.ReportLayout,//报告布局
+            isPublcPublish: this.reportInfo.IsPublicPublish
+          }
+
+          this.getRelationPermission()
+      }
+    },
+  },
+  data() {
+    return {
+      formData: {
+        type: 1,
+        inheritId: 0,//继承report id
+        classify: [],
+        relationVariety: [],
+        title: "",
+        abstract: "",
+        author: ["投研团队"],
+        frequency: "日度",
+        time: this.$moment().format("YYYY-MM-DD") || "",
+        cooperationType: 1,//协作方式
+        cooperationUsers: [],
+        reportLayout: 1,//报告布局
+        isPublcPublish: 1
+      },
+      publishTip: `若选择是,则发布后所有人可见;<br>
+        若选择否,则发布后,仅创建人和审批人可见;`,
+
+      classifyArr: [],
+      authorlist: [],
+
+      //协作人弹窗
+      isChooseCooperaUser: false,
+
+      //继承报告弹窗
+      isChooseInherReport:false
+    };
+  },
+  computed: {
+    rules() {
+      return {
+        type: [
+          {
+            required: true,
+            message: this.$t("ReportManage.ReportList.please_report_type_select"),
+            trigger: "change",
+          },
+        ],
+        classify: [
+          {
+            required: true,
+            message: this.$t("ReportManage.ReportList.please_report_type_select"),
+            trigger: "change",
+          },
+        ],
+        title: [
+          {
+            required: true,
+            message: this.$t("ReportManage.ReportList.please_report_title_input"),
+            trigger: "blur",
+          },
+        ],
+      };
+    },
+  },
+  methods: {
+    handleClose() {
+      this.formData = {
+        type: 1,
+        inheritId: 0,
+        classify: [],
+        relationVariety: [],
+        title: "",
+        abstract: "",
+        author: ["投研团队"],
+        frequency: "日度",
+        time: this.$moment().format("YYYY-MM-DD") || "",
+        cooperationType: 1,//协作方式
+        cooperationUsers: [],
+        reportLayout: 1,//报告布局
+        isPublcPublish: 1
+      }
+
+      this.$emit("showChange", false);
+    },
+
+    async handleConfirm() {
+      await this.$refs.baseinfoForm.validate()
+
+      const params = {
+        AddType: this.formData.type,
+        ClassifyIdFirst: this.formData.classify[0]
+          ? this.formData.classify[0]
+          : 0,
+        ClassifyNameFirst: "",
+        ClassifyIdSecond: this.formData.classify[1]
+          ? this.formData.classify[1]
+          : 0,
+        ClassifyNameSecond: "",
+        ClassifyIdThird: this.formData.classify[2]
+          ? this.formData.classify[2]
+          : 0,
+        ClassifyNameThird: "",
+        Title: this.formData.title,
+        Abstract: this.formData.abstract,
+        Author:
+          this.formData.author.length > 0
+            ? this.formData.author.join(",")
+            : "",
+        CreateTime: this.formData.time,
+        ReportLayout: this.formData.reportLayout,
+        CollaborateType: this.formData.cooperationType,
+        IsPublicPublish: this.formData.isPublcPublish,
+        InheritReportId: this.formData.inheritId,
+        GrantAdminIdList: this.formData.cooperationUsers.map(_ => _.NodeId)
+      };
+
+      this.classifyArr.forEach((item) => {
+        if (item.value === params.ClassifyIdFirst) {
+          params.ClassifyNameFirst = item.label;
+          const arr = item.children || [];
+          arr.forEach((_item) => {
+            if (_item.value === params.ClassifyIdSecond) {
+              params.ClassifyNameSecond = _item.label;
+              _item.children && _item.children.forEach(last_item => {
+                if (last_item.value === params.ClassifyIdThird) {
+                  params.ClassifyNameThird = last_item.label
+                }
+              })
+            }
+          });
+        }
+      });
+      // 编辑
+      if (this.id) {
+        this.$emit("save", params);
+        return;
+      }
+      reportadd(params).then((res) => {
+        if (res.Ret === 200) {
+
+          let { href } = this.$router.resolve({
+            path: this.formData.reportLayout===1 
+              ? '/reportEditV2'
+              : "/smpartReportEditV2",
+            query: { 
+              id: res.Data.ReportId,
+              coopType: params.CollaborateType
+            },
+          });
+          window.open(href, "_blank");
+
+          this.handleClose();
+        }
+      });
+    },
+
+
+    //分类变化 获取关联品种 
+    handleChangeClassify(val) {
+      this.getRelationPermission()
+      this.handleUpdateBaseInfo()
+    },
+
+    handleUpdateBaseInfo() {
+      this.formData.inheritId = 0;
+
+      if (this.formData.type === 1) {
+        if (this.formData.classify.length === 2) {
+          this.formData.title = this.getSelectClassifyName()[1];
+        }
+        return;
+      }
+      if(!this.formData.classify.length&&this.formData.type===2) return
+
+      
+      //获取上次报告
+      reportV2Interface
+        .getAuthReportList({
+          ClassifyIdFirst: this.formData.classify[0],
+          ClassifyIdSecond: this.formData.classify[1],
+          ClassifyIdThird: this.formData.classify[3],
+          CurrentIndex: 1,
+          PageSize:1,
+          Keyword:''
+        }).then((res) => {
+          if (res.Ret !== 200) return;
+          if (!res.Data.List) {
+            this.$message.warning(
+              this.$t("ReportManage.ReportList.no_reports_msg")
+            );
+            return false;
+          }
+
+          this.chooseInheritReport(res.Data.List[0])
+        });
+    },
+
+    /* 选择继承报告 */
+    async chooseInheritReport(item) {
+      const { Id,Title,Abstract,Author,CollaborateType,ReportLayout,IsPublicPublish,ClassifyIdFirst,ClassifyIdSecond,ClassifyIdThird } = item;
+
+      this.formData.title = Title;
+      this.formData.abstract = Abstract;
+      this.formData.author = Author
+        ? Author.split(",")
+        : "";
+      this.formData.cooperationType = CollaborateType;
+      this.formData.inheritId = Id;
+      this.formData.reportLayout = ReportLayout;
+      this.formData.isPublcPublish = IsPublicPublish;
+      this.formData.classify = ClassifyIdThird
+        ? [ClassifyIdFirst,ClassifyIdSecond,ClassifyIdThird]
+        : ClassifyIdSecond 
+        ? [ClassifyIdFirst,ClassifyIdSecond]
+        : [ClassifyIdFirst]
+      
+      //继承的章节报告默认带出协作人
+      if(CollaborateType===1) {
+        this.formData.cooperationUsers = [];
+      }else {
+        const res = await reportV2Interface.getRportBase({
+          ReportId: Id
+        })
+        if(res.Ret!==200) return
+        
+        this.formData.cooperationUsers = res.Data.GrandAdminList
+          ? res.Data.GrandAdminList.map(_ => ({
+              NodeId: _.AdminId,
+              NodeName: _.AdminName
+            }))
+          : [];
+      }
+    },
+
+    //选择协作人
+    handleChooseCooper() {
+      this.isChooseCooperaUser = true
+    },
+
+    getChooseCooperaUser(val) {
+      this.formData.cooperationUsers = val;
+    },
+
+    removeCooper(index) {
+      this.formData.cooperationUsers.splice(index,1)
+    },
+
+    //获取关联品种
+    async getRelationPermission() {
+      if(!this.formData.classify.length) return
+
+      const res = await classifyPermissionInterface.classifyPermissionList({ClassifyId:this.formData.classify[this.formData.classify.length-1]})
+
+        if(res.Ret!==200) return
+        this.formData.relationVariety = res.Data || []
+    },
+
+    // 获取选择的分类名称
+    getSelectClassifyName() {
+      let arr = [];
+      this.classifyArr.forEach((item) => {
+        if (
+          this.formData.classify[0] &&
+          item.value === this.formData.classify[0]
+        ) {
+          arr.push(item.label);
+          if (item.children && item.children.length > 0) {
+            item.children.forEach((_item) => {
+              if (
+                this.formData.classify[1] &&
+                _item.value === this.formData.classify[1]
+              ) {
+                arr.push(_item.label);
+              }
+            });
+          }
+        }
+      });
+      return arr;
+    },
+
+    // 获取分类
+    getclassifylist() {
+      //获取分类列表
+      let params = { CurrentIndex: 0, PageSize: 1000, KeyWord: "" };
+
+      classifylist(params).then((res) => {
+        if (res.Ret == 200 && Array.isArray(res.Data.List)) {
+          this.classifyArr = res.Data.List||[];
+        }
+      });
+    },
+    // 获取作者
+    getreportauthor() {
+      apiSmartReport.reportAuthor({}).then((res) => {
+        if (res.Ret == 200) {
+          this.authorlist = res.Data.List || [];
+        }
+      });
+    },
+  },
+  mounted() {
+  },
+};
+</script>
+
+<style lang="scss">
+.baseinfo-form-wrap {
+  width: 85%;
+  margin: 0 auto;
+  .el-input {
+    width: 100%;
+  }
+  .el-input-group__append {
+    background-color: #0052D9;
+    color: #fff;
+  }
+  .el-form-item {
+    margin-left: auto;
+    margin-right: auto;
+  }
+  .choosed-cooper {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 10px;
+  }
+  .permission-wrap {
+    width: 80%;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 5px;
+  }
+}
+</style>

+ 167 - 0
src/views/report_manage/reportV2/components/reportEditHeader.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="top-action-wrap">
+    <template>
+      <el-input 
+        v-if="reportInfo&&reportInfo.ReportChapterId" 
+        v-model="reportInfo.Title"
+        style="width:240px;"
+        :placeholder="$t('ReportManage.ReportList.label_chap_name')"
+        @change="handleUpdateTitle"
+      ></el-input>
+      
+      <div v-else class="title text_oneLine">{{reportInfo&&reportInfo.Title}}</div>
+    </template>
+    
+      <ul class="action-list">
+          <li 
+            class="action-item" 
+            @click="$emit('handleClearContent')"
+            v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_clearCont)"
+            >
+              <img src="~@/assets/img/smartReport/icon01.png" alt="">
+              <span><!-- 一键清空内容 -->{{$t('ReportManage.ReportList.click_clear_btn')}}</span>
+          </li>
+          <li v-if="!reportInfo.ReportChapterId" class="action-item" @click="$emit('openBaseInfo')">
+              <img src="~@/assets/img/smartReport/icon01.png" alt="">
+              <span>{{$t('ReportManage.ReportList.information_title')}}</span>
+          </li>
+          <li class="action-item" @click="$emit('handleRefreshAllChart')">
+              <img src="~@/assets/img/smartReport/icon02.png" alt="">
+              <span><!-- 一键刷新 -->{{$t('ReportManage.ReportList.click_refresh_btn')}}</span>
+          </li>
+          <li class="action-item" @click="$emit('handlePreviewReport')">
+              <img src="~@/assets/img/smartReport/icon03.png" alt="">
+              <span>{{$t('ReportManage.ReportList.preview_btn')}}</span>
+          </li>
+          <li class="action-item" @click="$emit('handleSaveContent')">
+              <img src="~@/assets/img/smartReport/icon01.png" alt="">
+              <span>{{$t('ReportManage.ReportList.save_draft_btn')}}</span>
+          </li>
+        
+        <!-- 章节报告,只有提交 提交即是发布 -->
+        <template v-if="reportInfo&&reportInfo.ReportChapterId">
+            <li 
+                class="action-item" 
+                :class="{'disabled':checkLoading}"
+                @click="$emit('handlePublishOpt')"
+            >
+                <img src="~@/assets/img/smartReport/icon01.png" alt="">
+                <span>{{$t('ReportManage.ReportList.submit_chapter_btn')}}</span>
+            </li>
+        </template>
+
+        <!-- 单人报告 -->
+        <template v-else>
+            <template v-if="!isApprove||!hasApproveFlow">
+                <li 
+                    class="action-item" 
+                    :class="{'disabled':checkLoading}"
+                    @click="$emit('handlePublishOpt','dsfb')"
+                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+                    >
+                    <img src="~@/assets/img/smartReport/icon01.png" alt="">
+                    <span>{{$t('ReportManage.ReportList.scheduled_publish_btn')}}</span>
+                </li>
+                <li 
+                    class="action-item" 
+                    :class="{'disabled':checkLoading}"
+                    @click="$emit('handlePublishOpt','fb')"
+                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+                >
+                    <img src="~@/assets/img/smartReport/icon01.png" alt="">
+                    <span>{{$t('ReportManage.ReportList.publish_btn')}}</span>
+                </li>
+            </template>
+            <template v-if="isApprove&&hasApproveFlow">
+                <li 
+                    class="action-item" 
+                    :class="{'disabled':checkLoading}"
+                    @click="$emit('handlePublishOpt','submit')"
+                    v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_publish)"
+                >
+                    <img src="~@/assets/img/smartReport/icon01.png" alt="">
+                    <span>{{$t('ReportManage.ReportList.submission_btn')}}</span>
+                </li>
+            </template>
+        </template>
+
+          
+      </ul>
+  </div>
+</template>
+<script>
+import {
+	reportV2Interface
+} from '@/api/modules/reportV2';
+export default {
+  props: {
+    reportInfo: {
+        type: Object
+    },
+    isApprove: {
+        type: Boolean
+    },
+    hasApproveFlow: {
+        type: Boolean
+    }
+  },
+  methods:{
+    async handleUpdateTitle() {
+      let res = await reportV2Interface.saveChapterTitle({
+        ReportChapterId: this.reportInfo.ReportChapterId,
+        Title: this.reportInfo.Title
+      })
+      if(res.Ret !== 200) return
+      this.$emit('update')
+    }
+  },
+  mounted() {
+  }
+}
+</script>
+<style scoped lang='scss'>
+.top-action-wrap{
+    position: sticky;
+    top: 0px;
+    background-color: #fff;
+    box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.10);
+    height: 60px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 0 24px;
+    .title{
+        line-height: 60px;
+        font-size: 16px;
+    }
+    .action-list{
+        display: flex;
+        align-items: center;
+        flex-shrink: 0;
+        .action-item{
+            height: 36px;
+            display: flex;
+            align-items: center;
+            border-right: 1px solid #C8CDD9;
+            padding: 0 30px;
+            font-size: 16px;
+            cursor: pointer;
+            img{
+                width: 16px;
+                height: 16px;
+                margin-right: 4px;
+                position: relative;
+                top: 2px;
+            }
+            &:last-child{
+                border-right: none;
+            }
+            &.disabled{
+                pointer-events: none;
+                cursor: not-allowed;
+                color:#999;
+            }
+        }
+    }
+}
+</style>

+ 168 - 0
src/views/report_manage/reportV2/components/reportPreview.vue

@@ -0,0 +1,168 @@
+<template>
+  <el-drawer
+    :visible.sync="show"
+    :modal-append-to-body="false"
+    direction="rtl"
+    @close="handleClose"
+    :show-close="false"
+    size="70%"
+    custom-class="reportPreivew-drawer"
+  > 
+    <template slot="title">
+      <div class="header">
+        <span>报告预览</span>
+        <i class="el-icon-close" @click="handleClose"></i>
+      </div>
+    </template>
+
+    <div style="max-width:1200px; margin:10px auto 70px;" v-loading="isLoading" element-loading-text="研报加载中...">
+      <component
+        v-if="show"
+        :is="reportIdInfo.ReportLayout===1?'reportDetail':'smartReportDetail'"
+        :reportId="reportIdInfo.Id"
+        @reportStartLoading="loading=true"
+        @reportEndLoading="loading=false"
+      />
+    </div>
+
+    <ul class="fixed-handles">
+        <li v-permission="permissionBtn.reportManageBtn.reportManage_reportView_copyWechat" :data-clipboard-text='linkUrl' @click="copyHandle" class="copy">
+            <el-button type="text"><!-- 复制链接 -->{{$t('ReportManage.ReportList.copy_share_link')}}</el-button>
+        </li>
+        <li v-permission="permissionBtn.reportManageBtn.reportManage_reportView_wechartShare" @mouseenter="isShowCode=true" @mouseleave="isShowCode=false" style="position:relative">
+            <el-button type="text"><!-- 微信分享 -->{{$t('ReportManage.ReportList.weChat_share')}}</el-button>
+
+          <vue-qr :text="linkUrl" :margin="0" colorDark="#333" colorLight="#fff" :dotScale="1" :size="100" style="position:absolute;left:-20px;top:-120px;" v-if="isShowCode"></vue-qr>
+        </li>
+        <li v-if="showDownPDF">
+            <el-button type="text" @click="$emit('itemclick',{type:'下载Pdf',data: reportIdInfo})"><!-- 下载PDF -->{{$t('ReportManage.smart_btn.download_pdf')}}</el-button>
+        </li>
+        <li v-if="showDowmImg">
+            <el-button type="text" @click="$emit('itemclick',{type:'下载长图',data: reportIdInfo})"><!-- 下载长图 -->{{$t('ReportManage.smart_btn.download_long_image')}}</el-button>
+        </li>
+
+    </ul>
+
+  </el-drawer>
+</template>
+<script>
+import { reportdetail,departInterence } from 'api/api.js';
+import http from '@/api/http.js';
+import vueQr from 'vue-qr'
+import reportDetail from '../normalReport/reportdtl.vue';
+import smartReportDetail from '../smartReport/reportDetail.vue';
+export default {
+  props: {
+    show: {
+      type: Boolean
+    },
+    reportIdInfo: {
+      type: Object
+    }
+  },
+  components: { reportDetail,smartReportDetail,vueQr },
+  computed: {
+    linkUrl(){
+      let str=''
+      const baseUrl= localStorage.getItem('dynamicOutLinks') ? JSON.parse(localStorage.getItem('dynamicOutLinks')).ReportViewUrl : '';
+      if(this.reportIdInfo.ReportCode){
+        // 设置水印文案
+        let waterMarkStr= localStorage.getItem('waterMarkStr');
+
+        str= this.reportIdInfo.ReportLayout===1 
+          ? `${baseUrl}/reportshare_crm_report?code=${this.reportIdInfo.ReportCode}&flag=${waterMarkStr}`
+          : `${baseUrl}/reportshare_smart_report?code=${this.reportIdInfo.ReportCode}`
+      }
+      
+      return str
+    },
+
+    showDownPDF() {
+      return [2,6].includes(this.reportIdInfo.State) && this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportPdf') && this.reportIdInfo.DetailPdfUrl
+    },
+
+    showDowmImg() {
+       return [2,6].includes(this.reportIdInfo.State) && this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportImg') && this.reportIdInfo.DetailImgUrl
+    }
+  },
+  watch: {
+    show(nval) {
+      if(!nval) return
+
+    }
+  },
+  data() {
+    return {
+      reportInfo:{},
+    
+      handlesOpt: [
+        { key:'copyLink',label:'复制链接' },
+        { key:'wxShare',label:'微信分享' },
+        { key:'downPdf',label:'下载PDF' },
+        { key:'downPic',label:'下载长图' },
+      ],
+      loading: false,
+
+      isShowCode: false
+    }
+  },
+  methods:{
+    handleClose() {
+      $('.el-drawer__body')[0].scrollTop = 0
+      this.$emit('update:show',false)
+    },
+
+    /* 复制链接 */
+    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()
+      })
+    }
+  },
+}
+</script>
+<style lang="scss">
+  .reportPreivew-drawer {
+    .el-drawer__header {
+      margin-bottom: 0;
+      padding-bottom: 20px;
+      border-bottom: 1px solid #ccc;
+    }
+    
+    .el-drawer__body {
+      position: relative;
+      overflow-y: auto;
+    }
+  }
+</style>
+<style scoped lang='scss'>
+.header {
+  display: flex;
+  justify-content: space-between;
+  font-size: 16px;
+  color: #333;
+}
+
+
+  .fixed-handles {
+    width: 100%;
+    height: 60px;
+    padding: 0 15px;
+    position: fixed;
+    bottom: 0;
+    background: #fff;
+    border-top: 1px solid #ccc;
+    display: flex;
+    align-items: center;
+    gap: 40px;
+  }
+</style>

+ 178 - 0
src/views/report_manage/reportV2/components/smartTerritorSetDia.vue

@@ -0,0 +1,178 @@
+<template>
+  <el-dialog
+    v-dialogDrag
+    :title="$t('ReportManage.ReportList.img_set_btn')"
+    width="900px"
+    :visible.sync="isShow"
+    :modal-append-to-body="false"
+    :close-on-click-modal="false"
+    :append-to-body="false"
+    @close="closeDia"
+  >
+    <div class="main">
+      <ul class="set-ul">
+        <li>
+          <label class="el-form-item__label"><!-- 版图设置 -->{{$t('ReportManage.ReportList.img_set_btn')}}</label>
+          <div class="img-cont">
+
+            <div class="cont-item">
+              <img class="add-cont" :src="layoutInfo.headImg" alt="" v-if="layoutInfo.headImg">
+              <div class="add-cont" v-else @click="defaultType=1;isOpenChooseImg=true">+{{$t('ReportManage.ReportList.choose_head_img')}}<!-- 选择版头 --></div>
+              <i class="el-icon-delete" v-if="layoutInfo.headImg"  @click="layoutInfo.headImg='';layoutInfo.headImgId=0;"></i>
+            </div>
+
+            <div class="cont-item">
+              <img class="add-cont" :src="layoutInfo.endImg" alt="" v-if="layoutInfo.endImg">
+              <div class="add-cont" v-else @click="defaultType=2;isOpenChooseImg=true">+{{$t('ReportManage.ReportList.choose_end_img')}}<!-- 选择版尾 --></div>
+              <i class="el-icon-delete" v-if="layoutInfo.endImg" @click="layoutInfo.endImg='';layoutInfo.endImgId=0;"></i>
+            </div>
+
+          </div>
+        </li>
+
+        <li>
+          <label class="el-form-item__label"><!-- 画布设置 -->{{$t('ReportManage.ReportList.canvas_set')}}</label>
+          <el-color-picker v-model="layoutInfo.bgColor"></el-color-picker>
+        </li>
+
+      </ul>
+    </div>
+
+    <div class="dialog-btn">
+        <el-button type="primary" plain @click="closeDia">{{$t('Dialog.cancel_btn')}}</el-button>
+        <el-button type="primary" @click="handleSaveSet">{{$t('Dialog.confirm_btn')}}</el-button>
+    </div>
+
+
+    <!-- 选择版图弹窗 -->
+    <m-dialog
+      :show.sync="isOpenChooseImg"
+      :title="'选择版图'"
+      width="900px"
+    >
+      <div class="main">
+        <imgSource
+          :inDialog="true"
+          :defaultType="defaultType"
+          @close="isOpenChooseImg=false"
+          @change="handleGetImg"
+        />
+      </div>
+    </m-dialog>
+  </el-dialog>
+</template>
+<script>
+import mDialog from '@/components/mDialog.vue';
+import imgSource from '../smartReport/components/ImgSource.vue'
+export default {
+  components: { mDialog,imgSource },
+  props: {
+    isShow: {
+      type: Boolean
+    },
+    info: {
+      type:Object
+    }
+  },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+
+      this.layoutInfo = {
+        bgColor: this.info.CanvasColor||'',
+        headImg:this.info.HeadImg||'',
+        endImg: this.info.EndImg||'',
+        headImgId: this.info.HeadResourceId||0,
+        endImgId: this.info.EndResourceId||0,
+      }
+    }
+  },
+  data() {
+    return {
+      layoutInfo: {
+        bgColor: '',
+        headImg:'',//版头图片
+        endImg: '',//版尾图片
+        headImgId: 0,//版头Id
+        endImgId: 0,//版尾Id
+      },
+      
+      defaultType: 1,
+      isOpenChooseImg: false,
+    }
+  },
+  mounted(){
+
+  },
+  methods:{
+    closeDia() {
+      this.$emit('update:isShow',false)
+    },
+
+    /* 保存设置 */
+    handleSaveSet() {
+      this.$emit('change',this.layoutInfo)
+      this.closeDia()
+    },
+    
+    handleGetImg({type,data}) {
+      this.isOpenChooseImg = false;
+      if(type === 1) {
+        this.layoutInfo.headImgId = data.ResourceId;
+        this.layoutInfo.headImg = data.ImgUrl;
+      } else {
+        this.layoutInfo.endImgId = data.ResourceId;
+        this.layoutInfo.endImg = data.ImgUrl;
+      }
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.main {
+  .set-ul {
+    li {
+      display: flex;
+      margin: 20px 0;
+      .img-cont {
+        width: 80%;
+        height: 300px;
+        background: rgba($color: #000000, $alpha: 0.05);
+        display: flex;
+        justify-content: center;
+        flex-wrap: wrap;
+        align-items: center;
+        .cont-item  {
+          width: 90%;
+          height: 35%;
+          position: relative;
+          .add-cont {
+            width: 100%;
+            height: 100%;
+            object-fit: fill !important;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            background: rgba($color: #000000, $alpha: 0.1);
+          }
+          .el-icon-delete {
+            font-size: 20px;
+            position: absolute;
+            top: 10px;
+            right: 10px;
+            z-index: 2;
+            cursor: pointer;
+            color: #ededed;
+          }
+        }
+      }
+    }
+  }
+}.dialog-btn  {
+  margin:30px 0;
+  text-align: center;
+  .el-button {
+    width: 120px;
+  }
+}
+</style>

+ 1218 - 0
src/views/report_manage/reportV2/list.vue

@@ -0,0 +1,1218 @@
+//研报模块整合 智能研报,研报合并
+<template>
+  <div class="reportV2-list">
+     <el-card class="box-card">
+      <div slot="header" class="header">
+            <el-button
+              v-permission="permissionBtn.reportManageBtn.reportManage_reportAdd"
+              type="primary"
+              size="medium"
+              @click="showAddReport=true"
+              >{{$t('ReportManage.smart_add_report')}}</el-button
+            >
+
+            <el-input
+              @input="filterChange"
+              :placeholder="$t('ReportManage.smart_title_creator_btn')"
+              v-model="searchform.key_word"
+              clearable
+              size="medium"
+              style="width:250px"
+              prefix-icon="el-icon-search"
+            />
+      </div>
+      <template>
+        <div class="filter-cont">
+          <el-form :inline="true" :model="searchform" @submit.native.prevent style="display:flex;">
+            <!-- 整合的筛选项 -->
+            <el-form-item label="">
+              
+              <div class="select-wrap">
+                  <div class="select-item">
+                      <el-cascader
+                          @change="filterChange"
+                          :options="classifyOptions"
+                          v-model="searchform.classifyIds"
+                          :props="{
+                            value: 'Id',
+                            label: 'ClassifyName',
+                            children: 'Child'
+                          }"
+                          clearable
+                          :placeholder="$t('ReportManage.smart_type_filtering')"
+                          style="width:100%;"
+                      ></el-cascader>
+                  </div>
+
+                  <div class="select-item">
+                      <el-select
+                          v-model.number="searchform.publishState"
+                          :placeholder="$t('ReportManage.smart_status_filtering')"
+                          size="medium"
+                          clearable
+                          style="width:100%;"
+                          @change="filterChange"
+                      >
+                        <el-option :label="$t('ReportManage.smart_unpublished')" :value="1" v-if="!isOtherApprove"></el-option>
+                          <el-option :label="$t('ReportManage.smart_published')" :value="2"></el-option>
+                          <el-option :label="$t('ReportManage.smart_pending')" :value="3" v-if="isApprove"></el-option>
+                          <el-option :label="$t('ReportManage.smart_awaiting_approval')" :value="4" v-if="isApprove"></el-option>
+                          <el-option :label="$t('ReportManage.smart_rejected')" :value="5"></el-option>
+                          <el-option :label="$t('ReportManage.smart_approved')" :value="6"></el-option>
+                        </el-select>
+                  </div>
+                
+                  <div class="select-item">
+                    <el-select
+                        v-model="searchform.timeType"
+                        :placeholder="$t('ReportManage.smart_select_time_type_btn')"
+                        size="medium"
+                        style="width:150px;"
+                        @change="filterChange"
+                    >
+                        <el-option :label="$t('ReportManage.smart_publish_time')" value="publish_time"></el-option>
+                        <el-option :label="$t('ReportManage.smart_approval_time')" value="approve_time"></el-option>
+                        <el-option :label="$t('ReportManage.smart_update_time')" value="modify_time"></el-option>
+                    </el-select>
+                    <el-date-picker
+                      @change="filterChange"
+                      v-model="searchform.dateValue"
+                      type="daterange"
+                      unlink-panels
+                      value-format="yyyy-MM-dd"
+                      :range-separator="$t('Common.to')"
+                      :start-placeholder="$t('Common.ph_time_start')"
+                      :end-placeholder="$t('Common.ph_time_end')"
+                      size="medium"
+                      style="width: 280px"
+                    ></el-date-picker>
+                  </div>
+                  <div class="select-item">
+                      <el-select
+                          v-permission="permissionBtn.reportManageBtn.reportManage_reportList_sendTime"
+                          @change="filterChange"
+                          v-model.number="searchform.msgIsSend"
+                          :placeholder="$t('ReportManage.smart_notification_status_btn')"
+                          size="medium"
+                          clearable
+                          style="width:100%;"
+                      >
+                          <el-option :label="$t('ReportManage.smart_notification_yet_pushed')" :value="1"></el-option>
+                          <el-option :label="$t('ReportManage.smart_notification_pushed')" :value="2"></el-option>
+                      </el-select>
+                  </div>
+              </div>
+
+            </el-form-item>
+          </el-form>
+          
+          <el-radio-group 
+            v-model="searchform.listType" 
+            @input="filterChange"
+            class="report-types-cont"
+          >
+            <el-radio-button 
+              :label="item.key"  
+              v-for="item in reportTypes"
+              :key="item.key" 
+            >{{item.label}}</el-radio-button>
+          </el-radio-group>
+        </div>
+        
+        <el-table
+          ref="table"
+          :data="tableData"
+          v-loading="listLoading"
+          @sort-change="sortChange"
+          :element-loading-text="$t('Table.data_loading')" 
+          border
+          style="width: 100%"
+        >
+          <el-table-column
+            prop="Title"
+            :label="$t('ReportManage.smart_report_title')"
+            align="center"
+            min-width="140"
+            fixed="left"
+          >
+            <template slot-scope="scope">
+              <div @click="lookreportdtl(scope.row)">
+                <span
+                  style="cursor: pointer; color: #4099ef"
+                >{{ scope.row.Title }}</span
+                >
+                <span
+                  style="cursor: pointer; color: #4099ef"
+                  v-if="scope.row.MsgSendTime"
+                  >({{ scope.row.MsgSendTime.substring(5, 7)
+                  }}{{ scope.row.MsgSendTime.substring(8, 10) }})</span
+                >
+                <span
+                  style="cursor: pointer; color: #4099ef"
+                  v-else-if="scope.row.PublishTime"
+                  >({{ scope.row.PublishTime.substring(5, 7)
+                  }}{{ scope.row.PublishTime.substring(8, 10) }})</span
+                >
+                <span
+                  style="cursor: pointer; color: #4099ef"
+                  v-else-if="scope.row.CreateTime"
+                  >({{ scope.row.CreateTime.substring(5, 7)
+                  }}{{ scope.row.CreateTime.substring(8, 10) }})</span
+                >
+
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="Abstract"
+            :label="$t('ReportManage.smart_abstract_table')"
+            align="center"
+            min-width="140"
+            fixed="left"
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column :label="$t('ReportManage.smart_report_type')" align="center" min-width="140">
+            <template slot-scope="scope">
+              {{ scope.row.ClassifyNameFirst }}
+              <span v-if="scope.row.ClassifyNameSecond">/ {{ scope.row.ClassifyNameSecond }}</span>
+              <span v-if="scope.row.ClassifyNameThird">/ {{ scope.row.ClassifyNameThird }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="AdminRealName"
+            :label="$t('ReportManage.smart_creator_btn')"
+            align="center"
+            min-width="100"
+          ></el-table-column>
+          <el-table-column
+            prop="LastModifyAdminName"
+            :label="$t('ReportManage.table_col02')"
+            align="center"
+            min-width="100"
+          ></el-table-column>
+          <el-table-column :label="$t('ReportManage.smart_status_table')" align="center" v-if="isApprove">
+            <template slot-scope="scope">
+                <span v-if="scope.row.State == '1'">{{$t('ReportManage.smart_unpublished')}}</span>
+                <span v-if="scope.row.State == '2'">{{$t('ReportManage.smart_published')}}</span>
+                <span v-if="scope.row.State == '3'">{{$t('ReportManage.smart_pending')}}</span>
+                <span v-if="scope.row.State == '4'">{{$t('ReportManage.smart_awaiting_approval')}}</span>
+                <span v-if="scope.row.State == '5'">{{$t('ReportManage.smart_rejected')}}</span>
+                <span v-if="scope.row.State == '6'">{{$t('ReportManage.smart_approved')}}</span>
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="PublishTime" :label="$t('ReportManage.smart_release_approval_time')" min-width="124" align="center">
+            <template slot-scope="scope">
+                <template v-if="[1,2].includes(scope.row.State)">
+                    <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+                    <svg style="position: relative;top:2px" v-if="scope.row.PrePublishTime&&scope.row.State == '1'" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                        <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+                    </svg>
+                </template>
+                <template v-else>
+                    <span>{{scope.row.ApproveTime|formatTime}}</span>
+                </template>
+            </template>
+          </el-table-column>
+
+          <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_reportList_sendTime)"
+            prop="MsgSendTime"
+            :label="$t('ReportManage.smart_report_push_time_btn')"
+            min-width="124"
+            align="center"
+          >
+            <template slot-scope="scope">{{
+              scope.row.MsgSendTime | formatTime
+            }}</template>
+          </el-table-column>
+          <el-table-column
+            prop="ModifyTime"
+            :label="$t('ReportManage.smart_update_time')"
+            min-width="124"
+            align="center"
+            :formatter="formatterColumn"
+          ></el-table-column>
+          <el-table-column :label="$t('ReportManage.smart_issue_number_btn')" align="center">
+            <template slot-scope="scope">第{{ scope.row.Stage }}期</template>
+          </el-table-column>
+          <el-table-column
+            :label="hasUV?'PV / UV':'PV'"
+            align="center"
+            :render-header="renderHeader"
+            width="140"
+          >
+            <template slot-scope="scope"
+              >{{ hasUV? scope.row.Pv+'/'+scope.row.Uv:scope.row.Pv }}</template
+            >
+          </el-table-column>
+          <el-table-column :label="$t('Table.column_operations')" align="center" min-width="130" fixed="right">
+            <!-- 操作 -->
+            <template slot-scope="scope">
+              <div class="opt-btns">
+                
+                <!-- 前面的按钮 -->
+                <span 
+                  v-for="bu in getbuttonList(scope.row,'f')" 
+                  :key="bu.label" 
+                  :class="['删除'].includes(bu.label)?'deletesty':'editsty'"
+                  :style="{
+                    color:['撤销','取消发布','已推送消息'].includes(bu.label)?'red':
+                          ['音频上传'].includes(bu.label)?'#46c371':'',
+                    cursor:['已推送消息'].includes(bu.label)?'text':''
+                  }"
+                  @click.stop="itemclickHandle({type:bu.label,data:scope.row})"
+                >
+                  <template v-if="bu.label==='编辑中'">{{ scope.row.Editor || "" }}{{$t(bu.text)}}</template>
+
+                  <template v-else-if="['撤销','取消发布'].includes(bu.label)">{{scope.row.HasAuth?$t(bu.text):''}}</template>
+
+                  <a :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)" v-else-if="bu.label=='音频下载A'" 
+                    :download="scope.row.VideoName" style="cursor: pointer; color: #4099ef">{{$t('ReportManage.smart_audio_download_btn')}}</a>
+
+                  <template v-else>{{$t(bu.text)}}</template>
+                </span>
+                <!-- 后面的按钮 -->
+                <el-dropdown size="medium" placement="bottom-start" @command="itemclickHandle"
+                v-if="getbuttonList(scope.row,'b').length" style="height: 16px;">
+                  <span class="el-dropdown-link">
+                    <i class="el-icon-more el-icon--right"></i>
+                    <el-dropdown-menu slot="dropdown">
+                      <el-dropdown-item :command="{type:bu.label,data:scope.row}" 
+                      v-for="bu in getbuttonList(scope.row,'b')" :key="bu.label">
+                        <a :href="hostapi + '?ReportId=' + parseInt(scope.row.Id)" v-if="bu.label=='音频下载A'" 
+                        :download="scope.row.VideoName" style="cursor: pointer; color: #4099ef">{{$t('ReportManage.smart_audio_download_btn')}}</a>
+                        <span :class="['删除','撤销','取消发布'].includes(bu.label)?'deletesty':'editsty'" v-else
+                        :style="{
+                          color:['撤销','取消发布','已推送消息'].includes(bu.label)?'red':
+                                ['音频上传'].includes(bu.label)?'#46c371':'',
+                          cursor:['已推送消息'].includes(bu.label)?'text':''
+                        }">
+                          {{$t(bu.text)}}
+                        </span>
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </span>
+                </el-dropdown>
+              </div>
+            </template>
+          </el-table-column>
+          <template slot="empty">
+            <tableNoData text="暂无数据"/>
+          </template>
+        </el-table>
+
+      </template>
+      
+      <el-col :span="24" class="toolbar">
+        <el-pagination
+          layout="total,prev,pager,next,jumper"
+          background
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          :total="total"
+          style="float: right"
+        ></el-pagination>
+      </el-col>
+    </el-card>
+
+    <!-- 新增报告基础信息 -->
+    <reportBaseInfo 
+      v-model="showAddReport" 
+      :id="0" 
+    />
+
+    <!-- 报告预览弹窗 -->
+    <reportPreview
+      :show.sync="isShowPreview"
+      :reportIdInfo="previewReportInfo"
+      @itemclick="itemclickHandle"
+    />
+
+
+    <!-- 上传音频弹框 -->
+    <el-dialog
+      :title="$t('ReportManage.smart_audio_upload_btn')"
+      :visible.sync="uploadDialog"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="510px"
+    >
+      <div slot="title" style="display: flex; align-items: center">
+        <img
+          :src="$icons.up"
+          style="color: #fff; width: 16px; height: 16px; margin-right: 5px"
+        />
+        <span style="font-size: 16px">{{$t('ReportManage.smart_audio_upload_btn')}}</span>
+      </div>
+      <el-form
+        :model="uploadForm"
+        ref="uploadForm"
+        label-position="right"
+        label-width="0px"
+        @submit.native.prevent
+      >
+        <el-form-item label="">
+          <input
+            type="file"
+            name="file"
+            @change="fileSelected()"
+            id="file"
+            class="true-file"
+            style="display: none"
+          />
+          <el-input
+            type="text"
+            v-model="uploadForm.audioname"
+            readonly
+            :placeholder="$t('ReportManage.smart_upload_recording_btn')"
+            size="medium"
+            style="width: 350px"
+          ></el-input>
+          <el-button type="primary" size="medium" @click.native="clickinput"
+            >{{$t('ReportManage.smart_select_file')}}</el-button
+          >
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer" style="text-align: center">
+        <el-button
+          type="primary"
+          plain
+          size="medium"
+          @click.native="uploadDialog = false"
+          >{{$t('Dialog.cancel_btn')}}</el-button
+        >
+        <el-button
+          type="primary"
+          size="medium"
+          :loading="uploadloading"
+          @click.native="uploadaudio"
+          >{{ uploadloading ? $t('ReportManage.smart_btn.uploading') : $t('ReportManage.smart_btn.upload') }}</el-button
+        >
+      </div>
+    </el-dialog>
+
+    <!-- 音频下载弹窗(晨报周报多个音频情况) -->
+    <el-dialog
+      :title="$t('ReportManage.smart_audio_download_btn')"
+      :visible.sync="downloadAudio.show"
+      :modal-append-to-body="false"
+      :close-on-click-modal="false"
+      :center="true"
+      v-dialogDrag
+      custom-class="dialogclass"
+      width="510px"
+    >
+      <div class="download-audio-wrap">
+        <h3
+          style="
+            text-align: center;
+            font-size: 14px;
+            margin-top: -10px;
+            margin-bottom: 10px;
+          "
+        >
+          {{ downloadAudio.title }}
+        </h3>
+        <div class="list-box">
+          <el-checkbox
+            :indeterminate="downloadAudio.select.length > 0 && !checkAllAudio"
+            v-model="checkAllAudio"
+            style="margin-bottom: 10px"
+            @change="handleDownloadAudioCheckAll"
+            >{{$t('ReportManage.smart_btn.select_all')}}</el-checkbox
+          >
+          <el-checkbox-group v-model="downloadAudio.select">
+            <el-checkbox
+              :label="item"
+              v-for="item in downloadAudio.list"
+              :key="item.ReportChapterId"
+              style="margin-bottom: 10px; display: block"
+              >{{ item.VideoName }}</el-checkbox
+            >
+          </el-checkbox-group>
+        </div>
+        <div style="text-align: center; margin: 30px 0">
+          <el-button type="primary" plain @click="downloadAudio.show = false"
+            >{{$t('Dialog.confirm_btn')}}</el-button
+          >
+          <el-button type="primary" @click="handelConfirmDownloadAudio"
+            >{{$t('Dialog.confirm_btn')}}</el-button
+          >
+        </div>
+      </div>
+    </el-dialog>
+
+
+    <!-- 批量发布弹窗 -->
+    <el-dialog
+      :title="$t('ReportManage.smart_release_prompt_btn')"
+      :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?$t('ReportManage.smart_template_msg'):$t('ReportManage.smart_push_template_btn')}}
+        </div>
+        <div style="margin-bottom: 20px; text-align: center">
+          <el-button
+            type="primary"
+            plain
+            style="width: 100px"
+            @click="handleClosePublish"
+            >{{$t('Dialog.cancel_btn')}}</el-button
+          >
+          <el-button
+            type="primary"
+            style="width: 100px; margin: 0 20px"
+            @click="handlePublic(1)"
+            >{{$t('ReportManage.smart_btn.only_publish')}}</el-button
+          >
+          <el-button
+            type="primary"
+            style="width: 100px"
+            :disabled="!canPushMsg"
+            @click="handlePublic(2)"
+            >{{$t('ReportManage.smart_btn.publish_push')}}</el-button
+          >
+        </div>
+      </div>
+    </el-dialog>
+    
+  </div>
+</template>
+<script>
+import {
+  reportlist,
+  classifylist,
+  reportpublish,
+  reportpublishcancle,
+  voiceupload,
+  reportdelete,
+  markReport,
+  reportMessageSend,
+  weekReportValidAudio,
+} from '@/api/modules/reportV2.js';
+import { departInterence } from "api/api.js";
+import {approveInterence} from '@/api/modules/approve.js';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js";
+import reportBaseInfo from './components/reportBaseInfoDia.vue';
+import reportPreview from './components/reportPreview.vue';
+export default {
+  name:'reportV2',
+  components: { reportBaseInfo,reportPreview },
+  mixins:[reportApproveConfig],
+  computed: {
+    exportUrlDl() {
+      let url = process.env.VUE_APP_API_ROOT + "/report/report_view_record/export";
+
+      let ids = this.batches.join(",");
+      let param_token = localStorage.getItem("auth") || "";
+      return `${url}?ReportIds=${ids}&${param_token}`;
+    },
+    checkAllAudio() {
+      return (
+        this.downloadAudio.list.length === this.downloadAudio.select.length
+      )
+    },
+    canPushMsg() {
+      //判断是否能推送
+      if (this.batches.length == 0) return false;
+      let tag = false;
+      this.tableData.forEach((item) => {
+        if (this.batches.includes(item.Id)) {
+          if (item.MsgIsSend== 0) {
+            tag = true;
+          }
+        }
+      });
+      return tag;
+    },
+    //是否有UV
+    hasUV(){
+      return this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_reportList_uv)
+    },
+
+    reportTypes(){
+      return [
+        { label: /* '我的研报' */this.$t('ReportManage.ReportList.tab_mine'),key:'3' },
+        { label: /* '共享研报' */this.$t('ReportManage.ReportList.tab_share'),key:'2' },
+        { label: /* '公共研报' */this.$t('ReportManage.ReportList.tab_public'),key:'1' },
+      ]
+    }
+  },
+  data() {
+    return {
+      searchform: {
+        listType: '3',
+        timeType:'publish_time',
+        dateValue: "",
+        frequency: "",
+        classifyIds: '',
+        state: "",
+        key_word: "",
+        publish_sort: "desc",
+        msgIsSend: "",
+        publishState:'',
+      },
+
+      hostapi: process.env.VUE_APP_API_ROOT + "/voice/download",
+      dayWeekAudio: process.env.VUE_APP_API_ROOT + "/voice/report/download",
+
+      PageIndex: 1,
+      total: 0,
+      pageSize: 15,
+      listLoading: false,
+      tableData: [],
+
+      classifyOptions: [],//分类options
+
+      batches: [],
+      uploadloading: false,
+      uploadDialog: false,
+      uploadForm: {
+        id: "",
+        formdata: null,
+        audioname: "",
+      },
+
+      downloadAudio: {
+        show: false,
+        title: "名称",
+        list: [],
+        select: [],
+      },
+
+      showAddReport:false,//添加研报基础信息
+
+      showPublish: false,
+      isDSFB:false,//是否为定时发布
+      tableKey:0,
+      selectNum:1,
+
+      submitId:0,//当前选择的报告id
+
+      // 列出所有的按钮
+      /*未发布——发布、编辑、删除 1
+        已发布——取消发布、推送消息/已推送消息 2
+        待提交——提交、编辑、删除 3
+        待审批——撤销 4
+        已通过——撤销、推送消息/已推送消息 6
+        已驳回——撤销 5
+
+        音频上传和下载,跟State无关
+      */
+      allButtons:[
+        {label:"发布",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_publish'),States:[1],text:'ReportManage.smart_btn.publish'},
+        {label:"提交",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_publish'),States:[3],text:'ReportManage.smart_btn.submission'},
+        {label:"编辑",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_reportEdit'),States:[1,3],text:'Table.edit_btn'},
+        {label:"编辑中",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_reportEdit'),States:[1,3],text:'ReportManage.smart_btn.editing',},
+        {label:"删除",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_reportDel'),States:[1,3],text:'Table.delete_btn'},
+        {label:"取消发布",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_cancelPublish'),States:[2],text:'ReportManage.smart_btn.withdraw'},
+        {label:"撤销",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_cancelPublish'),States:[4,5,6],text:'ReportManage.smart_btn.withdraw'},
+        {label:"下载Pdf",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportPdf'),States:[2,6],text:'ReportManage.smart_btn.download_pdf'},
+        {label:"下载长图",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportImg'),States:[2,6],text:'ReportManage.smart_btn.download_long_image'},
+        {label:"推送消息",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_sendMsg'),States:[2,6],text:'ReportManage.smart_push_notification_btn'},
+        {label:"已推送消息",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_sendMsg'),States:[2,6],text:'ReportManage.smart_notification_pushed'},
+        {label:"音频上传",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_audioUpload'),States:true,text:'ReportManage.smart_audio_upload_btn'},
+        {label:"音频下载A",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_audioDownload'),States:true,text:'ReportManage.smart_audio_download_btn'},
+        // {label:"音频下载",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_audioDownload'),States:true,text:'ReportManage.smart_audio_download_btn'},
+      ],
+
+      waterMarkStr:"",
+      publishReportCode:'',
+
+      isShowPreview: false,//预览报告弹窗
+      previewReportInfo: {},
+
+      linkPdfUrl: '',//生成pdf链接的url
+    }
+  },
+  mounted(){
+    let PageIndex = sessionStorage.getItem("PageIndex") || false;
+    let searchform = sessionStorage.getItem("searchform") || false;
+    if (PageIndex && searchform) {
+      this.searchform = JSON.parse(searchform);
+      this.PageIndex = PageIndex;
+      sessionStorage.removeItem("PageIndex");
+      sessionStorage.removeItem("searchform");
+    }
+
+    this.getclassifylist();
+    this.getReportList();
+    this.getSystemUserInfo();
+  },
+  methods:{
+    getclassifylist() {
+      //获取分类列表
+      let params = { CurrentIndex: 0, PageSize: 1000, KeyWord: "" };
+
+      classifylist(params).then((res) => {
+        if (res.Ret == 200 && Array.isArray(res.Data.List)) {
+          this.classifyOptions = res.Data.List||[];
+          
+        }
+      });
+    },
+
+    getReportList() {
+       //获取列表
+      let params = {
+        CurrentIndex: this.PageIndex,
+        PageSize: this.pageSize,
+        Frequency: this.searchform.frequency,
+        ClassifyIdFirst: this.searchform.classifyIds
+          ? this.searchform.classifyIds[0]
+          : "",
+        ClassifyIdSecond:
+          this.searchform.classifyIds &&
+          this.searchform.classifyIds.length > 1
+            ? this.searchform.classifyIds[1]
+            : "",
+        ClassifyIdThird:
+          this.searchform.classifyIds &&
+          this.searchform.classifyIds.length > 1
+            ? this.searchform.classifyIds[2]
+            : "",
+        State: this.searchform.state ? this.searchform.state : null,
+        KeyWord: this.searchform.key_word,
+        MsgIsSend: this.searchform.msgIsSend,
+        State:this.searchform.publishState,
+        TimeType:this.searchform.timeType,
+        FilterReportType: this.searchform.listType
+      };
+      
+      if (this.searchform.dateValue) {
+        params.StartDate = this.searchform.dateValue[0];
+        params.EndDate = this.searchform.dateValue[1];
+      }
+
+      this.listLoading = true;
+      reportlist(params).then((res) => {
+        this.listLoading = false;
+
+        if (res.Ret === 200) {
+          this.tableData = res.Data.List || [];
+          this.total = parseInt(res.Data.Paging.Totals);
+        }
+        
+      });
+    },
+
+    renderHeader(h, { column, $index }) {
+      //table表头自定义
+      return h("div", { attrs: { style: "padding:0;" } }, [
+        h("span", column.label),
+        h("el-tooltip", { props: { placement: "top" } }, [
+          h(
+            "p",
+            {
+              slot: "content",
+              attrs: { style: "display:block;padding:5px 0;width:420px;" },
+            },
+            `pv:${this.$t('ReportManage.tooltip_pv_show')}`
+          ),
+          this.hasUV?h(
+            "p",
+            {
+              slot: "content",
+              attrs: { style: "display:block;padding:5px 0;width:420px;" },
+            },
+            `uv:${this.$t('ReportManage.tooltip_uv_show')}`
+          ):h(''),
+          h(
+            "el-button",
+            {
+              props: { icon: "el-icon-info" },
+              attrs: { style: "border:none;background:none" },
+            },
+            ""
+          ),
+        ]),
+      ]);
+    },
+
+    sortChange(column, prop, order) {
+
+      this.searchform.publish_sort =
+        column.order == "ascending"
+          ? "asc"
+          : column.order == "descending"
+          ? "desc"
+          : "";
+      this.filterChange();
+    },
+
+    filterChange() {
+      this.PageIndex = 1;
+      this.getReportList();
+    },
+
+    handleCurrentChange(current) {
+      //分页页码跳转
+      this.PageIndex = current;
+      this.getReportList();
+    },
+
+    // 预览报告详情
+    lookreportdtl(item) {
+      //如果没有预览权限,就不跳转
+      if(!this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_reportView)) return
+
+      this.previewReportInfo = item;
+      this.isShowPreview = true
+
+    },
+
+
+    //下载音频弹窗
+    handleShowDownloadAudio(item) {
+      this.downloadAudio.show = true;
+      this.downloadAudio.title = item.Title;  
+      this.downloadAudio.list = item.ChapterVideoList;
+      this.downloadAudio.select = [];
+    },
+    handleDownloadAudioCheckAll(val) {
+      this.downloadAudio.select = val ? this.downloadAudio.list : [];
+    },
+    //下载音频
+    handelConfirmDownloadAudio() {
+      //批量下载音频
+      let ids = [];
+      this.downloadAudio.select.forEach((item) => {
+        ids.push(item.ReportChapterId);
+      });
+
+      const a = document.createElement("a");
+      a.style.display = "none";
+      a.setAttribute("download", "测试");
+      a.href = `${this.dayWeekAudio}?ChapterIds=${ids.join(",")}`;
+      document.body.appendChild(a);
+      a.click();
+
+    },
+
+    //唤醒上传弹窗
+    openupload({Id}) {
+      this.uploadForm = { id: Id, formdata: null, audioname: "" };
+      this.uploadDialog = true;
+    },
+    clickinput() {
+      //上传模拟点击
+      $("#file").click();
+    },
+    fileSelected() {
+      //选择文件上传
+      const that = this;
+      if (document.getElementById("file").files[0]) {
+        let hostfile = document.getElementById("file").files[0];
+        let size = Math.floor(hostfile.size / 1024 / 1024);
+        if (size > 200) {
+          that.$message.error(this.$t('ReportManage.smart_msg.uploaded_limitation'));
+          hostfile = {};
+          return false;
+        }
+        if (
+          hostfile.name.includes(".mp3") ||
+          hostfile.name.includes(".wav") ||
+          hostfile.name.includes(".wma")
+        ) {
+          let form = new FormData();
+          form.append("file", hostfile); //hostfile.name
+          form.append("ReportId", this.uploadForm.id);
+          this.uploadForm.formdata = form;
+          this.uploadForm.audioname = hostfile.name;
+        } else {
+          that.$message.error(this.$t('ReportManage.smart_msg.upload_format'));
+        }
+      }
+    },
+    uploadaudio() {
+      if (this.uploadForm.formdata == null) {
+        this.$message.error("请选择文件");
+        return false;
+      }
+      this.uploadloading = true;
+      voiceupload(this.uploadForm.formdata).then((res) => {
+        if (res.Ret === 200) {
+          this.$message.success("上传成功");
+          this.getReportList();
+        }
+        this.uploadloading = false;
+        $("#file").val("");
+        this.uploadDialog = false;
+      });
+    },
+
+      //取消发布
+    canclepublish(item) {
+      reportpublishcancle({ ReportIds: item.Id }).then((res) => {
+        if (res.Ret === 200) {
+          this.$message.success(this.$t('MsgPrompt.operate_success_msg'));
+          this.getReportList();
+        }
+      });
+    },
+
+      //删除
+    deleteitem(item) {
+      this.$confirm(this.$t('ReportManage.smart_msg.delete_it'), this.$t('Confirm.prompt'), {
+        confirmButtonText:  this.$t('Dialog.confirm_btn'),
+        type: "warning",
+      }).then(() => {
+          reportdelete({ ReportIds: item.Id }).then((res) => {
+            if (res.Ret === 200) {
+              this.$message.success(res.Msg);
+              this.getReportList();
+            }
+          });
+        })
+        .catch(() => {});
+    },
+
+    //编辑报告
+    async editreport(item, type) {
+
+      if(item.CollaborateType===1) {
+        //编辑前标记一下
+          const res = await markReport({
+            Status: 1,
+            ReportId: item.Id,
+          });
+          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;
+          }
+      }
+
+      sessionStorage.setItem("searchform", JSON.stringify(this.searchform));
+      sessionStorage.setItem("PageIndex", this.PageIndex);
+
+      let pathV2 = item.ReportLayout===1 ? '/reportEditV2' : "/smpartReportEditV2";
+
+      this.$router.push({
+        // path: item.ReportVersion === 2 ? pathV2 : "/editreport",
+        path: pathV2,
+        query: {
+          id: item.Id,
+          coopType: item.CollaborateType
+        },
+      });
+    },
+
+    //发布报告
+    async publishreport(item) {
+      this.batches = [];
+      this.batches.push(item.Id);
+      this.publishReportCode = item.ReportCode
+      this.isDSFB=item.PrePublishTime?true:false
+
+      let baseUrl= localStorage.getItem('dynamicOutLinks') ? JSON.parse(localStorage.getItem('dynamicOutLinks')).ReportViewUrl : '';
+			this.linkPdfUrl = item.ReportLayout===1 ? `${baseUrl}/reportshare_pdf` : `${baseUrl}/reportshare_smart_pdf`;
+
+      if(this.isApprove){
+        this.handlePublic(1)
+        return
+      }
+      const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)
+      if(isPost){
+          this.showPublish = true;
+      }else{
+        this.handlePublic(1)
+      }
+      
+    },
+
+    // 点击确认发布&推送报告
+    // 1 仅发布 2发布且推送
+    handlePublic(type) {
+      reportpublish({ ReportIds: this.batches.join(","),ReportUrl:this.generatePdfLinks(this.publishReportCode)}).then((res) => {
+        if (res.Ret == 200) {
+          if (type == 2) {
+            reportMessageSend({
+              ReportId: this.batches[0],
+            }).then((resMsg) => {
+              if (resMsg.Ret == 200) {
+                this.$message.success(this.$t('ReportManage.smart_msg.published_success'));
+                this.batches = [];
+                this.getReportList();
+                this.showPublish = false;
+              }
+            });
+          } else {
+            if (res.Data) {
+              this.$alert(res.Data, this.$t('ReportManage.smart_msg.release_prompt'), {
+               confirmButtonText: this.$t('Dialog.confirm_btn'),
+                callback: (action) => {},
+              });
+            } else {
+              this.$message.success(this.$t('MsgPrompt.publish_msg'));
+            }
+            this.batches = [];
+            this.getReportList();
+            this.showPublish = false;
+          }
+        }
+      });
+    },
+    generatePdfLinks(Code){
+			return `${this.linkPdfUrl}?code=${Code}&flag=${this.waterMarkStr}`
+		},
+
+    //取消发布
+    handleClosePublish() {
+      this.batches = [];
+      this.showPublish = false;
+    },
+
+    //提交报告
+    handleSubmitReport(item){
+        this.submitId = item.Id
+        this.$confirm(this.$t('ReportManage.smart_msg.submit_approval'),this.$t('Confirm.prompt'),{
+            confirmButtonText: this.$t('Dialog.confirm_btn'),
+            cancelButtonText: this.$t('Dialog.cancel_btn'),
+            type:'warning',
+        }).then(()=>{
+            this.submitReport()
+        })
+    },
+    submitReport(type){
+        //both:提交&推送
+        /* if(type==='submit'){ */
+            approveInterence.reportCnSubmit({
+                ReportId:Number(this.submitId)
+            }).then(res=>{
+                if(res.Ret!==200) return
+                this.$message.success(this.$t('ReportManage.smart_msg.submit_success'))
+                this.getReportList()
+            })
+        /* } */
+    },
+
+    //撤销提交报告
+    cancelReport(item){
+      this.$confirm(this.$t('ReportManage.smart_msg.revoke_approval'),this.$t('Confirm.prompt'),{
+          confirmButtonText: this.$t('Dialog.confirm_btn'),
+          cancelButtonText: this.$t('Dialog.cancel_btn'),
+      }).then(()=>{
+          approveInterence.reportCnCancel({
+              ReportId:Number(item.Id)
+          }).then(res=>{
+              if(res.Ret!==200) return 
+              this.$message.success(this.$t('ReportManage.smart_msg.revoke_success'))
+              this.getReportList()
+          })
+      })
+    },
+
+    /* 下载阅读数据 */
+    downLoadReport() {
+      if (this.batches.length == 0) {
+        this.$confirm(this.$t('ReportManage.smart_msg.select_dl_report'), this.$t('Confirm.prompt'), {
+          type: "warning",
+          showCancelButton: false,
+        })
+          .then(() => {})
+          .catch(() => {});
+        return false;
+      }
+    },
+
+    // 推送消息(同时推送模板消息和客群消息)
+    messageSend(item) {
+      reportMessageSend({ ReportId: item.Id }).then((res) => {
+        if (res.Ret === 200) {
+          this.$message.success(this.$t('ReportManage.smart_msg.push_success'));
+          item.MsgIsSend = 1;
+          item.MsgSendTime = res.Data.MsgSendTime;
+        }
+      });
+    },
+
+    //操作
+    itemclickHandle({type,data}){
+      switch (type) {
+        case '发布':
+          this.publishreport(data)
+          break;
+        case '提交':
+          this.handleSubmitReport(data)
+          break;
+        case '编辑':
+          this.editreport(data, 'edit')
+          break;
+        case '编辑中':
+          this.editreport(data, 'editing')
+          break;
+        case '删除':
+          this.deleteitem(data)
+          break;
+        case '取消发布':
+          this.canclepublish(data)
+          break;
+        case '撤销':
+          this.cancelReport(data)
+          break;
+        case '推送消息':
+          this.messageSend(data)
+          break;
+        case '音频上传':
+          this.openupload(data)
+          break;
+        case '音频下载':
+          this.handleShowDownloadAudio(data)
+          break;
+        case '下载Pdf':
+          this.downloadPdfImg(data,1)
+          break;
+        case '下载长图':
+          this.downloadPdfImg(data,2)
+          break;
+        default:
+          break;
+      }
+    },
+
+    getSystemUserInfo(){
+      departInterence.systemUserInfo().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)
+            this.waterMarkStr=Base64.encode(waterMarkString)
+            
+            localStorage.setItem('waterMarkStr',this.waterMarkStr)
+          }
+        }
+      })
+    },
+
+    downloadPdfImg(row,type){
+      if(type == 1){
+          window.open(row.DetailPdfUrl,"_blank")
+      }else{
+          this.handleDownloadResource(row.DetailImgUrl,`${row.Title}`)
+      }
+    },
+
+    // 搞成前面一部分按钮,后面一部分按钮的形式
+    getbuttonList(row,type){
+      if(!type) return []
+
+      const commonFilter=(but)=>{
+        return but.permission &&
+          (typeof(but.States)=='boolean' || but.States.includes(row.State) ) &&
+          ( row.CanEdit || (![1,3].includes(row.State)) )
+      }
+      let buttonArr=this.allButtons.filter(but =>{
+        const commonFilterPass=commonFilter(but)
+        if(but.label==='编辑中'){
+          return but.permission &&
+              (typeof(but.States)=='boolean' || but.States.includes(row.State) ) &&
+              (!row.CanEdit)
+        }else if(but.label==='推送消息'){
+          return commonFilterPass && row.MsgIsSend==0 && row.HasAuth
+        }else if(but.label==='已推送消息'){
+          return commonFilterPass && row.MsgIsSend!==0
+        }else if(['音频上传'].includes(but.label)){
+          return commonFilterPass&&row.HasAuth
+        }else if(but.label==='音频下载A'){
+          return commonFilterPass && (row.VideoUrl || row.ChapterVideoList.length>0)
+        }else if(but.label==='下载Pdf'){
+          return commonFilterPass && row.DetailPdfUrl    
+        }else if(but.label==='下载长图'){
+          return commonFilterPass && row.DetailImgUrl           
+        }
+
+        return commonFilterPass
+      })
+
+      if(type=='f') return buttonArr.slice(0,2)
+      else return buttonArr.slice(2)
+    },
+  },
+}
+</script>
+<style scoped lang='scss'>
+.reportV2-list {
+  .header {
+    display: flex;
+    justify-content: space-between;
+  }
+  .select-btn{
+      cursor: pointer;
+      width:130px;
+      height: 36px;
+      text-align: center;
+      background-color: #ECF2FE;
+      border-radius: 4px;
+      box-sizing: border-box;
+      line-height:36px;
+      img,span{
+        display: inline-block;
+        vertical-align: middle;
+      }
+      .select-num{
+        width:20px;
+        height:20px;
+        line-height: 20px;
+        border-radius: 50%;
+        background-color:#0052D9;
+        color:white;
+        font-size: 12px;
+      }
+  }
+
+  .select-wrap{
+      display: flex;
+      flex-wrap: wrap;
+      gap: 15px;
+      /* margin:0 20px;
+      .select-item{
+          margin-top:20px;
+      } */
+  }
+  
+  .opt-btns {
+    span,
+    a {
+      display: inline-block;
+      margin: 0 3px;
+    }
+  }
+
+  .report-types-cont {
+    margin-bottom: 20px;
+  }
+}
+</style>
+<style lang="scss">
+  .el-tooltip__popper {
+    max-width: 40%;
+  }
+</style>

+ 86 - 0
src/views/report_manage/reportV2/normalReport/components/ETAChart.vue

@@ -0,0 +1,86 @@
+<template>
+    <div class="eta-chart-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span :class="['item',activeType==='ETA图库'?'active':'']" @click="activeTypeChange('ETA图库')">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</span>
+                <span :class="['item',activeType==='MyETA'?'active':'']" @click="activeTypeChange('MyETA')">{{$t('MyEtaPage.tab_my')}}</span>
+            </div>
+            <el-input
+                class="search-box"
+                :placeholder="$t('ReportManage.ReportList.chart_name')"
+                v-model="keyword"
+                size="medium"
+                prefix-icon="el-icon-search"
+                v-if="activeType==='ETA图库'"
+                @input="handleETAChartSearch"
+            />
+        </div>
+        <ImportETAChart ref="ETAChartWrap" v-if="activeType==='ETA图库'" @insertHtml="item =>{$emit('insertHtml',item)}"/>
+        <ImportMyETAChart @handleImportMyChart="handleImportMyChart" v-if="activeType==='MyETA'"/>
+    </div>
+</template>
+
+<script>
+import ImportETAChart from './ImportETAChart.vue';
+import ImportMyETAChart from './importMyChart.vue';
+export default {
+    name:"ETAChartWrap",
+    components:{ImportETAChart,ImportMyETAChart},
+    data() {
+        return {
+            keyword:'',
+            activeType:'ETA图库',
+        }
+    },
+    methods: {
+        activeTypeChange(e){
+            if(this.activeType===e) return
+            this.keyword = ''
+            this.activeType=e
+        },
+
+        handleETAChartSearch(){
+            this.$refs.ETAChartWrap.handleSearch(this.keyword)
+        },
+
+        handleImportMyChart(list){
+            this.$emit('handleImportMyChart',list)
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.eta-chart-wrap{
+    .top-box{
+        .left-card{
+            width: fit-content;
+            margin-bottom: 15px;
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            align-items: center;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
+        }
+    }
+}
+</style>

+ 144 - 0
src/views/report_manage/reportV2/normalReport/components/ETAPriceChart.vue

@@ -0,0 +1,144 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="right">
+                <el-input
+                    class="search-box"
+					placeholder="图表名称"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                <div class="chart-item" v-for="item in list" :key="item.UniqueCode">
+                    <div class="title">{{item.ChartName}}</div>
+                    <img
+                        :src="item.ChartImage"
+                        @click="$emit('insertHtml',item)"
+                    />
+                </div>
+                <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import futuresInterface from "@/api/modules/futuresBaseApi";
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            isShowMe:false,
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getChartList()
+    },
+    methods: {
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        /* 搜索图表分页 */
+        async getChartList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            };
+            this.loading=true
+            let res = await futuresInterface.searchChart(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getChartList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 0 20px;
+
+        }
+    }
+}
+.chart-item {
+    width: 250px;
+    margin: 10px 0;
+    padding: 20px;
+    border: 1px solid #eaeaea;
+    border-radius: 10px;
+    font-size: 16px;
+    text-align: center;
+    img {
+        width: 100%;
+    }
+}
+</style>

+ 137 - 0
src/views/report_manage/reportV2/normalReport/components/ETASandBox.vue

@@ -0,0 +1,137 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.no_reports_msg')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+               
+                <div class="chart-item" v-for="item in list" :key="item.SandboxId">
+                    <div class="title">{{item.Name}}</div>
+                    <img
+                        :src="item.PicUrl"
+                        @click="$emit('insertHtml',item)"
+                    />
+                </div>
+                <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {sandInterface} from "@/api/api.js";
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSandBoxList()
+    },
+    methods: {
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSandBoxList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSandBoxList()
+        },
+
+        /* 搜索图表分页 */
+        async getSandBoxList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            };
+            this.loading=true
+            let res = await sandInterface.sandlistByQuote(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSandBoxList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 0 20px;
+
+        }
+    }
+}
+.chart-item {
+    width: 250px;
+    margin: 10px 0;
+    padding: 20px;
+    border: 1px solid #eaeaea;
+    border-radius: 10px;
+    font-size: 16px;
+    text-align: center;
+    img {
+        width: 100%;
+    }
+}
+</style>

+ 123 - 0
src/views/report_manage/reportV2/normalReport/components/ETASheet.vue

@@ -0,0 +1,123 @@
+<template>
+    <div class="eta-sheet-wrap">
+        <div class="top-box">
+            <el-input
+                class="search-box"
+				:placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+				v-model="keyword"
+				size="medium"
+				prefix-icon="el-icon-search"
+                @input="handleSearch"
+			/>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+            <div class="sheet-item" v-for="item in list" :key="item.ExcelInfoId">
+                <div class="title">{{item.ExcelName}}</div>
+                <div class="img" :style="`backgroundImage:url(${ !item.HaveOperaAuth?$icons.lock_big:item.ExcelImage })`" @click="$emit('insertHtml',item)"></div>
+                <img
+                    :src="!item.HaveOperaAuth?$icons.lock_big:item.ExcelImage"
+                    @click="$emit('insertHtml',item)"
+                />
+            </div>
+            <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+    data() {
+        return {
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSheetList()
+    },
+    methods: {
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSheetList()
+        },
+        getSheetList() {
+            this.loading=true
+            sheetInterface.sheetList({
+                Keyword: this.keyword,
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            }).then((res) => {
+                this.loading=false
+                if (res.Ret !== 200) return;
+                const arr = res.Data.List || [];
+                this.list =
+                    this.page === 1
+                    ? arr
+                    : [...this.list, ...arr];
+                this.finished =  res.Data.Paging.IsEnd;
+            });
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSheetList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.eta-sheet-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        .search-box{
+            width: 330px;
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 0 20px;
+
+        }
+        .sheet-item{
+            width: 250px;
+            margin: 10px 0;
+            padding: 20px;
+            border: 1px solid #eaeaea;
+            border-radius: 10px;
+            font-size: 16px;
+            text-align: center;
+            img {
+                width: 100%;
+                height: 200px;
+            }
+        }
+    }
+}
+</style>

+ 121 - 0
src/views/report_manage/reportV2/normalReport/components/ImportETAChart.vue

@@ -0,0 +1,121 @@
+<template>
+    <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+ 
+                <div class="chart-item" v-for="item in list" :key="item.UniqueCode">
+                    <div class="title">{{item.ChartName}}</div>
+                    <img
+                        :src="!item.HaveOperaAuth?$icons.lock_big:item.ChartImage"
+                        @click="$emit('insertHtml',item)"
+                    />
+                </div>
+                <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+</template>
+
+<script>
+import { dataBaseInterface } from "@/api/api.js";
+export default {
+    data() {
+        return {
+            isShowMe:false,
+            page:1,
+            pageSize:20,
+            list:[],
+            finished:false,
+            keyword:'',
+            loading:false
+        }
+    },
+    computed: {
+        //语言版本
+        currentLang() {
+            return this.$store.state.lang
+        }
+    },
+    created() {
+        this.getETAChartList()
+    },
+    methods: {
+
+        async getETAChartList(){
+            this.loading=true
+            const res=await dataBaseInterface.chartSearchByEs({
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            })
+            this.loading=false
+            if(res.Ret===200){
+                const arr=res.Data.List || []
+                this.list=[...this.list,...arr]
+                this.finished=res.Data.Paging.IsEnd
+            }
+        },
+
+        handleIsShowMeChange(){
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.getETAChartList()
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getETAChartList()
+        },
+
+        handleSearch(key){
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.keyword=key
+            this.getETAChartList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+
+.main-box{
+    margin-top: 30px;
+    height: calc(100vh - 300px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+    background: #FFF;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    .list-wrap{
+        flex: 1;
+        overflow-y: auto;
+        display: flex;
+        flex-wrap: wrap;
+        gap: 0 20px;
+    }
+}
+.chart-item {
+    width: 250px;
+    margin: 10px 0;
+    padding: 20px;
+    border: 1px solid #eaeaea;
+    border-radius: 10px;
+    font-size: 16px;
+    text-align: center;
+    img {
+        width: 100%;
+    }
+}
+</style>

+ 138 - 0
src/views/report_manage/reportV2/normalReport/components/SemanticAnalysis.vue

@@ -0,0 +1,138 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.keyword_search')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                    <div class="chart-item" v-for="item in list" :key="item.SaCompareId">
+                        <div class="title">{{item.Title}}</div>
+                        <img
+                            :src="item.ResultImg"
+                            @click="$emit('insertHtml',{...item,PicUrl:item.ResultImg})"
+                        />
+                    </div>
+                <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {semanticInterface} from '@/api/modules/semanticsApi.js';
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSemanticList()
+    },
+    methods: {
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSemanticList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSemanticList()
+        },
+
+        /* 搜索图表分页 */
+        async getSemanticList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            };
+            this.loading=true
+            let res = await semanticInterface.compareSearch(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSemanticList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 0 20px;
+
+        }
+    }
+}
+.chart-item {
+    width: 250px;
+    margin: 10px 0;
+    padding: 20px;
+    border: 1px solid #eaeaea;
+    border-radius: 10px;
+    font-size: 16px;
+    text-align: center;
+    img {
+        width: 100%;
+        height: 200px;
+    }
+}
+</style>

+ 225 - 0
src/views/report_manage/reportV2/normalReport/components/StatisticAnalysis.vue

@@ -0,0 +1,225 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span
+                    :class="['item',activeType===item.key?'active':'']" 
+                    @click="activeTypeChange(item.key)"
+                    v-for="item in typeOpts"
+                    :key="item.key"
+                >{{item.name}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.chart_name')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                
+                <div class="chart-item" v-for="item in list" :key="item.UniqueCode">
+                    <div class="title">{{item.ChartName}}</div>
+                    <img
+                        :src="item.ChartImage"
+                        @click="$emit('insertHtml',item)"
+                    />
+                </div>
+                <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
+import {
+  fittingEquationInterface,
+  statisticFeatureInterface,
+  crossVarietyInterface
+} from "@/api/modules/chartRelevanceApi";
+export default {
+    data() {
+        return {
+
+            keyword:'',
+            isShowMe:false,
+            activeType:'相关性',
+
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getChartList()
+    },
+    methods: {
+
+        activeTypeChange(e){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.keyword=''
+            this.isShowMe=false
+            this.activeType=e
+            this.getChartList()
+        },
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        /* 搜索图表分页 */
+        async getChartList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            };
+            this.loading=true
+            let res = null;
+            if (this.activeType === '相关性') {
+                res = await chartRelevanceApi.searchChart(params);
+            } else if (this.activeType === '拟合方程曲线') {
+                res = await fittingEquationInterface.searchChart(params);
+            } else if (this.activeType === '统计特征') {
+                res = await statisticFeatureInterface.searchChart(params);
+            } else if (this.activeType === '跨品种分析') {
+                res = await crossVarietyInterface.searchChart(params);
+            }
+            this.loading=false
+
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getChartList()
+        }
+    },
+    computed:{
+      typeOpts(){
+        return [
+                {
+                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
+                    key:'相关性'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
+                    key:'拟合方程曲线'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
+                    key:'统计特征'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
+                    key:'跨品种分析'
+                }
+            ]
+      }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        .left-card{
+            margin-bottom: 15px;
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            gap: 0 3px;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
+        }
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 0 20px;
+
+        }
+    }
+}
+.chart-item {
+    width: 250px;
+    margin: 10px 0;
+    padding: 20px;
+    border: 1px solid #eaeaea;
+    border-radius: 10px;
+    font-size: 16px;
+    text-align: center;
+    img {
+        width: 100%;
+    }
+}
+</style>

+ 165 - 0
src/views/report_manage/reportV2/normalReport/components/importMyChart.vue

@@ -0,0 +1,165 @@
+<template>
+    <div class="import-mychart-wrap">
+        <div>
+			<el-select 
+				v-model="selectMyChartClassify" 
+				filterable 
+				:placeholder="$t('ReportManage.ReportList.chart_category_name')"
+				@change="handleChange"
+			>
+				<el-option
+					v-for="item in myChartClassifyList"
+					:key="item.MyChartClassifyId"
+					:label="item.MyChartClassifyName"
+					:value="item.MyChartClassifyId"
+				>
+				</el-option>
+			</el-select>
+			<el-button type="primary" @click="handleImport">{{$t('ReportManage.ReportList.click_import')}}</el-button>
+			<el-tooltip class="item" effect="dark" :content="$t('ReportManage.ReportList.import_all_chart_msg')" placement="top-start">
+				<i style="font-size:20px;color: #666;" class="el-icon-question"></i>
+			</el-tooltip>
+		</div>
+		<div class="list" v-infinite-scroll="load" v-if="list.length>0">
+            <div class="item" v-for="item in list" :key="item.UniqueCode" @click="handleClickItem">
+                <div class="chartEn-mark" v-show="item.IsEnChart && showEnMark" style="top: 0;left: 0;">En</div>
+                <p class="color_primary">{{ item.ChartName }}</p>
+                <img :src="!item.HaveOperaAuth?$icons.lock_big:item.ChartImage" alt="">
+            </div>
+		</div>
+        <div v-if="list.length==0" class="empty-box">
+            {{$t('Table.prompt_slogan')}}
+        </div>
+    </div>
+</template>
+
+<script>
+import { mychartInterface } from '@/api/api.js';
+export default {
+    data() {
+        return {
+            myChartClassifyList:[],
+            selectMyChartClassify:'',
+            pageSize:10000,
+			CurrentIndex: 1,
+			list:[],
+            loading:false,
+            finished:false,
+
+        }
+    },
+    props:{
+        showEnMark:{
+            type:Boolean,
+            default:false
+        }
+    },
+    mounted(){
+        this.getMyChartClassify()
+    },  
+    methods: {
+        //获取我的图库中分类
+		getMyChartClassify(){
+			mychartInterface.classifyList().then(res=>{
+				if (res.Ret !== 200) return;
+				this.myChartClassifyList=res.Data?res.Data.List:[]
+			})
+		},
+        handleChange(){
+            this.CurrentIndex=1
+            this.list=[]
+            this.finished=false
+            this.loading=false
+            this.handleGetMyChartList()
+        },
+		async handleGetMyChartList(){
+            if(!this.selectMyChartClassify) return
+            this.loading=true
+            const res=await  mychartInterface.myList({
+				PageSize: this.pageSize,
+				CurrentIndex: this.CurrentIndex,
+				MyChartClassifyId: this.selectMyChartClassify || 0
+			})
+            this.loading=false
+            const arr=res.Data?res.Data.List.filter(_=>!_.Disabled):[]
+            this.list=[...this.list,...arr]
+            if(!res.Data){
+                this.finished=true
+            }
+            if(res.Data&&res.Data.Paging.IsEnd){
+                this.finished=true
+            }
+		},
+
+        load(){
+            if(this.finished) return
+            this.CurrentIndex++
+            this.handleGetMyChartList()
+        },
+
+        handleImport:_.throttle(function(){
+            if(!this.selectMyChartClassify){
+                this.$message.warning(this.$t('ReportManage.ReportList.please_select_category'))
+                return
+            }
+            let filterList = this.list.filter(_ =>_.HaveOperaAuth)
+            if(filterList.length==0){
+                this.$message.warning(this.$t('ReportManage.ReportList.no_chart_msg'))
+                return
+            }
+            this.$emit('handleImportMyChart',filterList)
+            setTimeout(() => {
+                this.CurrentIndex=1
+                this.list=[]
+                this.finished=false
+                this.loading=false
+                this.selectMyChartClassify=''
+            }, 300);
+        },1000),
+
+        handleClickItem(){
+            this.$message.warning(this.$t('ReportManage.ReportList.no_one_charts'))
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap{
+    background: #fff;
+    padding: 20px;
+    .list{
+        height: calc(100vh - 320px);
+        overflow-x: hidden;
+		overflow-y: auto;
+        display: flex;
+        flex-wrap: wrap;
+        gap: 0 20px;
+        .item{
+            width: 250px;
+            margin: 10px 0;
+            padding: 20px;
+            box-sizing: border-box;
+            border: 1px solid #eaeaea;
+            border-radius: 10px;
+            position: relative;
+            overflow: hidden;
+            p{
+                text-align: center;
+                font-size: 16px;
+                margin-bottom: 10px;
+                color: #5882EF;
+            }
+            img{
+                width: 100%;
+            }
+        }
+    }
+    .empty-box{
+        height: calc(100vh - 320px);
+        text-align: center;
+        color: #999;
+        padding-top: 100px;
+    }
+}
+</style>

+ 104 - 0
src/views/report_manage/reportV2/normalReport/components/insertContent.vue

@@ -0,0 +1,104 @@
+<template>
+  <div class="insert-content">
+    <div class="close-icon" @click="$emit('slide')">
+        <img src="~@/assets/img/smartReport/icon14.png" alt="">
+    </div>
+    <!-- 图库插入 -->
+    <ETAChart 
+        v-if="actTab==='etaChart'"
+        @handleImportMyChart="handleImportMyChart"
+        @insertHtml="item => {$emit('insertHtml',{item})}"
+    />
+    <!-- ETA表格 -->
+    <ETASheet v-if="actTab==='etaSheet'" @insertHtml="item =>{$emit('insertHtml',{item,type:'sheet'})}"/>
+    <!-- 统计分析 -->
+    <StatisticAnalysis v-if="actTab==='statisticAnalysis'" @insertHtml="item => {$emit('insertHtml',{item})}"/>
+    <!-- 商品价格曲线 -->
+    <ETAPriceChart v-if="actTab==='etaPriceChart'" @insertHtml="item => {$emit('insertHtml',{item})}"/>
+    <!-- 沙盘图 -->
+    <ETASandBox v-if="actTab==='etaSandBox'" @insertHtml="item=>{$emit('insertHtml',{item,type:'image'})}"/>
+    <!-- 语义分析 -->
+    <SemanticAnalysis v-if="actTab==='semanticAnalysis'" @insertHtml="item => {$emit('insertHtml',{item,type:'image'})}"/>
+
+  </div>
+</template>
+<script>
+import ETAChart from './ETAChart.vue'
+import ETASheet from './ETASheet.vue'
+import StatisticAnalysis from './StatisticAnalysis.vue'
+import ETAPriceChart from './ETAPriceChart.vue'
+import ETASandBox from './ETASandBox.vue'
+import SemanticAnalysis from './SemanticAnalysis.vue'
+export default {
+  props: {
+    actTab: {
+      type: String
+    }
+  },
+  components: {ETAChart,ETASheet,StatisticAnalysis,ETAPriceChart,ETASandBox,SemanticAnalysis  },
+  data() {
+    return {
+    }
+  },
+  methods: {
+      handleImportMyChart(list){
+          this.$emit('handleImportMyChart',list)
+      }
+  }
+}
+</script>
+<style scoped lang='scss'>
+*{ box-sizing: border-box; }
+.insert-content {
+  /* width: 400px; */
+  height: calc(100vh - 100px);
+  flex: 1;
+  margin-left: 30px;
+  padding: 30px;
+  position: relative;
+  &::before{
+      display: block;
+      content: '';
+      width: 1px;
+      height: 100%;
+      background-color: #C8CDD9;
+      position: absolute;
+      left: 0;
+      top: 0;
+  }
+
+  .close-icon{
+      width: 20px;
+      height: 20px;
+      border-radius: 4px;
+      background: #FFF;
+      box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      cursor: pointer;
+      position: absolute;
+      left: -10px;
+      top: 22px;
+      img{
+          width: 16px;
+          height: 16px;
+      }
+  }
+
+  .slide-icon {
+		padding: 20px 0;
+		box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.3);
+		border-radius: 5px;
+		background-color: #fff;
+		cursor: pointer;
+		position: absolute;
+		top: 40%;
+		z-index: 99;
+    left: -15px;
+		&:hover {
+			background-color: #e0e0e0;
+		}
+	}
+}
+</style>

+ 711 - 0
src/views/report_manage/reportV2/normalReport/editReport.vue

@@ -0,0 +1,711 @@
+<template>
+	<div id="editreport">
+		
+		<!-- 章节报告 章节编辑区 -->
+		<div class="left-wrap" v-if="reportCoopType===2">
+			<chapterWrapper
+				v-show="isLeftWrapShow"
+				ref="chapterContRef"
+				:isApprove="isApprove"
+				:hasApproveFlow="hasApproveFlow"
+				@change="handleChapterInfo"
+				@checkClassifyNameArr="handleCheckClassifyNameArr"
+				@openBaseInfo="showReportBaseInfo=true"
+				@handlePreviewReport="handlePreviewReport"
+				@handlePublish="handlePublishReport"
+				@update="({Title}) => { reportInfo.Title=Title }"
+			/>
+
+			<span
+					class="slide-btn-icon"
+					:class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+					@click="isLeftWrapShow = !isLeftWrapShow"
+			>
+					<i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+			</span>
+		</div>
+
+		<div class="editor-wrapper">
+
+			<!-- 章节报告默认 -->
+			<template v-if="reportCoopType===2&&!selectChapterId">
+				<div style="padding-top: 20%;">
+					<tableNoData :text="$t('Common.no_cont_msg')"/>
+				</div>
+			</template>
+
+			<!-- 章节报告预览 -->
+			<template v-else-if="reportCoopType===2&&selectChapterId&&!editChapterId">
+				<div>
+					<reportDetail
+						v-if="reportInfo.ReportChapterId"
+						:info="reportInfo"
+					/>
+				</div>
+			</template>
+
+			<!-- 非章节报告或章节报告编辑 -->
+			<template v-else>
+					<!-- 顶部操作栏 -->
+					<editHeader
+						:isApprove="isApprove"
+						:hasApproveFlow="hasApproveFlow"
+						:reportInfo="reportInfo"
+						@handleClearContent="handleClearContent"
+						@openBaseInfo="showReportBaseInfo=true"
+						@handleRefreshAllChart="refreshReport"
+						@handlePreviewReport="reportInfo.ReportChapterId?handlePreviewChapter():handlePreviewReport()"
+						@handleSaveContent="reportInfo.ReportChapterId?handleAutoSaveChapter('save'):handleAutoSave('save')"
+						@handlePublishOpt="(type) =>{reportInfo.ReportChapterId?handlePublishChapter():handlePublishReport(type)}"
+						@update="()=>{$refs.chapterContRef&&$refs.chapterContRef.getChapterList()}"
+					/>
+
+					<div class="editor-main">
+						<div 
+							id="leftfroala"
+							v-loading="importChartNum>0" 
+							:element-loading-text="$t('ReportManage.ReportList.chart_insertion_progress')"
+							element-loading-spinner="el-icon-loading"
+							element-loading-background="rgba(0, 0, 0, 0.8)"
+						>
+							<froala
+								ref="froalaEditor"
+								:tag="'textarea'"
+								:config="CNEditorConfig"
+								v-model="reportInfo.Content"
+							></froala>
+						</div>
+
+						<!-- 可插入内容 -->
+						<insertContent
+							v-show="activeTab"
+							:actTab="activeTab"
+							@slide="activeTab=''"
+							@insertHtml="insertHtml"
+							@handleImportMyChart="handleImportMyChart"
+						/>
+						
+					</div>
+
+					<!-- 可插入模块 -->
+					<ul class="fixed-insert-wrapper">
+							<li v-for="item in insertTabs" :key="item.type" @click="activeTab=item.type">
+								<img class="icon" :src="item.icon" alt="">
+								<span>{{item.name}}</span>
+							</li>
+					</ul>
+			</template>
+
+		</div>
+
+
+		<!-- 报告基础信息 -->
+    <reportBaseInfo  
+			v-model="showReportBaseInfo" 
+			:reportInfo="reportCoopType===2?($refs.chapterContRef&&$refs.chapterContRef.reportBase):reportInfo" 
+			:id="$route.query.id"
+			@save="handleReportEdit"
+		/>
+
+		<!-- 定时发布弹窗 -->
+		<el-dialog 
+			v-dialogDrag 
+			:append-to-body="true" 
+			:visible.sync="showDSFB" 
+			width="500px" 
+			:title="$t('ReportManage.ReportList.scheduled_publish_btn')"
+		>
+			<div>
+				<div>
+					<span>{{$t('ReportManage.ReportList.publish_time')}}</span>
+					<el-date-picker
+						v-model="taskTime"
+						type="datetime"
+						:placeholder="$t('ReportManage.ReportList.select_date_and_time')"
+						value-format="yyyy-MM-dd HH:mm"
+						:picker-options="timePickerOpt"
+					/>
+				</div>
+				<p style="margin:15px 0">{{$t('ReportManage.ReportList.the_report_will_be_posted_on_time')}}</p>
+				<div style="text-align:right;margin:20px 0">
+					<el-button type="primary" plain @click="showDSFB=false">{{$t('Dialog.cancel_btn')}}</el-button>
+					<el-button type="primary" @click="handleSetReportPrepublish">{{$t('Dialog.confirm_btn')}}</el-button>
+				</div>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import {
+	autosave,
+	reportedit,
+	reportdetail,
+	classifylist,
+	reportpublish,
+	reportSetPrepublish,
+	reportV2Interface,
+	chapterDetail,
+	saveChapterReport,
+	publishChapterReport,
+	getChapterReportIsLast,
+	reportMessageSend
+} from '@/api/modules/reportV2';
+import { getPublicSettingsApi } from '@/api/modules/oldApi';
+import http from '@/api/http.js';
+import mixinMsg from './mixins/messagePush'
+import reportMixin from './mixins/reportMixin';
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+import editHeader from '../components/reportEditHeader.vue';
+import insertContent from './components/insertContent.vue';
+import chapterWrapper from '../components/chapterEditWrapper.vue'
+import reportBaseInfo from '../components/reportBaseInfoDia.vue';
+import reportDetail from '../normalReport/reportdtl.vue';
+export default {
+	mixins:[ mixinMsg,reportMixin,reportApproveConfig ],
+	components: { editHeader,insertContent,chapterWrapper,reportBaseInfo,reportDetail },
+	data() {
+		var that = this;
+		return {
+			//批量导入图表
+			importChartNum:0,//批量导入图表的数量 如果大于0则说明在加载
+			report_id: this.$route.query.id,
+			reportCoopType: 0,//协作类型 1单人 2章节报告
+			selectChapterId: 0, //选中章节Id
+      editChapterId: 0,//编辑章节Id
+
+			reportInfo: {}, //个人报告详情或章节报告详情
+
+			optionsArr: [],
+
+			lastEditRange: null,
+			lastsavetime: '',
+			ThsMsgIsSend:'',//是否推送过客群
+
+			showReportBaseInfo: false,
+
+			isLeftWrapShow: true,//展开章节区
+		};
+	},
+	created() {
+		this.reportCoopType = Number(this.$route.query.coopType)
+		this.getPublicSettings()
+	},
+	mounted() {
+		
+		if(this.reportCoopType===1) {	
+			this.getreportdetail();
+			this.timer = setInterval(() => {
+				this.handleAutoSave();
+			}, 6000);
+		}
+
+		window.addEventListener('message',this.reInitIframe)
+	},
+	updated() {
+		$('#leftfroala').find('p').css({ fontSize: '16px',width:'100%'});
+	},
+	destroyed() {
+		window.removeEventListener('message',this.reInitIframe)
+		if (this.timer) {
+			clearInterval(this.timer);
+		}
+	},
+
+	methods: {
+		/* 当前章节信息 */
+		handleChapterInfo({ selectChapterId,editChapterId }) {
+			this.timer && clearInterval(this.timer);
+			
+			this.selectChapterId = selectChapterId;
+			this.editChapterId = editChapterId;
+			this.activeTab='';
+			
+			this.getChapterDetail()
+		},
+
+		/* 获取章节报告详情 */
+		async getChapterDetail() {
+			if(!this.selectChapterId) return
+
+			const res = await chapterDetail({
+				ReportChapterId: this.selectChapterId
+			})
+			
+			if(res.Ret !== 200) return
+			this.reportInfo = res.Data;
+			
+			$('.editor-wrapper')[0].scrollTop = 0;
+			if(this.editChapterId) {
+				this.timer = setInterval(() => {
+					this.handleAutoSaveChapter();
+				}, 6000);
+			}
+		},
+
+		/* 章节自动保存 存草稿*/
+		async handleAutoSaveChapter(type='auto') {
+			
+			if(!this.reportInfo.ReportChapterId||!this.editChapterId) return
+
+			if(!$('.fr-element')[0]){
+					this.timer && clearInterval(this.timer);
+					return
+			}
+
+			//如果富文本中有未上传完成的图片,去除这个dom
+			$('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
+			const res = await saveChapterReport({
+				ReportChapterId: this.reportInfo.ReportChapterId,
+				// Title: this.reportInfo.Title,
+				Content: $('.fr-element').html()
+			})
+			if(res.Ret !== 200) return 
+
+			this.lastsavetime = http.dateFormatter(new Date(), true);
+			type==='save' && this.$message.success(res.Msg);
+		},
+
+		/* 章节预览 */
+		handlePreviewChapter() {
+
+      sessionStorage.setItem("reportdtl", JSON.stringify({
+				...this.reportInfo,
+				Abstract:''
+			}));
+      let { href } = this.$router.resolve({ path: "/reportdtlV2" });
+      window.open(href, "_blank");
+		},
+
+		/* 单章节发布 */
+		async handlePublishChapter() {
+			if(!$('.fr-element').html()) return this.$message.warning(/* '请输入报告内容' */this.$t('ReportManage.ReportList.report_empty_msg'))
+
+			//如果富文本中有未上传完成的图片,去除这个dom
+			$('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
+
+			const res = await publishChapterReport({
+        ReportChapterId: this.reportInfo.ReportChapterId
+      });
+      if (res.Ret === 200) {
+        this.$message.success(this.$t('MsgPrompt.submit_msg'))
+				
+				this.$refs.chapterContRef&&this.$refs.chapterContRef.getChapterList()
+
+				// this.$refs.chapterContRef.handleMarkOver(this.reportInfo.ReportChapterId)
+        // setTimeout(() => {
+				// 	this.timer && clearInterval(this.timer);
+        //   this.$router.replace({ path: '/reportNew' });
+        // }, 1000);
+      }
+		},
+
+
+		handleCheckClassifyNameArr(arr){
+			this.checkClassifyNameArr(1,arr)
+		},
+		// 编辑基础信息
+		handleReportEdit(e){
+
+				const params={
+						...e,
+						ReportId: parseInt(this.report_id)
+				}
+				
+				console.log(params);
+				//检查classifynameArr是否有审批流
+				let classify = [e.ClassifyIdFirst,e.ClassifyIdSecond,e.ClassifyIdThird]
+				this.handleCheckClassifyNameArr(classify)
+
+				reportedit(params).then(res=>{
+						if(res.Ret===200){
+								this.$message.success(this.$t('MsgPrompt.saved_msg'))
+
+								if(this.reportCoopType === 1) {
+									this.reportInfo.Title=params.Title;
+									this.reportInfo.ClassifyIdFirst=params.ClassifyIdFirst;
+									this.reportInfo.ClassifyIdSecond=params.ClassifyIdSecond;
+									this.reportInfo.ClassifyIdThird=params.ClassifyIdThird;
+									this.reportInfo.ClassifyNameFirst=params.ClassifyNameFirst;
+									this.reportInfo.ClassifyNameSecond=params.ClassifyNameSecond;
+									this.reportInfo.ClassifyNameThird=params.ClassifyNameThird;
+									this.reportInfo.Abstract=params.Abstract;
+									this.reportInfo.Author=params.Author;
+									this.reportInfo.CreateTime=params.CreateTime;
+									this.reportInfo.IsPublicPublish=params.IsPublicPublish;
+								}else {
+									this.$refs.chapterContRef.getReportBaseInfo('notCheck')
+								}
+								
+								this.showReportBaseInfo=false
+						}
+				})
+		},
+
+		/* 预览 */
+		handlePreviewReport() {
+			//如果富文本中有未上传完成的图片,去除这个dom
+			$('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
+
+			let { href } = this.$router.resolve({
+				path: '/reportdtlV2',
+				query:{
+					id:this.$route.query.id
+				}
+			});
+			window.open(href, '_blank');
+		},
+
+		// 每十秒自动保存 存草稿
+		handleAutoSave(type='auto') {
+
+			if(!this.autoSaveFlag) return
+			//如果富文本中有未上传完成的图片,去除这个dom
+			$('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
+			return new Promise((resolve,reject)=>{
+				autosave({
+					ReportId: Number(this.$route.query.id),
+					Content: $('.fr-element').html(),
+					NoChange:this.ischange?0:1
+				}).then((res) => {
+					if (res.Ret === 200) {
+						resolve(true)
+
+						this.lastsavetime = http.dateFormatter(new Date(), true);
+						type==='save' && this.$message.success(res.Msg);
+					}
+				});
+				this.ischange = false;
+			})
+		},
+
+		/* 报告详情 */
+		async getreportdetail() {
+			
+			const res = await reportdetail({ ReportId: parseInt(this.report_id) })
+
+			if (res.Ret !== 200) return
+			this.reportInfo = res.Data;
+			
+			let data = res.Data;
+
+			this.ThsMsgIsSend=data.MsgIsSend
+			// 回显定时发布时间
+			if(data.PrePublishTime){
+				this.taskTime=data.PrePublishTime
+			}
+			let classify = [data.ClassifyIdFirst,data.ClassifyIdSecond,data.ClassifyIdThird]
+			this.handleCheckClassifyNameArr(classify)
+		},
+		
+		/* 发布报告 */
+		async handlePublishReport(tp) {
+
+			const saveRes = await this.handleAutoSave('auto');
+			if(!saveRes) return
+
+			if(tp==='dsfb'){
+        this.showDSFB=true
+				return
+			}else if(tp==='submit'){
+				this.handleSubmitReport(Number(this.$route.query.id))
+				return
+			}
+
+			this.isPublishloading = true;
+
+			let sendMsg = this.reportCoopType===2 ? this.$refs.chapterContRef.reportBase.MsgIsSend : this.ThsMsgIsSend;
+			if(sendMsg===1){
+				this.publishreport({sendMsg: false})
+			}else {
+				const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)
+
+				this.$confirm(
+						isPost?this.$t('ReportManage.smart_msg.publishing_messages'):this.$t('ReportManage.smart_msg.should_published_immediately'), 
+						this.$t('ReportManage.smart_release_prompt_btn'), 
+						{
+								confirmButtonText: isPost?this.$t('ReportManage.smart_btn.push'):this.$t('ReportManage.smart_btn.publish'),
+								cancelButtonText: isPost?this.$t('ReportManage.smart_btn.not_push'):this.$t('Dialog.cancel_btn'),
+								type: 'warning',
+								distinguishCancelAndClose:true,
+						
+								beforeClose:(action, instance,done)=>{
+										if(action==='close') {
+												//右上角
+												this.isPublishloading = false;
+										} else if(action==='cancel') {
+												//cancelButton
+												if(isPost) this.publishreport({sendMsg: false});
+										}else {
+												//confirmButton
+												this.publishreport({sendMsg: isPost?true:false})
+										}
+										done()
+								}
+						}
+				)
+
+			}
+		},
+
+		//发布报告
+		publishreport({sendMsg}) {
+			reportpublish({ 
+				ReportIds: String(this.$route.query.id),
+				ReportUrl:this.generatePdfLinks()
+			}).then((res) => {
+				this.isPublishloading = false;
+
+				if (res.Ret !== 200) return
+
+				sendMsg && reportMessageSend({ReportId: Number(this.$route.query.id)})
+
+				this.$message.success(this.$t('MsgPrompt.publish_msg'))
+				setTimeout(() => {
+					this.$router.replace({ path: '/reportNew' });
+				},1000)
+			});
+		},
+
+		generatePdfLinks(){
+			const baseUrl= localStorage.getItem('dynamicOutLinks') ? JSON.parse(localStorage.getItem('dynamicOutLinks')).ReportViewUrl : '';
+			let waterMarkStr= localStorage.getItem('waterMarkStr') || '';
+
+			let code = this.reportCoopType===2?this.$refs.chapterContRef&&this.$refs.chapterContRef.reportBase.ReportCode:this.reportInfo.ReportCode
+
+			return `${baseUrl}/reportshare_pdf?code=${code}&flag=${waterMarkStr}`
+		},
+
+		// 定时发布报告
+		handleSetReportPrepublish(){
+			if(!this.taskTime){
+				this.$message.warning(this.$t('ReportManage.smart_msg.select_push_time'))
+				return
+			}
+			const now=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+			if(this.$moment(this.taskTime).isBefore(now,'second')){
+				this.$message.warning(this.$t('ReportManage.smart_msg.than_current_time'))
+				return
+			}
+			// return console.log(this.reportCode,'reportCode');
+			// 如果改报告已经推送过模板消息
+			let sendMsg = this.reportCoopType===2 ? this.$refs.chapterContRef.reportBase.MsgIsSend : this.ThsMsgIsSend;
+			if(sendMsg===1){
+				reportSetPrepublish({
+					ReportId:Number(this.report_id),
+					PrePublishTime:this.taskTime,
+					PreMsgSend:0,
+					ReportUrl:this.generatePdfLinks()
+				}).then(res=>{
+					if(res.Ret===200){
+						this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+						this.$router.push({ path: '/reportNew' });
+					}
+				})
+				return
+			}
+			const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)
+
+			this.$confirm(isPost?this.$t('ReportManage.smart_msg.push_report_msg'):this.$t('ReportManage.smart_msg.is_push_timed'), this.$t('ReportManage.smart_release_prompt_btn'), {
+				confirmButtonText: isPost?this.$t('ReportManage.smart_btn.push'):this.$t('ReportManage.smart_btn.publish'),
+				cancelButtonText: isPost?this.$t('ReportManage.smart_btn.not_push'):this.$t('Dialog.cancel_btn'),
+				type: 'warning',
+				distinguishCancelAndClose:true,
+				beforeClose:(action, instance,done)=>{
+					console.log(action, instance);
+					if(action==='close'||action==='cancel') {
+						//右上角或者不推送
+						if(isPost){
+							reportSetPrepublish({
+								ReportId:Number(this.report_id),
+								PrePublishTime:this.taskTime,
+								PreMsgSend:0,
+								ReportUrl:this.generatePdfLinks()
+							}).then(res=>{
+								if(res.Ret===200){
+									this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+									this.$router.push({ path: '/reportNew' });
+								}
+							})
+						}
+					} else {
+						//confirmButton
+						reportSetPrepublish({
+							ReportId:Number(this.report_id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:isPost?1:0,
+							ReportUrl:this.generatePdfLinks()
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+								this.$router.push({ path: '/reportNew' });
+							}
+						})
+					}
+					done()
+				}
+			})
+
+		},
+
+		getclassifylist() {
+			//获取分类列表
+			let params = { CurrentIndex: 1, PageSize: 1000, KeyWord: ''  };
+			classifylist(params).then((res) => {
+				if (res.Ret == 200 && Array.isArray(res.Data.List)) {
+					this.optionsArr = [];
+					res.Data.List.forEach((item, index) => {
+						let newitem = {
+							label: item.ClassifyName,
+							value: JSON.stringify({
+								l: item.ClassifyName,
+								v: parseInt(item.Id),
+							}),
+							HasTeleconference:item.HasTeleconference
+						};
+						if (item.Child&&item.Child.length > 0) {
+							let childnode = [];
+							item.Child.forEach((itemchild, i) => {
+								childnode.push({
+									label: itemchild.ClassifyName,
+									value: JSON.stringify({
+										l: itemchild.ClassifyName,
+										v: parseInt(itemchild.Id),
+									}),
+									HasTeleconference:itemchild.HasTeleconference
+								});
+							});
+							newitem.children = childnode;
+						} else {
+							newitem.children = undefined;
+							newitem.disabled=true
+						}
+						this.optionsArr.push(newitem);
+					});
+				}
+			});
+		},
+
+		/* 获取动态配置 外部动态链接 */
+		async getPublicSettings() {
+				const res =  await getPublicSettingsApi();
+				if(res.Ret !== 200) return
+				
+				this.$store.commit('SET_DYNAMIC_LINK',res.Data)
+		},
+	},
+};
+</script>
+
+<style scoped lang="scss">
+#editreport {
+	display: flex;
+	overflow: hidden;
+	background: var(--unnamed, #F2F6FA);
+	.editor-wrapper {
+		position: relative;
+		flex: 1;
+		height: 100vh;
+		overflow: auto;
+		.top-action-wrap{
+				position: sticky;
+				top: 0;
+				background-color: #fff;
+				box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.10);
+				height: 60px;
+				z-index: 99;
+				display: flex;
+				justify-content: space-between;
+				align-content: center;
+				padding: 0 24px;
+				margin-bottom: 10px;
+				.title{
+						line-height: 60px;
+						font-size: 16px;
+				}
+				.action-list{
+						display: flex;
+						align-items: center;
+						.action-item{
+								height: 36px;
+								display: flex;
+								align-items: center;
+								border-right: 1px solid #C8CDD9;
+								padding: 0 30px;
+								font-size: 16px;
+								cursor: pointer;
+								img{
+										width: 16px;
+										height: 16px;
+										margin-right: 4px;
+										position: relative;
+										top: 2px;
+								}
+								&:last-child{
+										border-right: none;
+								}
+								&.disabled{
+										pointer-events: none;
+										cursor: not-allowed;
+										color:#999;
+								}
+						}
+				}
+		}
+		.editor-main {
+			display: flex;
+			padding: 20px 120px 20px 20px;
+		}
+	}
+	#leftfroala {
+		min-width: 500px;
+		width: 800px;
+		margin: 0 auto;
+		overflow: hidden;
+	}
+
+	.left-wrap {
+		position: relative;
+		.slide-btn-icon {
+			&.slide-left{
+					right:5px;
+					left: auto;
+			}
+			&.slide-right{
+					left: 0;
+					right: auto;
+			}
+		}
+	}
+
+	.fixed-insert-wrapper {
+		width: 90px;
+		background: #fff;
+		position: fixed;
+		right: 20px;
+		top: 10%;
+		li {
+			/* width: 100px; */
+			padding: 15px;
+			text-align: center;
+			cursor: pointer;
+			&:hover {
+				background: #dde1e4;
+			}
+			.icon {
+				display: block;
+				margin: 0 auto;
+			}
+		}
+
+	}
+}
+</style>
+<style lang="scss">
+#editreport {
+	.el-tabs__nav-wrap::after {
+		height: 0;
+	}
+	.el-tabs__item { font-size: 16px; }
+}	
+</style>

+ 115 - 0
src/views/report_manage/reportV2/normalReport/mixins/messagePush.js

@@ -0,0 +1,115 @@
+import { reportedit,reportMessageSend } from "@/api/modules/reportV2";
+import { dataBaseInterface } from '@/api/api';
+import {approveInterence} from '@/api/modules/approve.js';
+import * as sheetInterface from '@/api/modules/sheetApi.js';
+import { getUrlParams } from '@/utils/common'
+export default {
+  data() {
+    return {
+      isMessagePost: false,
+      isRightFormShow:true,
+      reportCode:''
+    };
+  },
+  methods: {
+
+    //刷报告中的所有图表和表格
+    refreshReport: _.debounce ( async function() {
+      let code_arr = [];
+      let sheet_code_arr = []
+      $('iframe').each((k,i) => {
+        try {
+          let href = $(i).attr('src');
+          if(href.includes('chartshow')){
+            code_arr.push(getUrlParams(href,'code'));
+          }
+          if(href.includes('sheetshow')){
+            sheet_code_arr.push(getUrlParams(href,'code'))
+          }
+        } catch (err) {
+        }
+      });
+
+      if(!code_arr.length&&!sheet_code_arr.length) return this.$message.warning(this.$t('ReportManage.smart_msg.chart_is_table_msg'))
+
+      const fromPage = "report";
+      if(this.$route.query.id&&code_arr.length) {
+        let res = await dataBaseInterface.getReportrefreshStatus({
+          Source: fromPage,
+          PrimaryId: Number(this.$route.query.id),
+          SubId: this.reportInfo.ReportChapterId
+        });
+        
+        if(!res.Data.RefreshResult) return this.$message.warning(this.$t('ReportManage.ReportList.chart_refreshed_msg'))
+        const { Ret,Msg } = await dataBaseInterface.reportRefresh({
+            ChartInfoCode: code_arr,
+            Source: fromPage,
+            PrimaryId: Number(this.$route.query.id),
+            SubId: this.reportInfo.ReportChapterId
+          })
+          
+          if(Ret === 200) {
+            $('iframe').each((k,i) => {
+                let href = $(i).attr('src');
+                if(href.includes('chartshow')){
+                    $(i).attr('src',$(i).attr('src'))
+                }
+            });
+            this.$message.success(Msg);
+          }
+      }
+
+      if(this.$route.query.id&&sheet_code_arr.length){
+        //获取刷新结果
+        let res = await sheetInterface.getRefreshResult({
+            Source: fromPage,
+            PrimaryId: Number(this.$route.query.id),
+            SubId: this.reportInfo.ReportChapterId
+          });
+        if(!res.Data.RefreshResult) return this.$message.warning(this.$t('ReportManage.ReportList.chart_refreshed_msg'))
+        const { Ret,Msg } = await sheetInterface.refreshSheet({
+            ExcelCodes: sheet_code_arr,
+            Source: fromPage,
+            PrimaryId: Number(this.$route.query.id),
+            SubId: this.reportInfo.ReportChapterId
+          })
+          
+          if(Ret === 200) {
+            $('iframe').each((k,i) => {
+                let href = $(i).attr('src');
+                if(href.includes('sheetshow')){
+                    $(i).attr('src',$(i).attr('src'))
+                }
+            });
+            this.$message.success(Msg);
+          }
+      }
+    },1000),
+
+    //展示提交审批弹窗
+    handleSubmitReport(id){
+        this.submitId = id
+        this.$confirm(this.$t('ReportManage.smart_msg.submit_approval'),this.$t('Confirm.prompt'),{
+          confirmButtonText: this.$t('Dialog.confirm_btn'),
+          cancelButtonText: this.$t('Dialog.cancel_btn'),
+          type:'warning',
+        }).then(()=>{
+            this.submitReport("submit")
+        }).catch(()=>{})
+        
+    },
+    //提交审批
+    submitReport(type){
+        /* if(type==='submit'){ */
+            approveInterence.reportCnSubmit({
+                ReportId:Number(this.submitId)
+            }).then(res=>{
+                if(res.Ret!==200) return
+                this.$message.success(this.$t('ReportManage.smart_msg.submit_success'))
+                this.isPublishloading = false;
+                this.$router.push({ path: '/reportNew' });
+            })
+        /* } */
+    }
+  },
+};

+ 368 - 0
src/views/report_manage/reportV2/normalReport/mixins/reportMixin.js

@@ -0,0 +1,368 @@
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import { dataBaseInterface } from "@/api/api.js";
+import futuresInterface from "@/api/modules/futuresBaseApi";
+import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
+import {
+  fittingEquationInterface,
+  statisticFeatureInterface,
+  crossVarietyInterface
+} from "@/api/modules/chartRelevanceApi";
+export default {
+  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';
+	        }
+		},
+  },
+  computed:{
+      CNEditorConfig(){
+          return {...this.froalaConfig,...{fontFamily:{'Arial,Helvetica,sans-serif': 'Arial',
+          'Georgia,serif': 'Georgia',
+          'Impact,Charcoal,sans-serif': 'Impact',
+          'Tahoma,Geneva,sans-serif': 'Tahoma',
+          "'Times New Roman',Times,serif": 'Times New Roman',
+          'Verdana,Geneva,sans-serif': 'Verdana',
+          '思源宋体':'思源宋体',
+          '思源黑体':'思源黑体',}}
+        }
+      },
+      insertTabs(){
+        return [
+            {
+              name:this.$t('ReportManage.ReportList.chart_top_type'),
+              type:'etaChart',
+              icon:require('@/assets/img/smartReport/icon04.png')
+            },
+            {
+                name:this.$t('ReportManage.ReportList.eta_top_type'),
+                type:'etaSheet',
+                icon:require('@/assets/img/smartReport/icon05.png')
+            },
+            {
+                name:this.$t('ReportManage.ReportList.statistical_top_type'),
+                type:'statisticAnalysis',
+                icon:require('@/assets/img/smartReport/icon06.png')
+            },
+            {
+                name:this.$t('ReportManage.ReportList.price_curve_radio'),
+                type:'etaPriceChart',
+                icon:require('@/assets/img/smartReport/icon07.png')
+            },
+            {
+                name:this.$t('ReportManage.ReportList.sandbox_top_type'),
+                type:'etaSandBox',
+                icon:require('@/assets/img/smartReport/icon08.png')
+            },
+            {
+                name:this.$t('ReportManage.ReportList.semantic_top_type'),
+                type:'semanticAnalysis',
+                icon:require('@/assets/img/smartReport/icon09.png')
+            }
+          ]
+      },
+      
+      //语言版本
+      currentLang() {
+        return this.$store.state.lang
+      }
+  },
+  data() {
+    let that = this;
+    return {
+      editor: null,
+      froalaConfig: {
+        toolbarButtons: [
+          "insertImage",
+          "insertVideo",
+          "insertLink",
+          "embedly",
+          "insertFile",
+          "textColor",
+          "bold",
+          "italic",
+          "underline",
+          "strikeThrough",
+          "subscript",
+          "superscript",
+          "fontFamily",
+          "fontSize",
+          "color",
+          "inlineClass",
+          "inlineStyle",
+          "paragraphStyle",
+          "lineHeight",
+          "paragraphFormat",
+          "align",
+          "formatOL",
+          "formatUL",
+          "outdent",
+          "indent",
+          "quote",
+          "insertTable",
+          "emoticons",
+          "fontAwesome",
+          "specialCharacters",
+          "insertHR",
+          "selectAll",
+          "clearFormatting",
+          /* "html", */
+          "undo",
+          "redo",
+        ],
+        height: 800,
+        fontSize: ["12", "13","14","15", "16", "18", "20", "24", "28", "32", "36", "40"],
+        fontSizeDefaultSelection: "16",
+        theme: "dark", //主题
+        placeholderText: localStorage.getItem('i18n') == 'en' ? 'Please input content' : "请输入内容",
+        language: localStorage.getItem('i18n') == 'en' ? 'en' : "zh_cn", //国际化
+        imageUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url
+        videoUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url
+        fileUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url 更多上传介绍 请访问https://www.froala.com/wysiwyg-editor/docs/options
+        imageDefaultWidth: false,
+        quickInsertButtons: ["image", "table", "ul", "ol", "hr"], //快速插入项
+        toolbarVisibleWithoutSelection: true, //是否开启 不选中模式
+        // disableRightClick:true,//是否屏蔽右击
+        // colorsHEXInput:false,//关闭16进制色值
+        toolbarSticky: false, //操作栏是否自动吸顶
+        // zIndex:99999,
+        saveInterval: 0,
+        events: {
+          //this.editor 定义在vue data 中
+          initialized: function () {
+            that.editor = this;
+          },
+          keyup: function (e, editor) {
+            //添加事件,在每次按键按下时,都记录一下最后停留位置
+            that.$nextTick(function () {
+              getSelection().rangeCount &&
+                (that.lastEditRange = getSelection().getRangeAt(0));
+            });
+          },
+          click: function (e, editor) {
+            //添加事件,在每次鼠标点击时,都记录一下最后停留位置
+            that.$nextTick(function () {
+              getSelection().rangeCount &&
+                (that.lastEditRange = getSelection().getRangeAt(0));
+            });
+          },
+          //内容改变事件
+          contentChanged: function () {
+            that.ischange = true;
+            that.lastEditRange = getSelection().rangeCount
+              ? getSelection().getRangeAt(0)
+              : 0;
+          },
+          //粘贴图片上传事件
+          "image.beforePasteUpload": function (img) {
+            //console.log('image.beforePasteUpload',img)
+            //暂停自动保存
+            that.autoSaveFlag = false;
+          },
+          //点击toolbar上传图片事件
+          "image.beforeUpload": function (imgs) {
+            //console.log('image.beforeUpload',imgs)
+            //暂停自动保存
+            that.autoSaveFlag = false;
+          },
+          "image.inserted": function ($img, response) {
+            //console.log('img-inserted',$img)
+            //开启自动保存
+            that.autoSaveFlag = true;
+          },
+          //如果上传图片出错,重置autoSaveFlag
+          "image.error": function (error, response) {
+            that.autoSaveFlag = true;
+          },
+          "paste.before":function(e,editor){
+            let content = e.clipboardData.getData('text/html');
+           // console.log(content)
+            var tempDiv = document.createElement('div');
+            tempDiv.innerHTML = content;
+            var iframes = tempDiv.querySelectorAll('iframe');
+            const srcArr = Array.from(iframes).map(i=>i.src)
+            //console.log(srcArr);
+            if(srcArr.filter(i=>!i.includes(that.$setting.dynamicOutLinks.ChartViewUrl)).length){
+                that.$message.warning("粘贴内容含有外链,请核对内容或粘贴纯文本")
+                return false
+            }
+          },
+        },
+        charCounterCount: false,
+        reportloadding: false,
+        lastsavetime: "",
+        isAddEnter: false, //是否已经添加过
+        timer: null,
+        ischange: false,
+        isPublishloading: false,
+      },
+
+      isPublishloading: false,
+      lastsavetime: "",
+
+      setEnName: false,
+      // 传入的formItem所需内容
+      formItemArray: [],
+      
+      activeTab: '',
+      chart_source: 1, //图表来源 1 eta 2 商品价格...
+
+      //截面散点设置英文props
+      enChartInfo: {},
+      enEdblist: [],
+
+      autoSaveFlag: true, //是否开启自动保存
+
+      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'
+			},
+    };
+  },
+
+  methods: {
+    insertHtml({item, type = "chart"}) {
+      const noAuthMsg = {
+        'chart': this.$t('MsgPrompt.no_chart_auth'),
+        'sheet': this.$t('MsgPrompt.no_sheet_auth')
+      }
+      if(!item.HaveOperaAuth&&noAuthMsg[type]) return this.$message.warning(noAuthMsg[type])
+
+      //设置编辑器获取焦点
+      this.editor.events.focus();
+      // 获取选定对象
+      const selection = getSelection();
+      // 判断是否有最后光标对象存在
+      if (this.lastEditRange) {
+        // 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态
+        selection.removeAllRanges();
+        selection.addRange(this.lastEditRange);
+      }
+
+      const insertMap = {
+        image: this.insertImage,
+        chart: this.insertChart,
+        sheet: this.insertSheet,
+      };
+      insertMap[type](item);
+      this.lastEditRange = selection.getRangeAt(0);
+    },
+
+    /* 插入图片 */
+    insertImage(item) {
+      this.$nextTick(() => {
+        this.editor.html.insert(
+          `<img style='width:100%' src='${item.PicUrl}' />`
+        );
+      });
+    },
+
+    /* 插入图表 */
+    insertChart(item) {
+      if (item.Disabled)
+        return this.$message.warning("内部图表,不允许插入报告");
+
+      const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+      let lang = this.$route.path === "/reportEnEditor" ? "en" : this.currentLang;
+      
+      this.$nextTick(() => {
+        this.editor.html.insert(
+          `<p style='text-align:left; margin-top:10px;'>
+						<iframe src='${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${lang}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+					</p>`
+        );
+      });
+    },
+
+    /* 插入表格 */
+    insertSheet(item) {
+      const LINK_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/sheetshow';
+
+      this.$nextTick(() => {
+        this.editor.html.insert(
+          `<p style='text-align:left; margin-top:10px;'>
+            <span style='font-size:17px;padding-left:10px;'>${item.ExcelName}</span>
+            <iframe 
+              src='${LINK_URL}?code=${item.UniqueCode}&fromScene=2' 
+              width='100%' 
+              class='iframe${item.UniqueCode}' 
+              style='border-width:0px;'
+              />
+              </p>`
+        );
+      });
+    },
+
+    /* 适配iframe高度 */
+    reInitIframe(e) {
+      const { height, code } = e.data;
+      let iframeDom = document.getElementsByClassName(`iframe${code}`);
+      iframeDom.forEach((ele) => {
+        ele.height = `${height}px`;
+      });
+    },
+
+    //批量插入我的图表
+		handleImportMyChart(data){
+      console.log(data)
+			//设置编辑器获取焦点
+			this.editor.events.focus();
+			// 获取选定对象
+			const selection = getSelection();
+			// 判断是否有最后光标对象存在
+			if (this.lastEditRange) {
+				// 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态
+				selection.removeAllRanges();
+				selection.addRange(this.lastEditRange);
+			}
+			//插入内容
+			let htmlStr=''
+			const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+			
+			data.forEach(item=>{
+				const t=new Date().getTime()
+				item.domId=item.UniqueCode+t //避免多次添加同一图表 id相同
+				htmlStr=htmlStr+`<p style='text-align:left; margin-top:10px;'>
+							<iframe id='${item.domId}' src='${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${this.currentLang}' width='100%' height='350' style='border-width:0px; min-height:350px;'></iframe>
+						</p>`
+			})
+			this.$nextTick(()=>{
+				console.log('import start',data);
+				this.importChartNum=data.length
+				this.editor.html.insert(htmlStr)
+				this.handleListenIframeLoad(data)
+			})
+			
+			this.lastEditRange = selection.getRangeAt(0);
+		},
+		// 监听批量导入的iframe是否加载完
+		handleListenIframeLoad(list){
+			list.forEach(item=>{
+				let ifm=document.getElementById(item.domId)
+				ifm.onload=(e)=>{
+					this.importChartNum--
+				}
+			})
+		},
+
+    handleClearContent() {
+      this.reportInfo.Content = ''
+    }
+  },
+
+};

+ 229 - 0
src/views/report_manage/reportV2/normalReport/reportdtl.vue

@@ -0,0 +1,229 @@
+<template>
+	<div id="reportdtl" v-if="isshow">
+		<header>{{reportInfo.Title}}</header>
+		<div style="padding:0 35px 0; box-sizing:border-box; color:#666; font-size:24px; overflow:hidden;">
+		  <span>{{reportInfo.Author}}</span>
+		  <span style="float:right;" v-if="reportInfo.PublishState===2||reportInfo.State===2">{{reportInfo.PublishTime}}</span>
+		</div>
+		
+		<div id="abstract" v-if="reportInfo.Abstract">
+		  <div>摘要:{{reportInfo.Abstract}}</div>
+		</div>
+		<div id="resetsty" style="padding:30px; box-sizing:border-box; overflow:hidden;">
+			<!-- 章节报告 -->
+			<block v-if="reportInfo.CollaborateType===2">
+				<div class="chapter-item" v-for="item in reportInfo.ChapterList" :key="item.ReportChapterId">
+					<div style="margin-bottom:10px">
+						<span class="type" v-if="item.TypeName">{{item.TypeName}}</span>
+						<span class="title">{{item.Title}}</span>
+					</div>
+					<div id="resetcss" style="overflow:hidden;" v-html="item.Content"></div>
+				</div>
+			</block>
+
+			<!-- 单报告 -->
+			<block v-else>
+				<div id="resetcss" style="overflow:hidden;" v-html="reportInfo.Content"></div>
+			</block>
+		</div>
+		<div v-if="linkUrl" style="width:100px;height30px;position:absolute;right:-100px;top:100px;cursor:pointer;">
+			<div v-permission="$route.query.fromPage==='en'
+                ?permissionBtn.enReportManageBtn.enReport_reportView_copyWechat
+                :permissionBtn.reportManageBtn.reportManage_reportView_copyWechat"
+                style="display:flex;alignItems:center;color:#333;" :data-clipboard-text='linkUrl' @click="copyHandle" class="copy">
+				<img src="@/assets/img/icons/cop.png" alt="" style="width:30px;height:30px;marginRight:10px;">复制链接
+			</div>
+			<div v-permission="$route.query.fromPage==='en'
+                ?permissionBtn.enReportManageBtn.enReport_reportView_wechatShare
+                :permissionBtn.reportManageBtn.reportManage_reportView_wechartShare"
+                style="display:flex;alignItems:center;color:#333;marginTop:20px;"  @mouseenter="isShowCode=true" @mouseleave="isShowCode=false">
+				<img src="@/assets/img/icons/wechat.png" alt="" style="width:30px;height:30px;marginRight:10px;">微信分享
+			</div>
+			<vue-qr :text="linkUrl" :margin="0" colorDark="#333" colorLight="#fff" :dotScale="1" :size="100" style="position:absolute;right:0;top:100px;" v-if="isShowCode"></vue-qr>
+		</div>
+	</div>
+</template>
+
+<script>
+	import { reportdetail,departInterence } from 'api/api.js';
+	import http from '@/api/http.js';
+	import * as reportEnInterface from '@/api/modules/reportEnApi';
+	import {strategyReportInterence} from '@/api/api.js'
+	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){
+					// 设置水印文案
+					let waterMarkStr= localStorage.getItem('waterMarkStr') || '';
+					
+					if(this.$route.query.fromPage == 'en'){
+						str=`${baseUrl}/reportshare_crm_report_en?code=${this.$route.query.code}&flag=${waterMarkStr}`
+					}else{
+						str=`${baseUrl}/reportshare_crm_report?code=${this.$route.query.code}&flag=${waterMarkStr}`
+					}
+				}
+				
+				return str
+			}
+		},
+		props:{
+			reportId:{ //审批详情-预览报告
+				type:Number,
+				default:0
+			},
+			info: {
+				type:Object
+			},
+			isEn:{
+				type:Boolean,
+				default:false
+			}
+		},
+		watch:{
+			info(nval) {
+				this.reportInfo = nval
+			}
+		},
+		data() {
+			return {
+				id:parseInt(this.$route.query.id),
+				isshow:false,
+				reportInfo:{},
+				isShowCode:false,
+
+				systemUserInfo:null,
+			}
+		},
+		components: {
+			vueQr
+		},
+		mounted() {
+			//内嵌章节预览
+			if(this.info) {
+				this.reportInfo = this.info;
+				this.isshow=true;
+				return 
+			}
+
+			if(this.$route.query.id||this.reportId) {
+				this.getreportdetail();
+			}else {
+				let reportdtl=sessionStorage.getItem('reportdtl') || false;
+				this.reportInfo=JSON.parse(reportdtl);
+				console.info("reportInfo");
+				console.log(this.reportInfo);
+				this.isshow=true;
+			}
+		},
+		updated(){
+		  $('#resetcss').find('img').css({display:'block',margin:'0 auto'});
+		  $('#resetcss').find('video').css({display:'block',margin:'0 auto'});
+			$("#resetcss").find("pre").css({display: "block",whiteSpace: "pre-wrap"});
+		},
+		methods: {
+			async getreportdetail(){
+				let res
+				let reportId = this.id||this.reportId
+				this.$emit("reportStartLoading")
+				if((this.$route.query.fromPage == 'en'||this.isEn)){
+					res=await reportEnInterface.reportDetail({ReportId:parseInt(reportId)})
+				}else if(this.$route.query.fromPage == 'strategyReport'){
+					res=await strategyReportInterence.getReportDetail({Id:parseInt(reportId)})
+				}else{
+					res=await reportdetail({ReportId:parseInt(reportId)})
+				}
+				this.$emit("reportEndLoading")
+				if( res.Ret!==200 ){
+					this.$emit("reportError")
+					return 
+				}
+
+				this.reportInfo=res.Data;
+				this.isshow=true;
+			},
+			/* 复制链接 */
+			copyHandle() {
+				var clipboard = new this.Clipboard('.copy')
+				clipboard.on('success', e => {
+					this.$message.success(/* '复制链接成功' */this.$t('Chart.OptMsg.copy_link_success'))
+					e.clearSelection() // 释放内存
+					clipboard.destroy()
+				})
+				// // 浏览器不支持
+				clipboard.on('error', e => {
+					this.$message.warning(/* '浏览器暂不支持' */this.$t('MsgPrompt.browser_not_support'))
+					// 释放内存
+					clipboard.destroy()
+				})
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	#reportdtl{ background:#fff;  max-width:1200px; margin:10px auto;position:relative;
+		img{ display:'block'; width:'100%'; margin:'0 auto'; }
+		header{ padding:10px 30px; box-sizing:border-box; font-size:28px; font-weight:500; color:#333; background:#fff; }
+		#abstract{ padding:10px 30px 0; box-sizing:border-box; font-size:22px; line-height:36px;
+		  >div{ padding:10px 20px; box-sizing:border-box; background:rgba(20,121,253,0.1); color:#4099ef; border-radius:10px; }
+		}
+		#resetsty{ 
+			img{ display:block; max-width:100%; height:auto; margin:0 auto; }
+		}
+		table{ border-top:1px solid #eaeaea; border-left:1px solid #eaeaea; border-collapse:collapse; 
+			th,td{ border-right:1px solid #eaeaea; border-bottom:1px solid #eaeaea; padding:5px 10px; box-sizing:border-box; }
+		}
+
+		.chapter-item{
+			margin-bottom: 20px;
+			padding-bottom: 20px;
+			border-bottom: 1px dashed #ccc;
+			.type{
+				font-size: 15px;
+				color: #fff;
+				padding: 5px 10px;
+				background-color: #E6A23C;
+				border-radius: 4px;
+			}
+			.title{
+				font-size: 15px;
+				margin-left: 10px;
+				font-weight: bold;
+			}
+		}
+    #abstract-en{
+      margin:35px 35px;
+      padding:20px;
+      background-color: rgba(77, 130, 191, 0.1);
+      border: 1px solid #E2E2E2;
+      .abstract{
+        font-size: 24px;
+        font-weight: 600;
+        padding-bottom: 20px;
+        border-bottom: 1px solid #C1C1C1;
+      }
+      #overview{
+        margin-top:20px;
+        font-size: 24px;
+        .overview{
+          margin-top:20px;
+          font-size: 18px;
+        }
+      }
+    }
+		#resetcss{
+			p{
+				font-size: 18px !important;
+			}
+			span{
+				font-size: 18px !important;
+			}
+			ul,ol {
+				list-style-position: inside !important;
+			}
+		}
+	}
+</style>

+ 316 - 0
src/views/report_manage/reportV2/smartReport/components/BaseInfo.vue

@@ -0,0 +1,316 @@
+<template>
+    <el-dialog
+        :title="$t('ReportManage.ReportList.information_title')"
+        :visible.sync="show"
+        :modal-append-to-body="false"
+        :close-on-click-modal="false"
+        :center="true"
+        v-dialogDrag
+        custom-class="dialogclass"
+        width="440px"
+        @close="handleClose"
+    >
+        <el-form 
+            :model="formData" 
+            :rules="rules" 
+            ref="baseinfoForm"
+            class="baseinfo-form-wrap"
+        >  
+            <el-form-item prop="type">
+                <el-radio-group v-model="formData.type" :disabled="id" @change="handleUpdateBaseInfo">
+                    <el-radio :label="1">{{$t('ReportManage.ReportList.new_report_radio')}}</el-radio>
+                    <el-radio :label="2">{{$t('ReportManage.ReportList.inherit_report_radio')}}</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item prop="classify">
+                <el-cascader
+					ref="cascader"
+					:options="classifyArr"
+					v-model="formData.classify"
+					:placeholder="$t('ReportManage.ReportList.please_select_category')"
+					size="medium"
+                    style="width:340px"
+                    @change="handleUpdateBaseInfo"
+				/>
+            </el-form-item>
+            <el-form-item prop="title">
+                <el-input :placeholder="$t('ReportManage.ReportList.input_title_please')" v-model="formData.title" style="width:340px"></el-input>
+            </el-form-item>
+            <el-form-item prop="abstract">
+                <el-input type="textarea" :placeholder="$t('ReportManage.ReportList.please_input_abstract')" v-model="formData.abstract" style="width:340px"></el-input>
+            </el-form-item>
+            <el-form-item prop="author">
+				<el-select
+					v-model="formData.author"
+					multiple
+					:placeholder="$t('ReportManage.ReportList.please_select_author')"
+					size="medium"
+					style="width: 340px"
+				>
+					<el-option
+						v-for="(item, i) in authorlist"
+						:key="i"
+						:label="item.ReportAuthor"
+						:value="item.ReportAuthor"
+					></el-option>
+				</el-select>
+			</el-form-item>
+            <el-form-item prop="frequency">
+                <el-select
+					v-model="formData.frequency"
+					:placeholder="$t('ReportManage.ReportList.please_select_frequency')"
+					size="medium"
+					style="width: 340px"
+				>
+                    <el-option :label="$t('ReportManage.smart_annually')" :value="$t('ReportManage.smart_annually')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_semi_annually')" :value="$t('ReportManage.smart_semi_annually')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_quarterly')" :value="$t('ReportManage.smart_quarterly')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_monthly')" :value="$t('ReportManage.smart_monthly')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_bi_weekly')" :value="$t('ReportManage.smart_bi_weekly')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_weekly')" :value="$t('ReportManage.smart_weekly')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_daily')" :value="$t('ReportManage.smart_daily')"></el-option>
+                    <el-option :label="$t('ReportManage.smart_irregularly')" :value="$t('ReportManage.smart_irregularly')"></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item prop="time">
+                <el-date-picker
+					v-model="formData.time"
+					type="date"
+					value-format="yyyy-MM-dd"
+					:placeholder="$t('ReportManage.ReportList.please_select_date')"
+					size="medium"
+					:clearable="false"
+					style="width: 340px"
+				></el-date-picker>
+            </el-form-item>
+        </el-form>
+        <div style="text-align:center;margin-top:60px;margin-bottom:40px">
+            <el-button type="primary" plain style="width:120px" @click="handleClose">{{$t('Dialog.cancel_btn')}}</el-button>
+            <el-button type="primary" style="width:120px" @click="handleConfirm">{{$t('Dialog.confirm_btn')}}</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import {apiSmartReport}  from '@/api/modules/smartReport'
+export default {
+    name:"BaseInfo",
+    model:{
+        prop:'show',
+        event:'showChange'
+    },
+    props:{
+        show:{
+            type:Boolean,
+            default:false
+        },
+        id:{
+            type:Number,
+            default:0
+        }
+    },
+    watch: {
+        show(n){
+            if(!n){
+                this.formData.type=1
+                this.formData.classify=[]
+                this.formData.title=''
+                this.formData.abstract=''
+                this.formData.author=['投研团队']
+                this.formData.frequency='日度'
+                this.formData.time=this.$moment().format('YYYY-MM-DD')
+            }else{
+                if(this.id){
+                    apiSmartReport.reportDetail({
+                        SmartReportId:Number(this.id)
+                    }).then(res=>{
+                        if(res.Ret===200){
+                            this.formData.type=res.Data.AddType
+                            this.formData.classify=[res.Data.ClassifyIdFirst,res.Data.ClassifyIdSecond]
+                            this.formData.title=res.Data.Title
+                            this.formData.abstract=res.Data.Abstract
+                            this.formData.author=res.Data.Author ? res.Data.Author.split(',') : []
+                            this.formData.frequency=res.Data.Frequency
+                            this.formData.time=res.Data.CreateTime
+                        }
+                    })
+                }
+            }
+        }  
+    },
+    data() {
+        return {
+            
+            formData:{
+                type:1,
+                classify:[],
+                title:'',
+                abstract:'',
+                author:['投研团队'],
+                frequency:'日度',
+                time:this.$moment().format('YYYY-MM-DD')||''
+            },
+            classifyArr:[],
+            authorlist:[]
+        }
+    },
+    computed:{
+        rules(){
+            return {
+                type:[{ required: true, message: this.$t('ReportManage.ReportList.please_report_type_select'), trigger: 'change' }],
+                classify:[{ required: true, message: this.$t('ReportManage.ReportList.please_report_type_select'), trigger: 'change' }],
+                title:[{ required: true, message: this.$t('ReportManage.ReportList.please_report_title_input'), trigger: 'blur' }],
+            }
+        }
+    },
+    methods: {
+        handleClose(){
+            this.$emit('showChange', false)
+        },
+
+        handleConfirm(){
+            this.$refs.baseinfoForm.validate((valid)=>{
+                if(valid){
+
+                    const params={
+                        AddType: this.formData.type,
+                        ClassifyIdFirst: this.formData.classify[0]?this.formData.classify[0]:0,
+                        ClassifyNameFirst: '',
+                        ClassifyIdSecond:this.formData.classify[1]?this.formData.classify[1]:0,
+                        ClassifyNameSecond:'',
+                        Title: this.formData.title,
+                        Abstract: this.formData.abstract,
+                        Author:
+                            this.formData.author.length > 0
+                                ? this.formData.author.join(',')
+                                : '',
+                        Frequency: this.formData.frequency,
+                        CreateTime: this.formData.time,
+                    }
+                    this.classifyArr.forEach(item=>{
+                        if(item.value===params.ClassifyIdFirst){
+                            params.ClassifyNameFirst=item.label
+                            const arr=item.children||[]
+                            arr.forEach(_item=>{
+                                if(_item.value===params.ClassifyIdSecond){
+                                    params.ClassifyNameSecond=_item.label
+                                }
+                            })
+                        }
+                    })
+                    // 编辑
+                    if(this.id){
+                        this.$emit('save',params)
+                        return
+                    }
+                    apiSmartReport.reportAdd(params).then(res=>{
+                        if(res.Ret===200){
+                            this.handleClose()
+                            let { href } = this.$router.resolve({
+                                path: "/smartReportEdit",
+                                query: { id: res.Data.SmartReportId },
+                            });
+                            window.open(href, "_blank");
+                        }
+                    })
+
+                }
+            })
+        },
+
+        handleUpdateBaseInfo(){
+            if(this.formData.type===1){
+                if(this.formData.classify.length===2){
+                    this.formData.title=this.getSelectClassifyName()[1]
+                }
+                return
+            }
+            //获取上次报告
+            apiSmartReport.getLastReport({
+                ClassifyIdFirst:this.formData.classify[0],
+                ClassifyIdSecond:this.formData.classify[1]
+            }).then(res=>{
+                if(res.Ret!==200) return
+                if (res.Data == null) {
+					this.$message.warning(this.$t('ReportManage.ReportList.no_reports_msg'));
+					return false;
+				}
+                this.formData.title=res.Data.Title
+                this.formData.abstract=res.Data.Abstract
+                this.formData.author=res.Data.Author ? res.Data.Author.split(',') : ''
+                this.formData.frequency=res.Data.Frequency
+            })
+        },
+
+        // 获取选择的分类名称
+        getSelectClassifyName(){
+            let arr=[]
+            this.classifyArr.forEach(item=>{
+                if(this.formData.classify[0]&&item.value===this.formData.classify[0]){
+                    arr.push(item.label)
+                    if(item.children&&item.children.length>0){
+                        item.children.forEach(_item=>{
+                            if(this.formData.classify[1]&&_item.value===this.formData.classify[1]){
+                                arr.push(_item.label)
+                            }
+                        })
+                    }
+                }
+            })
+            return arr
+        },
+
+        // 获取分类
+        getclassifylist() {
+            let params = { Enabled:1, KeyWord: "",HideDayWeek:1,/*不显示晨报/周报*/ };
+            apiSmartReport.classifyList(params).then((res) => {
+                if (res.Ret == 200 && Array.isArray(res.Data.List)) {
+                    this.classifyArr = [];
+                    res.Data.List.forEach((item, index) => {
+                        let newitem = {
+                            label: item.ClassifyName,
+                            value: item.Id,
+                        };
+                        if (item.Child) {
+                            let childnode = [];
+                            item.Child.forEach((itemchild, i) => {
+                                childnode.push({
+                                    label: itemchild.ClassifyName,
+                                    value: itemchild.Id,
+                                });
+                            });
+                            newitem.children = childnode;
+                        }
+                        this.classifyArr.push(newitem);
+                    });
+                }
+            });
+        },
+        // 获取作者
+        getreportauthor() {
+			apiSmartReport.reportAuthor({}).then((res) => {
+				if (res.Ret == 200) {
+					this.authorlist = res.Data.List || [];
+				}
+			});
+		},
+    },
+    mounted(){
+        this.getclassifylist()
+        this.getreportauthor()
+    },
+}
+</script>
+
+<style lang="scss">
+.baseinfo-form-wrap{
+    .el-input{
+        width: 100%;
+    }
+    .el-form-item{
+        width: 340px;
+        margin-left: auto;
+        margin-right: auto;
+    }
+}
+</style>

+ 20 - 0
src/views/report_manage/reportV2/smartReport/components/ChartComp.vue

@@ -0,0 +1,20 @@
+<template>
+    <div 
+        class="report-comp-item chart-comp"
+        style="width:100%;height:100%;overflow: hidden;display:flex;flex-direction: column;"
+    >
+        <iframe :src="compData.content" style="flex:1;width:100%;height:100%;border-width:0px;"></iframe>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        compData:{}
+    }
+}
+</script>
+
+<style>
+
+</style>

+ 106 - 0
src/views/report_manage/reportV2/smartReport/components/ETAChart.vue

@@ -0,0 +1,106 @@
+<template>
+    <div class="eta-chart-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span :class="['item',activeType==='ETA图库'?'active':'']" @click="activeTypeChange('ETA图库')">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</span>
+                <span :class="['item',activeType==='MyETA'?'active':'']" @click="activeTypeChange('MyETA')">{{$t('MyEtaPage.tab_my')}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.chart_name')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    v-if="activeType==='ETA图库'"
+                    @input="handleETAChartSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <ImportETAChart ref="ETAChartWrap" v-if="activeType==='ETA图库'"/>
+            <ImportMyETAChart @handleImportMyChart="handleImportMyChart" v-if="activeType==='MyETA'"/>
+        </div>
+    </div>
+</template>
+
+<script>
+import ImportETAChart from './ImportETAChart.vue';
+import ImportMyETAChart from './ImportMyETAChart.vue';
+export default {
+    name:"ETAChartWrap",
+    components:{ImportETAChart,ImportMyETAChart},
+    data() {
+        return {
+            keyword:'',
+            activeType:'ETA图库',
+        }
+    },
+    methods: {
+        activeTypeChange(e){
+            if(this.activeType===e) return
+            this.activeType=e
+        },
+
+        handleETAChartSearch(){
+            this.$refs.ETAChartWrap.handleSearch(this.keyword)
+        },
+
+        handleImportMyChart(list){
+            this.$emit('handleImportMyChart',list)
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.eta-chart-wrap{
+    width: 100%;
+    min-width: 600px;
+    overflow-x: auto;
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .left-card{
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            align-items: center;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
+        }
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 0 20px 20px 20px;
+    }
+}
+</style>

+ 180 - 0
src/views/report_manage/reportV2/smartReport/components/ETAPriceChart.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span>{{$t('ReportManage.ReportList.price_curve_radio')}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					placeholder="图表名称"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                <draggable
+                    :list="list"
+                    :group="{ name: 'component', pull: 'clone', put: false }"
+                    class="chart-list-box"
+                    animation="300"
+                    :sort="false"
+                    tag="div"
+                >
+                    <div class="chart-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.UniqueCode">
+                        <div class="title">{{item.ChartName}}</div>
+                        <div class="img" :style="'backgroundImage:url('+item.ChartImage+')'"></div>
+                    </div>
+                </draggable>
+                <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import futuresInterface from "@/api/modules/futuresBaseApi";
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            isShowMe:false,
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getChartList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+            const obj={
+                compId:3,
+                compType:'chart',
+                content:`${LINK_CHART_URL}?code=${item.UniqueCode}`
+            }
+            return JSON.stringify(obj)
+        },
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        /* 搜索图表分页 */
+        async getChartList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            };
+            this.loading=true
+            let res = await futuresInterface.searchChart(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getChartList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
+    }
+}
+.chart-list-box{
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: cover;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+}
+</style>

+ 172 - 0
src/views/report_manage/reportV2/smartReport/components/ETASandBox.vue

@@ -0,0 +1,172 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span>{{$t('ReportManage.ReportList.sandbox_top_type')}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.no_reports_msg')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                <draggable
+                    :list="list"
+                    :group="{ name: 'component', pull: 'clone', put: false }"
+                    class="chart-list-box"
+                    animation="300"
+                    :sort="false"
+                    tag="div"
+                >
+                    <div class="chart-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.SandboxId">
+                        <div class="title">{{item.Name}}</div>
+                        <div class="img" :style="'backgroundImage:url('+item.PicUrl+')'"></div>
+                    </div>
+                </draggable>
+                <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {sandInterface} from "@/api/api.js";
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSandBoxList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const obj={
+                compId:2,
+                compType:'img',
+                content:item.PicUrl
+            }
+            return JSON.stringify(obj)
+        },
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSandBoxList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSandBoxList()
+        },
+
+        /* 搜索图表分页 */
+        async getSandBoxList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            };
+            this.loading=true
+            let res = await sandInterface.sandlistByQuote(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSandBoxList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
+    }
+}
+.chart-list-box{
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: contain;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+}
+</style>

+ 173 - 0
src/views/report_manage/reportV2/smartReport/components/ETASheet.vue

@@ -0,0 +1,173 @@
+<template>
+    <div class="eta-sheet-wrap">
+        <div class="top-box">
+            <span>{{$t('ReportManage.ReportList.eta_top_type')}}</span>
+            <el-input
+                class="search-box"
+				:placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+				v-model="keyword"
+				size="medium"
+				prefix-icon="el-icon-search"
+                @input="handleSearch"
+			/>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+            <draggable
+                :list="list"
+                :group="{ name: 'component', pull: 'clone', put: false }"
+                class="sheet-list-box"
+                animation="300"
+                :sort="false"
+                tag="div"
+                :move="onMoveItemHandle"
+            >
+                <div class="sheet-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.ExcelInfoId">
+                    <div class="title">{{item.ExcelName}}</div>
+                    <div class="img" :style="`backgroundImage:url(${ !item.HaveOperaAuth?$icons.lock_big:item.ExcelImage })`"></div>
+                </div>
+            </draggable>
+            <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+    data() {
+        return {
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSheetList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const LINK_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/sheetshow';
+            // console.log(LINK_URL);
+            const obj={
+                compId:4,
+                compType:'sheet',
+                content:`${LINK_URL}?code=${item.UniqueCode}&fromScene=1`,
+                title: item.ExcelName
+            }
+            return JSON.stringify(obj)
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSheetList()
+        },
+        getSheetList() {
+            this.loading=true
+            sheetInterface.sheetList({
+                Keyword: this.keyword,
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            }).then((res) => {
+                this.loading=false
+                if (res.Ret !== 200) return;
+                const arr = res.Data.List || [];
+                this.list =
+                    this.page === 1
+                    ? arr
+                    : [...this.list, ...arr];
+                this.finished =  res.Data.Paging.IsEnd;
+            });
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSheetList()
+        },
+
+        onMoveItemHandle(e) {
+            /* 无权限 */
+            if (!e.draggedContext.element.HaveOperaAuth) {
+                this.messageTip()
+                return false;
+            }
+
+            return true
+        },
+        
+        messageTip: _.debounce(function() {
+            this.$message.warning(this.$t('MsgPrompt.no_sheet_auth'))
+        },200)
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.eta-sheet-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        .search-box{
+            width: 330px;
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
+        .sheet-list-box{
+            display: flex;
+            flex-wrap: wrap;
+            gap: 20px;
+            .sheet-item{
+                cursor: move;
+                padding: 0 10px 10px 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: contain;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+        }
+    }
+}
+</style>

+ 16 - 0
src/views/report_manage/reportV2/smartReport/components/ImgComp.vue

@@ -0,0 +1,16 @@
+<template>
+    <div 
+        class="report-comp-item img-comp" 
+        style="width:100%;height:100%;overflow-y: auto;"
+    >
+        <img style="width:100%;display:block" :src="compData.content" alt="">
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        compData:{}
+    }
+}
+</script>

+ 141 - 0
src/views/report_manage/reportV2/smartReport/components/ImgEdit.vue

@@ -0,0 +1,141 @@
+<template>
+    <div class="img-edit-wrap" @paste="handleListenPaste">
+        <div style="font-size:16px;margin-bottom:20px">{{$t('ReportManage.ReportList.img_uplaod_title')}}</div>
+        <div class="main-box">
+            <input type="file" size="small" name="file" @change="fileSelected" id="file" class="true-file" style="display:none;">
+            <div class="upload-box" @click="clickinput">
+                <img class="bg" :src="content" alt="" v-if="content">
+                <img src="~@/assets/img/smartReport/icon15.png" alt="">
+                <div>{{$t('ReportManage.ReportList.click_img_upload')}}</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { bannerupload } from 'api/api.js';
+export default {
+    name:'ImgEdit',
+    props:{
+        content:''
+    },
+    created() {
+        window.addEventListener('paste',this.handleListenPaste)
+    },
+     
+    destroyed(){
+        window.removeEventListener('paste',this.handleListenPaste)
+    },
+    methods: {
+        clickinput(){  //上传模拟点击
+			$(`#file`).click();
+		},
+        fileSelected(file){  //选择文件上传
+            let hostfile=document.getElementById('file').files[0]||file
+			const that = this;
+		    if( hostfile ){
+		        let size = Math.floor(hostfile.size / 1024 / 1024);
+		        if( size>200 ){
+		            that.$message.warning(this.$t('ReportManage.smart_msg.uploaded_limitation'));
+		            hostfile = {};
+		            return false
+		        }
+		        if( hostfile.name.toLowerCase().includes('.png') || hostfile.name.toLowerCase().includes('.jpg') || hostfile.name.toLowerCase().includes('.jpeg') ){
+		        	let form = new FormData();
+		        	form.append('file',hostfile);  //hostfile.name
+					bannerupload(form).then((res) => {
+						if( res.Ret === 200 ){
+							that.$emit('imgChange', res.Data.ResourceUrl)
+                            that.content=res.Data.ResourceUrl
+						}
+						$("#file").val('');
+						hostfile = {};
+					});
+				}else{
+					that.$message.warning(this.$t('ReportManage.smart_msg.upload_format'));
+		        }
+		    } 
+		},
+
+        handleListenPaste:_.throttle(async function(e){
+            if(!e.clipboardData) return
+            const clipboardDataItems = e.clipboardData.items
+            const clipboardDataFirstItem = clipboardDataItems[0]
+            if(clipboardDataFirstItem){
+                for (const item of clipboardDataItems) {
+                    if (item.kind === 'file' && item.type.indexOf('image') !== -1) {
+                        const imageFile = item.getAsFile()
+                        console.log('读取成功1',imageFile);
+                        if (imageFile) this.fileSelected(imageFile)
+                        return
+                    }
+                }
+                return
+            }
+            //clipboardData中没有图片,从navigator.clipboard.read里获取图片
+            let clipboardItems = null
+            try{
+                clipboardItems = await navigator.clipboard.read()
+            }catch(error){
+                this.$message.warning("剪贴板读取不到文件!")
+                return
+            }
+            const blob = await this.checkClipboardItems(clipboardItems)
+            console.log('读取成功2',blob);
+            if(blob) this.fileSelected(blob)
+
+        },1000),
+
+        checkClipboardItems(clipboard){
+            for(const Item of clipboard){
+                for(const type of Item.types){
+                    if(type.includes('image')){
+                        return Item.getType(type)
+                    }
+                }
+            }
+            return null
+        }
+    },
+
+
+
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+
+.main-box{
+    width: 100%;
+    height: calc(100vh - 150px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+    background: #FFF;
+    padding: 30px;
+    .upload-box{
+        cursor: pointer;
+        width: 120px;
+        height: 120px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        border: 1px dashed var(--gary-gy-5-line, #C8CDD9);
+        background: var(--gary-gy-1-bottom-bk, #F8F8F8);
+        color: #999;
+        position: relative;
+        .bg{
+            width: 100%;
+            height: 100%;
+            position: absolute;
+            left: 0;
+            top: 0;
+            z-index: 10;
+            background: #FFF;
+        }
+    }
+}
+</style>

+ 223 - 0
src/views/report_manage/reportV2/smartReport/components/ImgSource.vue

@@ -0,0 +1,223 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span v-if="defaultType">
+                    {{ defaultType===1 ? $t('ReportManage.ReportList.choose_head_img') : $t('ReportManage.ReportList.choose_end_img') }}
+                </span>
+                <span v-else>{{$t('ReportManage.ReportList.select_img_card')}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.img_name_ipt')"
+					v-model="keyword"
+                    @input="handleSearch"
+                    style="width:240px"
+                    size="medium"
+				/>
+                <el-select :placeholder="$t('ReportManage.ReportList.select_img_type')" v-model="type" style="width:240px" @change="handleSearch" size="medium" :disabled="defaultType" v-show="!defaultType">
+                    <el-option :label="$t('ReportManage.ReportList.page_header_op')" :value="1"></el-option>
+                    <el-option :label="$t('ReportManage.ReportList.page_trailer_op')" :value="2"></el-option>
+                </el-select>
+            </div>
+        </div>
+        <div class="main-box" :style="inDialog?'height:550px;':'height: calc(100vh - 180px)'">
+            <div style="flex:1;overflow-y: auto;padding:20px 0">
+            <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+                <div 
+                    :class="['item',selectItem&&selectItem.ResourceId===item.ResourceId?'active':'']" 
+                    v-for="item in list" 
+                    :key="item.ResourceId" 
+                    @click="handleSelectItem(item)"
+                >
+                    <div class="img" :style="'backgroundImage:url('+item.ImgUrl+')'"></div>
+                    <div class="title">{{item.ImgName}}</div>
+                </div>
+            </div>
+            </div>
+            <div class="btns-box">
+                <el-button type="primary" plain @click="handleClose">{{$t('Dialog.cancel_btn')}}</el-button>
+                <el-button type="primary" @click="handleSave">{{$t('Dialog.confirm_save_btn')}}</el-button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {apiSmartReport}  from '@/api/modules/smartReport'
+export default {
+    props: {
+        inDialog: { //内嵌进dialog
+            type: Boolean,
+            default: false
+        },
+        defaultType: { //默认类型
+            type: Number,
+            default: 0
+        }
+    },
+    watch: {
+        defaultType(nval) {
+            this.type = nval;
+            this.selectItem = null
+            this.page = 1;
+            this.getImgList()
+        }
+    },
+    data() {
+        return {
+            keyword:'',
+            type:this.defaultType||1,
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+
+            setType:'',
+            selectItem:null
+        }
+    },
+    created(){
+        this.getImgList()
+    },
+    methods: {
+        //资源库列表
+        async getImgList(){
+            const res=await apiSmartReport.imgReourceList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                Type:this.type,
+                Keyword:this.keyword
+            })
+            if(res.Ret===200){
+                const arr = res.Data.List || [];
+                this.list =
+                    this.page === 1
+                    ? arr
+                    : [...this.list, ...arr];
+                this.finished =  res.Data.Paging.IsEnd;
+            }
+        },
+
+        handleLoadMore(){
+            if(this.finished) return
+            this.page++
+            this.getImgList()
+        },
+
+        handleSearch(){
+            this.page=1
+            this.finished=false
+            this.selectItem=null
+            this.getImgList()
+        },
+
+        handleSelectItem(e){
+            this.selectItem=e
+        },
+
+        handleClose(){
+            this.$emit('close')
+        },
+
+        handleSave(){
+            // if(!this.setType){
+            //     this.$message.warning('请选择设置的版面类型')
+            //     return
+            // }
+            if(!this.selectItem){
+                this.$message.warning(this.type==1?'请选择版头':'请选择版尾')
+                return
+            }
+            this.$emit('change',{
+                type:this.type,
+                data:this.selectItem
+            })
+        }
+        
+
+    },
+
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            display: flex;
+            flex-wrap: wrap;
+            gap: 20px;
+            .item{
+                width: 240px;
+                cursor: pointer;
+                .img{
+                    background: var(--gary-gy-3-disabled, #EBEFF6);
+                    width: 240px;
+                    height: 240px;
+                    background-size: contain;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+                .title{
+                    margin-top: 5px;
+                    display: -webkit-box;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    -webkit-line-clamp: 2;
+                    line-break: anywhere;
+                    -webkit-box-orient: vertical;
+                }
+            }
+            .active{
+                position: relative;
+                .img{
+                    border: 1px solid #0052D9;
+                }
+                &::before{
+                    content: '';
+                    display: block;
+                    width: 20px;
+                    height: 20px;
+                    position: absolute;
+                    left: 0;
+                    top: 0;
+                    background-image: url('~@/assets/img/smartReport/icon17.png');
+                    background-size: cover;
+                    background-repeat: no-repeat;
+                }
+            }
+        }
+        .btns-box{
+            padding-top: 20px;
+            text-align: center;
+            .el-button{
+                width: 120px;
+            }
+        }
+    }
+}
+</style>

+ 166 - 0
src/views/report_manage/reportV2/smartReport/components/ImportETAChart.vue

@@ -0,0 +1,166 @@
+<template>
+    <div class="import-eta-chart-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <draggable
+                :list="list"
+                :group="{ name: 'component', pull: 'clone', put: false }"
+                class="chart-list-box"
+                animation="300"
+                :sort="false"
+                tag="div"
+                :move="onMoveItemHandle"
+            >
+                <div class="chart-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.UniqueCode">
+                    <div class="title">{{item.ChartName}}</div>
+                    <div class="img" :style="`backgroundImage:url(${ !item.HaveOperaAuth?$icons.lock_big:item.ChartImage })`"></div>
+                </div>
+            </draggable>
+            <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0"/>
+    </div>
+</template>
+
+<script>
+import { dataBaseInterface } from "@/api/api.js";
+export default {
+    data() {
+        return {
+            isShowMe:false,
+            page:1,
+            pageSize:20,
+            list:[],
+            finished:false,
+            keyword:'',
+            loading:false
+        }
+    },
+    computed: {
+        //语言版本
+        currentLang() {
+            return this.$store.state.lang
+        }
+    },
+    created() {
+        this.getETAChartList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+            const obj={
+                compId:3,
+                compType:'chart',
+                content:`${LINK_CHART_URL}?code=${item.UniqueCode}&lang=${this.currentLang}`
+            }
+            return JSON.stringify(obj)
+        },
+
+        async getETAChartList(){
+            this.loading=true
+            const res=await dataBaseInterface.chartSearchByEs({
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            })
+            this.loading=false
+            if(res.Ret===200){
+                const arr=res.Data.List || []
+                this.list=[...this.list,...arr]
+                this.finished=res.Data.Paging.IsEnd
+            }
+        },
+
+        handleIsShowMeChange(){
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.getETAChartList()
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getETAChartList()
+        },
+
+        handleSearch(key){
+            this.page=1
+            this.finished=false
+            this.list=[]
+            this.keyword=key
+            this.getETAChartList()
+        },
+
+        onMoveItemHandle(e) {
+            /* 无权限 */
+            if (!e.draggedContext.element.HaveOperaAuth) {
+                this.messageTip()
+                return false;
+            }
+
+            return true
+        },
+        
+        messageTip: _.debounce(function() {
+            this.$message.warning(this.$t('MsgPrompt.no_chart_auth'))
+        },200)
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.import-eta-chart-wrap{
+    height: 100%;
+    width: 100%;
+    position: relative;
+    overflow-y: auto;
+    overflow-x: hidden;
+    padding-top: 20px;
+    .onlyshowme-box{
+            display: block;
+            position: sticky;
+            top: -20px;
+            padding: 20px 0;
+            background-color: #FFF;
+        }
+        .chart-list-box{
+            display: flex;
+            flex-wrap: wrap;
+            gap: 20px;
+            .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: cover;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+        }
+}
+</style>

+ 171 - 0
src/views/report_manage/reportV2/smartReport/components/ImportMyETAChart.vue

@@ -0,0 +1,171 @@
+<template>
+    <div class="import-mychart-wrap">
+        <div class="select-box">
+			<el-select 
+				style="width:300px" 
+				v-model="selectMyChartClassify" 
+				filterable 
+				:placeholder="$t('ReportManage.ReportList.chart_category_name')"
+				@change="handleChange"
+			>
+				<el-option
+					v-for="item in myChartClassifyList"
+					:key="item.MyChartClassifyId"
+					:label="item.MyChartClassifyName"
+					:value="item.MyChartClassifyId"
+				>
+				</el-option>
+			</el-select>
+			<el-button type="primary" @click="handleImport">{{$t('ReportManage.ReportList.click_import')}}</el-button>
+			<el-tooltip class="item" effect="dark" :content="$t('ReportManage.ReportList.import_all_chart_msg')" placement="top-start">
+				<i style="font-size:24px;color: #666;" class="el-icon-question"></i>
+			</el-tooltip>
+		</div>
+		<div class="list" v-infinite-scroll="load" v-if="list.length>0">
+            <div class="chart-item" v-for="item in list" :key="item.UniqueCode" @click="handleClickItem">
+                <div class="title">{{item.ChartName}}</div>
+                <div class="img" :style="`backgroundImage:url(${ !item.HaveOperaAuth?$icons.lock_big:item.ChartImage })`"></div>
+            </div>
+		</div>
+        <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0"/>
+    </div>
+</template>
+
+<script>
+import { mychartInterface } from '@/api/api.js';
+export default {
+    data() {
+        return {
+            myChartClassifyList:[],
+            selectMyChartClassify:'',
+            pageSize:20,
+			CurrentIndex: 1,
+			list:[],
+            loading:false,
+            finished:false,
+
+        }
+    },
+    props:{
+        showEnMark:{
+            type:Boolean,
+            default:false
+        }
+    },
+    mounted(){
+        this.getMyChartClassify()
+    },  
+    methods: {
+        //获取我的图库中分类
+		getMyChartClassify(){
+			mychartInterface.classifyList().then(res=>{
+				if (res.Ret !== 200) return;
+				this.myChartClassifyList=res.Data?res.Data.List:[]
+			})
+		},
+        handleChange(){
+            this.CurrentIndex=1
+            this.list=[]
+            this.finished=false
+            this.loading=false
+            this.handleGetMyChartList()
+        },
+		async handleGetMyChartList(){
+            if(!this.selectMyChartClassify) return
+            this.loading=true
+            const res=await  mychartInterface.myList({
+				PageSize: this.pageSize,
+				CurrentIndex: this.CurrentIndex,
+				MyChartClassifyId: this.selectMyChartClassify || 0
+			})
+            this.loading=false
+            const arr=res.Data?res.Data.List.filter(_=>!_.Disabled):[]
+            this.list=[...this.list,...arr]
+            if(!res.Data){
+                this.finished=true
+            }
+            if(res.Data&&res.Data.Paging.IsEnd){
+                this.finished=true
+            }
+		},
+
+        load(){
+            if(this.finished) return
+            this.CurrentIndex++
+            this.handleGetMyChartList()
+        },
+
+        handleImport:_.throttle(function(){
+            if(!this.selectMyChartClassify){
+                this.$message.warning(this.$t('ReportManage.ReportList.please_select_category'))
+                return
+            }
+             let filterList = this.list.filter(_ =>_.HaveOperaAuth)
+            if(filterList.length==0){
+                this.$message.warning(this.$t('ReportManage.ReportList.no_chart_msg'))
+                return
+            }
+            this.$emit('handleImportMyChart',filterList)
+            setTimeout(() => {
+                this.CurrentIndex=1
+                this.list=[]
+                this.finished=false
+                this.loading=false
+                this.selectMyChartClassify=''
+            }, 300);
+        },1000),
+
+        handleClickItem(){
+            this.$message.warning(this.$t('ReportManage.ReportList.no_one_charts'))
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.import-mychart-wrap{
+    position: relative;
+    height: 100%;
+    padding-top: 20px;
+    .select-box{
+        position: absolute;
+        top: -75px;
+        right: 0;
+    }
+    .list{
+        max-height: calc(100vh - 220px);;
+        overflow-x: hidden;
+		overflow-y: auto;
+        display: flex;
+            flex-wrap: wrap;
+            gap: 20px;
+            .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                max-height: 260px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: cover;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+    }
+}
+</style>

+ 172 - 0
src/views/report_manage/reportV2/smartReport/components/SemanticAnalysis.vue

@@ -0,0 +1,172 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span>{{$t('ReportManage.ReportList.semantic_top_type')}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.keyword_search')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                <draggable
+                    :list="list"
+                    :group="{ name: 'component', pull: 'clone', put: false }"
+                    class="chart-list-box"
+                    animation="300"
+                    :sort="false"
+                    tag="div"
+                >
+                    <div class="chart-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.SaCompareId">
+                        <div class="title">{{item.Title}}</div>
+                        <div class="img" :style="'backgroundImage:url('+item.ResultImg+')'"></div>
+                    </div>
+                </draggable>
+                <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {semanticInterface} from '@/api/modules/semanticsApi.js';
+export default {
+    data() {
+        return {
+            
+            keyword:'',
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getSemanticList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const obj={
+                compId:2,
+                compType:'img',
+                content:item.ResultImg
+            }
+            return JSON.stringify(obj)
+        },
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSemanticList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getSemanticList()
+        },
+
+        /* 搜索图表分页 */
+        async getSemanticList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+            };
+            this.loading=true
+            let res = await semanticInterface.compareSearch(params);
+            this.loading=false
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getSemanticList()
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
+    }
+}
+.chart-list-box{
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: contain;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+}
+</style>

+ 48 - 0
src/views/report_manage/reportV2/smartReport/components/SheetComp.vue

@@ -0,0 +1,48 @@
+<template>
+    <div 
+        class="report-comp-item sheet-comp"
+        style="width:100%;overflow: hidden;"
+    >
+        <div 
+            style="padding-left:10px;font-size:17px" 
+            contenteditable="true"
+            :class="`title_${id}`"
+            v-html="compData.titleText"
+            v-if="compData.titleText"
+        ></div>
+        <iframe :class="id" :src="compData.content" width="100%" style="border-width:0px;"></iframe>
+    </div>
+</template>
+
+<script>
+function GetQueryString(url) {
+    let urlStr=url.split('?')[1]
+    let obj={}
+    let paramsArr=urlStr.split('&')
+    for (let index = 0; index < paramsArr.length; index++) {
+        let arr=paramsArr[index].split('=')
+        obj[arr[0]]=arr[1]
+    }
+    return obj
+}
+export default {
+    props:{
+        compData:{}
+    },
+    computed: {
+        id(){
+            if(this.compData.content){
+                // console.log(this.compData.content);
+                let params = GetQueryString(this.compData.content)
+                // console.log(params);
+                return `iframe${params.code}`
+            }
+            return ''
+        }
+    },
+}
+</script>
+
+<style>
+
+</style>

+ 258 - 0
src/views/report_manage/reportV2/smartReport/components/StatisticAnalysis.vue

@@ -0,0 +1,258 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span
+                    :class="['item',activeType===item.key?'active':'']" 
+                    @click="activeTypeChange(item.key)"
+                    v-for="item in typeOpts"
+                    :key="item.key"
+                >{{item.name}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					:placeholder="$t('ReportManage.ReportList.chart_name')"
+					v-model="keyword"
+					size="medium"
+					prefix-icon="el-icon-search"
+                    @input="handleSearch"
+				/>
+            </div>
+        </div>
+        <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleIsShowMeChange"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
+                <draggable
+                    :list="list"
+                    :group="{ name: 'component', pull: 'clone', put: false }"
+                    class="chart-list-box"
+                    animation="300"
+                    :sort="false"
+                    tag="div"
+                >
+                    <div class="chart-item" :comp-data="getCompData(item)" v-for="item in list" :key="item.UniqueCode">
+                        <div class="title">{{item.ChartName}}</div>
+                        <div class="img" :style="'backgroundImage:url('+item.ChartImage+')'"></div>
+                    </div>
+                </draggable>
+                <tableNoData :text="$t('ReportManage.ReportList.no_chart_table_available')" size="mini" v-if="list.length===0&&finished"/>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
+import {
+  fittingEquationInterface,
+  statisticFeatureInterface,
+  crossVarietyInterface
+} from "@/api/modules/chartRelevanceApi";
+export default {
+    data() {
+        return {
+
+            keyword:'',
+            isShowMe:false,
+            activeType:'相关性',
+
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
+        }
+    },
+    created(){
+        this.getChartList()
+    },
+    methods: {
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        getCompData(item){
+            const LINK_CHART_URL = this.$setting.dynamicOutLinks.ChartViewUrl+'/chartshow';
+            const obj={
+                compId:3,
+                compType:'chart',
+                content:`${LINK_CHART_URL}?code=${item.UniqueCode}`
+            }
+            return JSON.stringify(obj)
+        },
+
+        activeTypeChange(e){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.keyword=''
+            this.isShowMe=false
+            this.activeType=e
+            this.getChartList()
+        },
+
+        handleIsShowMeChange(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
+            this.getChartList()
+        },
+
+        /* 搜索图表分页 */
+        async getChartList(word) {
+            let params = {
+                Keyword: this.keyword || "",
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
+                IsShowMe: this.isShowMe,
+            };
+            this.loading=true
+            let res = null;
+            if (this.activeType === '相关性') {
+                res = await chartRelevanceApi.searchChart(params);
+            } else if (this.activeType === '拟合方程曲线') {
+                res = await fittingEquationInterface.searchChart(params);
+            } else if (this.activeType === '统计特征') {
+                res = await statisticFeatureInterface.searchChart(params);
+            } else if (this.activeType === '跨品种分析') {
+                res = await crossVarietyInterface.searchChart(params);
+            }
+            this.loading=false
+
+            if (res.Ret !== 200) return;
+            const arr = res.Data.List || [];
+            this.list =
+                this.page === 1
+                ? arr
+                : [...this.list, ...arr];
+            this.finished =  res.Data.Paging.IsEnd;
+        },
+
+        handleLoadMore(){
+            if(this.finished||this.loading) return
+            this.page++
+            this.getChartList()
+        }
+    },
+    computed:{
+      typeOpts(){
+        return [
+                {
+                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
+                    key:'相关性'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
+                    key:'拟合方程曲线'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
+                    key:'统计特征'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
+                    key:'跨品种分析'
+                }
+            ]
+      }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+div{
+    box-sizing: border-box;
+}
+.statistic-analysis-wrap{
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .left-card{
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            align-items: center;
+            gap: 0 3px;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
+        }
+        .right{
+            .search-box{
+                width: 330px;
+            }
+        }
+    }
+    .main-box{
+        margin-top: 30px;
+        height: calc(100vh - 180px);
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
+    }
+}
+.chart-list-box{
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    .chart-item{
+                cursor: move;
+                padding: 0 10px;
+                width: 250px;
+                border-radius: 4px;
+                border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                background: var(--gary-gy-white, #FFF);
+                .title{
+                    padding: 10px 0;
+                    text-align: center;
+                    border-bottom: 1px solid #C8CDD9;
+                    overflow: hidden;
+                    white-space: nowrap;
+                    text-overflow: ellipsis;
+                }
+                .img{
+                    width: 100%;
+                    height: 197px;
+                    background-size: cover;
+                    background-position: center;
+                    background-repeat: no-repeat;
+                }
+            }
+}
+</style>

+ 20 - 0
src/views/report_manage/reportV2/smartReport/components/TextComp.vue

@@ -0,0 +1,20 @@
+<template>
+    <div 
+        class="report-comp-item text-comp" 
+        style="width:100%;height: 100%;overflow-y: auto;"
+    >
+        <div class="rich-text-box" v-html="compData.content"></div>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        compData:{}
+    }
+}
+</script>
+
+<style>
+
+</style>

+ 168 - 0
src/views/report_manage/reportV2/smartReport/components/TextEdit.vue

@@ -0,0 +1,168 @@
+<template>
+    <div class="text-edit-wrap">
+        <div style="font-size:16px;margin-bottom:20px">{{$t('ReportManage.ReportList.text_editing')}}</div>
+        <froala
+			id="froala-editor"
+			ref="froalaEditor"
+			:tag="'textarea'"
+			:config="froalaConfig"
+			v-model="html"
+		/>
+    </div>
+</template>
+
+<script>
+import VueFroala from 'vue-froala-wysiwyg';
+export default {
+    name:'TextEdit',
+    props:{
+        content:''
+    },
+    data() {
+        const that = this;
+        return {
+            html:this.content||'',
+            editor: null,
+            lastEditRange: null,
+            froalaConfig:{
+                imageUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url
+                videoUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url
+                fileUploadURL: process.env.VUE_APP_API_ROOT + "/report/uploadImg", //上传url 更多上传介绍 请访问https://www.froala.com/wysiwyg-editor/docs/options
+                toolbarButtons: [
+                    "textColor",
+                    "bold",
+                    "italic",
+                    "underline",
+                    "strikeThrough",
+                    "subscript",
+                    "superscript",
+                    "fontFamily",
+                    "fontSize",
+                    "color",
+                    "inlineClass",
+                    "inlineStyle",
+                    "paragraphStyle",
+                    "lineHeight",
+                    "paragraphFormat",
+                    "align",
+                    "formatOL",
+                    "formatUL",
+                    "outdent",
+                    "indent",
+                    "quote",
+                    "specialCharacters",
+                    "insertHR",
+                    "selectAll",
+                    "clearFormatting",
+                    /* "html", */
+                    "undo",
+                    "redo",
+                ],
+                height: 800,
+                fontSize: ["12", "13","14","15", "16", "18", "20", "24", "28", "32", "36", "40"],
+                fontSizeDefaultSelection: "16",
+                theme: "dark", //主题
+                placeholderText: localStorage.getItem('i18n') == 'en' ? 'Please input content' : "请输入内容",
+                language: localStorage.getItem('i18n') == 'en' ? 'en' : "zh_cn", //国际化
+                imageDefaultWidth: false,
+                quickInsertEnabled: false,
+                toolbarVisibleWithoutSelection: true, //是否开启 不选中模式
+                toolbarSticky: false, //操作栏是否自动吸顶
+                saveInterval: 0,
+                fontFamily:{
+                    'Arial,Helvetica,sans-serif': 'Arial',
+                    'Georgia,serif': 'Georgia',
+                    'Impact,Charcoal,sans-serif': 'Impact',
+                    'Tahoma,Geneva,sans-serif': 'Tahoma',
+                    'Times New Roman,Times,serif': 'Times New Roman',
+                    'Verdana,Geneva,sans-serif': 'Verdana',
+                    '思源宋体':'思源宋体',
+                    '思源黑体':'思源黑体',
+                },
+                events: {
+                    //this.editor 定义在vue data 中
+                    initialized: function () {
+                        // this.editor = editor;
+                        that.editor = this;
+                        // that.editor.html.set(that.value);
+                        // that.setHtml()
+                    },
+                    keyup: function (e, editor) {
+                        //添加事件,在每次按键按下时,都记录一下最后停留位置
+                        that.$nextTick(function () {
+                            getSelection().rangeCount &&
+                                (that.lastEditRange = getSelection().getRangeAt(0));
+                        });
+                    },
+                    click: function (e, editor) {
+                        //添加事件,在每次鼠标点击时,都记录一下最后停留位置
+                        that.$nextTick(function () {
+                            getSelection().rangeCount &&
+                            (that.lastEditRange = getSelection().getRangeAt(0));
+                        });
+                    },
+                    //内容改变事件
+                    contentChanged: function () {
+                        that.lastEditRange = getSelection().rangeCount
+                            ? getSelection().getRangeAt(0)
+                            : 0;
+                        
+                        // that.$emit('textChange', that.html)
+                        that.sendHtml()
+                    },
+                    "paste.before":function(e,editor){
+                        let content = e.clipboardData.getData('text/html');
+                        // console.log(content)
+                        var tempDiv = document.createElement('div');
+                        tempDiv.innerHTML = content;
+                        var iframes = tempDiv.querySelectorAll('iframe');
+                        const srcArr = Array.from(iframes).map(i=>i.src)
+                        //console.log(srcArr);
+                        if(srcArr.filter(i=>!i.includes(that.$setting.dynamicOutLinks.ChartViewUrl)).length){
+                            that.$message.warning("粘贴内容含有外链,请核对内容或粘贴纯文本")
+                            return false
+                        }
+                    },
+                },
+            }
+        }
+    },
+    methods: {
+        sendHtml(){
+            const str=this.html.replace(/<p data-f-id=\"pbf\".*?<\/p>/g, "")
+            //如果富文本中有未上传完成的图片,去除这个dom
+			$('.fr-element').find('img.fr-uploading').length&&$('.fr-element').find('img.fr-uploading').remove()
+            this.$emit('textChange', str)
+        }
+    },
+    components:{}
+}
+</script>
+
+<style lang="scss">
+.text-edit-wrap{
+    .fr-box.fr-basic{
+        flex: 1;
+        overflow: hidden;
+        display: flex;
+        flex-direction: column;
+        .fr-wrapper{
+            flex: 1;
+            overflow: auto;
+        }
+    }
+}
+</style>
+<style lang="scss" scoped>
+.text-edit-wrap{
+    width:100%;
+    height: 100%;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+    #froala-editor{
+        flex:1;
+        overflow: auto;
+    }
+}
+</style>

+ 1857 - 0
src/views/report_manage/reportV2/smartReport/editReport.vue

@@ -0,0 +1,1857 @@
+<template>
+    <div class="edit-smart-box">
+        <!-- 章节编辑区 -->
+		<div class="left-wrap" v-if="reportCoopType===2">
+			<chapterWrapper
+				v-show="isLeftWrapShow"
+                ref="chapterContRef"
+                :isApprove="isApprove"
+				:hasApproveFlow="hasApproveFlow"
+				@change="handleChapterInfo"
+				@checkClassifyNameArr="handleCheckClassifyNameArr"
+				@openBaseInfo="showReportBaseInfo=true"
+				@handlePreviewReport="handlePreviewReport"
+                @handlePublish="handlePublishOpt"
+                @update="({Title}) => { reportInfo.Title=Title }"
+			/>
+
+			<span
+                class="slide-btn-icon"
+                :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
+                @click="isLeftWrapShow = !isLeftWrapShow"
+			>
+                <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+			</span>
+		</div>
+
+
+        <div class="edit-smart-report-page">
+            <!-- 章节报告默认 -->
+			<template v-if="reportCoopType===2&&!selectChapterId">
+				<div style="padding-top: 20%;">
+                    <tableNoData :text="$t('Common.no_cont_msg')"/>
+                </div>
+			</template>
+
+			<!-- 章节报告预览 -->
+			<template v-else-if="reportCoopType===2&&selectChapterId&&!editChapterId">
+				<div style="max-height:100vh;overflow-y:auto;">
+					<smartReportDetail
+						v-if="reportInfo&&reportInfo.ReportChapterId"
+						:info="reportInfo"
+					/>
+				</div>
+			</template>
+
+            <!-- 非章节报告或章节报告编辑 -->
+            <template v-else>
+                <!-- 顶部操作栏 -->
+                <editHeader
+                    :isApprove="isApprove"
+                    :hasApproveFlow="hasApproveFlow"
+                    :reportInfo="reportInfo"
+                    @handleClearContent="handleClearContent"
+                    @openBaseInfo="showReportBaseInfo=true"
+                    @handleRefreshAllChart="handleRefreshAllChart"
+                    @handlePreviewReport="reportInfo.ReportChapterId?handlePreviewChapter():handlePreviewReport()"
+                    @handleSaveContent="reportInfo.ReportChapterId?handleAutoSaveChapter('save'):handleSaveContent({isAutoSave:false})"
+                    @handlePublishOpt="(type) =>{reportInfo.ReportChapterId?handlePublishChapter():handlePublishOpt(type)}"
+                    @update="()=>{$refs.chapterContRef&&$refs.chapterContRef.getChapterList()}"
+                />
+                
+                <div class="main-wrap">
+                    <div class="report-action-wrap">
+                        <ul class="top-type-list">
+                            <li class="item" v-for="item in topTypeList" :key="item.name" @click="handleShowRight(item)" v-show="item.visable">
+                                <img class="icon" :src="item.icon" alt="">
+                                <span>{{item.name}}</span>
+                            </li>
+                        </ul>
+                        <!-- 公共组件 -->
+                        <draggable
+                            :list="compList"
+                            :group="{ name: 'component', pull: 'clone', put: false }"
+                            class="report-comp-wrap"
+                            animation="300"
+                            :sort="false"
+                            tag="ul"
+                            filter='.unDrag'
+                        >
+                            <li class="comp-item" :comp-data="JSON.stringify(comp)" v-for="comp in compList" :key="comp.id">
+                                <img :src="comp.icon">
+                            </li>
+                            <li class="comp-item unDrag" style="cursor: pointer;" v-if="!reportInfo.ReportChapterId">
+                                <el-color-picker v-model="bgColor" @change="handleBgColorChange"></el-color-picker>
+                            </li>
+                        </draggable>
+
+                        <div class="report-content-box" id="report-content-box" :style="{backgroundColor:bgColor}">
+                            <div class="html-head-img-box">
+                                <div class="opt-btn-box" style="display: none;">
+                                    <div class="del-btn" @click.stop="deleteLayoutPic(1)"></div>
+                                </div>
+                                <img :src="headImg" alt="" style="display:block;width:100%">
+                                <div class="head-layout-item" v-for="item in headImgStyle" :key="item.value"
+                                :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
+                                    width:item.width,height:item.height,left:item.left,top:item.top
+                                }">
+                                    {{ layoutBaseInfo[item.value] }}
+                                </div>
+                            </div>
+                            <draggable
+                                :list="conList"
+                                :group="{ name: 'component', pull: true, put: true }"
+                                class="report-html-wrap"
+                                id="report-html-content"
+                                animation="300"
+                                tag="div"
+                                handle=".drag-btn_p"
+                                @add="handleParentAdd"
+                                @remove="handleParentRemove"
+                                :move="handleParentMove"
+                            >
+                                <div 
+                                    :class="[
+                                        'report-drag-item-wrap',
+                                        activeId===item.id?'blue-bg':'',
+                                        item.child&&!item.child.length?'report-drag-item-out':''
+                                    ]"
+                                    v-for="item,index in conList" 
+                                    :key="item.id"
+                                    :comp-type="item.compType"
+                                    @click="handleChoose(item,index)"
+                                    :style="item.style"
+                                >
+                                    <!-- 缩放的盒子 -->
+                                    <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" @click.stop="handleDelItem(index,-1)"></div>
+                                    </div>
+                                    <div 
+                                        v-if="item.child&&!item.child.length"
+                                        class="report-drag-item-wrap_content"
+                                        style="width:100%;height:100%"
+                                        :data-id="item.id"
+                                    >
+                                        <component :is="getComponentName(item)" :compData="item"/>
+                                    </div>
+                                    <draggable
+                                        :list="item.child"
+                                        :group="{ name: 'component', pull: true, put: item.child&&item.child.length<3?true:false }"
+                                        animation="300"
+                                        tag="div"
+                                        class="report-drag-item-wrap_child-wrap"
+                                        @add="handleChildAdd($event,item,index)"
+                                        @remove="handleChildRemove($event,item.child)"
+                                        handle=".drag-btn_c"
+                                        style="display: flex;gap: 3px;align-items: flex-start;"
+                                    >
+                                        <div 
+                                            :class="['report-drag-item-wrap_child_content',activeId===child.id?'blue-bg':'']" 
+                                            v-for="child,cindex in item.child" 
+                                            :key="child.id"
+                                            :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" style="display: none;">
+                                                <div class="drag-btn drag-btn_c"></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 class="mark-box" v-if="isDragResize" style="position: absolute;left:0;right:0;top:0;bottom: 0;z-index: 10;"></div>
+                                        </div>
+                                    </draggable>
+                                </div>
+                            </draggable>
+
+                            <div class="html-end-img-box">
+                                <div class="opt-btn-box" style="display: none;">
+                                    <div class="del-btn" @click.stop="endImg=''"></div>
+                                </div>
+                                <img :src="endImg" alt="" style="display:block;width:100%">
+                                <div class="head-layout-item" v-for="item in endImgStyle" :key="item.value"
+                                :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
+                                    width:item.width,height:item.height,left:item.left,top:item.top
+                                }">
+                                    {{ layoutBaseInfo[item.value] }}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="right-action-wrap" v-show="showRight">
+                        <div class="close-icon" @click="handleCloseRight">
+                            <img src="~@/assets/img/smartReport/icon14.png" alt="">
+                        </div>
+                        <div style="overflow-x:auto;height:calc(100% + 12px);">
+                        <div style="min-width:800px;height: 100%;">
+                        <TextEdit 
+                            v-if="rightType==='text'"
+                            :key="activeId"
+                            :content="activeContent" 
+                            @textChange="handleTextChange" 
+                        />
+                        <ImgEdit 
+                            v-if="rightType==='img'"
+                            :key="activeId"
+                            :content="activeContent" 
+                            @imgChange="handleTextChange" 
+                        />
+                        <!-- 图库插入 -->
+                        <ETAChart 
+                            v-if="rightType==='etaChart'"
+                            @handleImportMyChart="handleImportMyChart"
+                        />
+                        <!-- ETA表格 -->
+                        <ETASheet v-if="rightType==='etaSheet'"/>
+                        <!-- 统计分析 -->
+                        <StatisticAnalysis v-if="rightType==='statisticAnalysis'"/>
+                        <!-- 商品价格曲线 -->
+                        <ETAPriceChart v-if="rightType==='etaPriceChart'"/>
+                        <!-- 沙盘图 -->
+                        <ETASandBox v-if="rightType==='etaSandBox'"/>
+                        <!-- 语义分析 -->
+                        <SemanticAnalysis v-if="rightType==='semanticAnalysis'"/>
+                        <!-- 版图资源库 -->
+                        <ImgSource v-if="rightType==='imgSource'" @change="handleInsertImgSource" @close="handleCloseRight"/>
+                        </div>
+                        </div>
+                    </div>
+                </div>
+            </template>
+
+            <!-- 报告基础信息 -->
+            <reportBaseInfo  
+                v-model="showReportBaseInfo" 
+                :reportInfo="reportCoopType===2?($refs.chapterContRef&&$refs.chapterContRef.reportBase):reportInfo"
+                :id="$route.query.id"
+                @save="handleReportEdit"
+            />
+
+            <!-- 定时发布弹窗 -->
+            <el-dialog 
+                v-dialogDrag 
+                :append-to-body="true" 
+                :visible.sync="showDSFB" 
+                width="500px" 
+                :title="$t('ReportManage.ReportList.scheduled_publish_btn')"
+            >
+                <div>
+                    <div>
+                        <span>{{$t('ReportManage.ReportList.publish_time')}}</span>
+                        <el-date-picker
+                            v-model="taskTime"
+                            type="datetime"
+                            :placeholder="$t('ReportManage.ReportList.select_date_and_time')"
+                            value-format="yyyy-MM-dd HH:mm"
+                            :picker-options="timePickerOpt"
+                        />
+                    </div>
+                    <p style="margin:15px 0">{{$t('ReportManage.ReportList.the_report_will_be_posted_on_time')}}</p>
+                    <div style="text-align:right;margin:20px 0">
+                        <el-button type="primary" plain @click="showDSFB=false">{{$t('Dialog.cancel_btn')}}</el-button>
+                        <el-button type="primary" @click="handleSetReportPrepublish">{{$t('Dialog.confirm_btn')}}</el-button>
+                    </div>
+                </div>
+            </el-dialog>
+
+        </div>
+    </div>
+</template>
+
+<script>
+import draggable from 'vuedraggable'
+import TextComp from './components/TextComp.vue'
+import ChartComp from './components/ChartComp.vue'
+import ImgComp from './components/ImgComp.vue'
+import SheetComp from './components/SheetComp.vue'
+import _ from 'lodash'
+import TextEdit from './components/TextEdit.vue'
+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 {
+	autosave,
+	reportedit,
+	reportdetail,
+	reportpublish,
+	reportSetPrepublish,
+    chapterDetail,
+	saveChapterReport,
+	publishChapterReport,
+    reportMessageSend
+} from '@/api/modules/reportV2';
+import {approveInterence} from '@/api/modules/approve.js';
+import * as sheetInterface from '@/api/modules/sheetApi.js';
+import reportBaseInfo from '../components/reportBaseInfoDia.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'
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+import ImgSource from './components/ImgSource.vue'
+import editHeader from '../components/reportEditHeader.vue';
+import chapterWrapper from '../components/chapterEditWrapper.vue';
+import smartReportDetail from './reportDetail.vue'
+import { GetQueryString } from '@/utils/common'
+export default {
+    mixins:[reportApproveConfig],
+    name:"smartReportEditV2",
+    components: {
+        draggable,
+        reportBaseInfo,
+        TextComp,
+        ChartComp,
+        ImgComp,
+        SheetComp,
+        TextEdit,
+        ImgEdit,
+        ETAChart,
+        ETASheet,
+        StatisticAnalysis,
+        ETAPriceChart,
+        ETASandBox,
+        SemanticAnalysis,
+        ImgSource,
+        editHeader,
+        chapterWrapper,
+        smartReportDetail
+    },
+    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:{},
+            showReportBaseInfo:false,
+
+            compList:[
+                {   
+                    compId:1,
+                    compType:'text',
+                    icon:require('@/assets/img/smartReport/icon10.png')
+                },
+                {
+                    compId:2,
+                    compType:'img',
+                    icon:require('@/assets/img/smartReport/icon11.png')
+                },
+                // {
+                //     compId:3,
+                //     compType:'chart',
+                // },
+                // {
+                //     compId:4,
+                //     compType:'sheet',
+                // }
+                
+            ],
+            conList:[],
+            activeId:'',
+            activeContent:'',
+            activePindex:'',
+            activeCindex:'',
+            showRight:false,
+            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,//是否正在拖动缩放
+
+            bgColor:'',//背景色
+            headImg:'',//版头图片
+            endImg:'',//版尾图片
+            headImgId:0,//版头Id
+            endImgId:0,//版尾Id
+            headImgStyle:'',//版头style
+            endImgStyle:'',//版尾style
+            layoutBaseInfo:{
+                研报标题:'',
+                研报作者:'',
+                创建时间:''
+            },
+
+            isLeftWrapShow: true,//展开章节区
+
+            reportCoopType: 0,//协作类型 1单人 2章节报告
+			selectChapterId: 0, //选中章节Id
+            editChapterId: 0,//编辑章节Id
+        }
+    },
+    methods: {
+        /* 当前章节信息 */
+		handleChapterInfo({ selectChapterId,editChapterId }) {
+            this.timer && clearInterval(this.timer);
+
+			this.selectChapterId = selectChapterId;
+			this.editChapterId = editChapterId;
+			this.showRight = false;
+            
+			this.getChapterDetail()
+		},
+
+		/* 获取章节报告详情 */
+		async getChapterDetail() {
+            if(!this.selectChapterId) return
+
+			const res = await chapterDetail({
+				ReportChapterId: this.selectChapterId
+			})
+			
+			if(res.Ret !== 200) return
+			this.reportInfo = res.Data;
+
+            this.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
+			
+			$('.edit-smart-report-page')[0].scrollTop = 0;
+			if(this.editChapterId) {
+				this.timer = setInterval(() => {
+					this.handleAutoSaveChapter();
+				}, 6000);
+			}
+		},
+
+		/* 章节自动保存 存草稿*/
+		async handleAutoSaveChapter(type='auto') {
+			
+			if(!this.reportInfo.ReportChapterId||!this.editChapterId) return
+            if(!document.getElementById('report-html-content')){
+                this.timer && clearInterval(this.timer);
+                return
+            }
+            
+			const htmlStr=document.getElementById('report-html-content').outerHTML.replace(/contenteditable="true"/g,'contenteditable="false"');
+			const res = await saveChapterReport({
+				ReportChapterId: this.reportInfo.ReportChapterId,
+				// Title: this.reportInfo.Title,
+				Content: htmlStr,
+                ContentStruct:this.formatContentListElData(),
+			})
+			if(res.Ret !== 200) return 
+
+			type==='save' && this.$message.success(res.Msg);
+		},
+
+		/* 章节预览 */
+		handlePreviewChapter() {
+            
+            const htmlStr=document.getElementById('report-html-content').outerHTML.replace(/contenteditable="true"/g,'contenteditable="false"');
+            sessionStorage.setItem('smartReportContent', htmlStr);
+            sessionStorage.setItem('smartReportContentBg', '');
+			let { href } = this.$router.resolve({ 
+                path: '/smartReportDetail',
+                query:{
+                    id:this.$route.query.id,
+                    chapterId: this.reportInfo.ReportChapterId,
+                    type:'previewChapter'
+                }
+            });
+			window.open(href, '_blank');
+		},
+
+		/* 单章节发布 */
+		async handlePublishChapter() {
+            
+			const res = await publishChapterReport({
+                ReportChapterId: this.reportInfo.ReportChapterId
+            });
+            if (res.Ret === 200) {
+                this.$message.success(this.$t('MsgPrompt.submit_msg'))
+
+                this.$refs.chapterContRef&&this.$refs.chapterContRef.getChapterList()
+
+                // this.$refs.chapterContRef.handleMarkOver(this.reportInfo.ReportChapterId)
+                // setTimeout(() => {
+                //     this.timer && clearInterval(this.timer);
+                //     this.$router.replace({ path: '/reportNew' });
+                // }, 1000);
+            }
+		},
+
+        /* 表格标题可修改,保存时获取每个sheet最新的title存进conList */
+        formatContentListElData() {
+            let newList = this.conList.map(_ => {
+                if(_.compId===4) {
+                    let params = GetQueryString(_.content);
+                    let titleText = ($(`.title_iframe${params.code}`)
+                    &&$(`.title_iframe${params.code}`)[0])
+                        ?$(`.title_iframe${params.code}`)[0].innerText
+                        :'';
+                        
+                    return {
+                        ..._,
+                        titleText
+                    }
+                }else {
+                    return _
+                }
+            })
+            
+            // console.log(newList)
+            this.contentChange = JSON.stringify(newList)===JSON.stringify(this.conList) ? this.contentChange : true;
+            return JSON.stringify(newList)
+        },
+
+        handleCheckClassifyNameArr(arr) {
+            this.checkClassifyNameArr(1,arr)
+        },
+
+        //清空内容 
+        handleClearContent() {
+            document.getElementById('report-html-content').innerHTML = '';
+            this.conList = [];
+            this.bgColor =''//背景色
+            this.headImg = ''//版头图片
+            this.endImg = ''//版尾图片
+            this.headImgId = 0//版头Id
+            this.endImgId = 0//版尾Id
+        },
+
+        // 大盒子的高度缩放
+        handleResizeP(e,index){
+            this.isDragResize=true
+            e.preventDefault()
+            const parentBox=e.target.parentNode.parentNode
+            const parentBoxWidth=parentBox.offsetWidth
+
+            const targetBox=e.target.parentNode
+            const targetBoxHeight=targetBox.offsetHeight
+            const targetBoxWidth=targetBox.offsetWidth
+
+            const startY=e.clientY
+            const startX=e.clientX
+            document.onmousemove=(mouseEl)=>{
+                mouseEl.preventDefault()
+                const h=mouseEl.clientY-startY+targetBoxHeight
+                // targetBox.style.minHeight=`${h<50?50:h}px`
+                targetBox.style.height=`${h}px`
+
+                // 去除minhight
+                targetBox.style.minHeight=`10px`
+
+                // 计算宽度
+                const w=mouseEl.clientX-startX+targetBoxWidth
+                const resW= (w/parentBoxWidth)*100//计算出的百分比结果值
+                targetBox.style.width=`${resW>=100?100:resW}%`
+            }
+            document.onmouseup=(el)=>{
+                console.log(targetBox.style.cssText);
+                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`
+                targetBox.style.height=`${h}px`
+            }   
+            document.onmouseup=(el)=>{
+                if(document.onmousemove){
+                    parentBox.childNodes.forEach(item=>{
+                        if(item!==targetBox){
+                            const temw=item.offsetWidth-computerW
+                            item.style.width=((temw/parentBoxWidth)*100)+'%'
+                        }
+                    })
+                    // 存储修改的值
+                    parentBox.childNodes.forEach((item,idx)=>{
+                        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(){
+            sessionStorage.removeItem('smartReportContent');
+            sessionStorage.removeItem('smartReportContentBg');
+            
+            if(document.getElementById('report-html-content')) {
+                const htmlStr=document.getElementById('report-html-content').outerHTML.replace(/contenteditable="true"/g,'contenteditable="false"');
+                sessionStorage.setItem('smartReportContent', htmlStr);
+                sessionStorage.setItem('smartReportContentBg', this.bgColor);
+            }
+			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';
+            // console.log(list);
+            let arr=[]
+            // 分成两个一组
+            for (let index = 0; index < list.length; index+=2) {
+                const temarr=list.slice(index,index+2)
+                let resArr={child:[]}
+                if(temarr.length===1){//落单了
+                    resArr={
+                        compId:3,
+                        compType:'chart',
+                        content:`${LINK_CHART_URL}?code=${temarr[0].UniqueCode}&lang=${this.currentLang}`,
+                        id:this.getCompId(`chart${temarr[0].UniqueCode}_`),
+                        style:'height:350px',
+                        child:[]
+                    }
+                }else{
+                    temarr.forEach(e => {
+                        resArr.child.push({
+                            compId:3,
+                            compType:'chart',
+                            content:`${LINK_CHART_URL}?code=${e.UniqueCode}`,
+                            id:this.getCompId(`chart${e.UniqueCode}_`),
+                            style:'height:350px',
+                            child:[]
+                        })
+                    });
+                }
+                arr.push(resArr)
+            }
+            // console.log(arr);
+            this.conList=[...this.conList,...arr]
+            
+        },
+
+        // 设置sheet iframe 样式
+        setSheetIframeStyle(e){
+            const { height, code } = e.data;
+            // console.log(e.data);
+            let iframeDom = document.getElementsByClassName(`iframe${code}`);
+            // console.log(iframeDom);
+            iframeDom.forEach((ele) => {
+                ele.height = `${height}px`;
+            });
+        },
+
+        handleParentAdd(e){
+            console.log('container-onAdd操作------------------->');
+
+            const {item,newDraggableIndex}=e
+
+            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
+
+            // 要添加的元素数据
+            const compData=JSON.parse(item.getAttribute('comp-data'))
+            // console.log(compData);
+            // 非注册组件返回
+            // if(!comp){
+            //     this.conList.splice(newDraggableIndex,1)
+            //     return
+            // }
+            const tempCompData={
+                compId:compData.compId,
+                compType:compData.compType,
+                id:this.getCompId(compData.compType),
+                content:compData.content||'',
+                titleText: compData.compId===4?compData.title:'',
+                style:compData.compType==='chart'?'height:350px':'',
+                child:[]
+            }
+            // console.log(tempCompData);
+            this.conList.splice(newDraggableIndex,1,tempCompData)
+            // this.activeId=tempCompData.id
+        },
+
+        handleChildAdd(e,parent,parentIndex){
+            console.log('child-onAdd操作------------------->');
+            // console.log(parent);
+            const {item,newDraggableIndex}=e
+
+            const compData=JSON.parse(item.getAttribute('comp-data'))
+
+            console.log(compData,newDraggableIndex);
+
+            const index=parentIndex
+            // if(index>-1){
+                let obj=_.cloneDeep(this.conList[index]) 
+
+                console.log(obj);
+
+                if(obj.child&&obj.child.length===1&&obj.id){
+                    if(compData){
+                        obj={
+                            child:[
+                                {
+                                    compId:obj.compId,
+                                    compType:obj.compType,
+                                    id:obj.id,
+                                    content:obj.content,
+                                    titleText: obj.compId===4?obj.titleText:'',
+                                    style:obj.compType==='chart'?'height:350px':'',
+                                    child:[]
+                                },
+                                {
+                                    compId:compData.compId,
+                                    compType:compData.compType,
+                                    content:compData.content||'',
+                                    id:this.getCompId(compData.compType),
+                                    titleText: compData.compId===4?compData.title:'',
+                                    style:compData.compType==='chart'?'height:350px':'',
+                                    child:[]
+                                }
+                            ]
+                        }
+                    }else{//是内容区域拖动排序的
+                        const temItem=_.cloneDeep(obj.child[0])
+                        if(temItem.child.length>0){//如果拖动的盒子里面有子元素则不能进入
+                            obj={
+                                ...obj,
+                                child:[]
+                            }
+                            setTimeout(() => {
+                                this.conList.splice(index,0,temItem)
+                            }, 50);
+                        }else{
+                            obj={
+                                child:[
+                                    {
+                                        compId:obj.compId,
+                                        compType:obj.compType,
+                                        id:obj.id,
+                                        content:obj.content,
+                                        titleText: obj.compId===4?obj.titleText:'',
+                                        style:obj.compType==='chart'?'height:350px':'',
+                                        child:[]
+                                    },
+                                    {
+                                        ...temItem
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                    
+                }else{
+                    if(compData){//如果是从内容区域拖入的没有compData
+                        obj.child.splice(newDraggableIndex,1,{
+                            compId:compData.compId,
+                            compType:compData.compType,
+                            content:compData.content||'',
+                            id:this.getCompId(compData.compType),
+                            titleText: compData.compId===4?compData.title:'',
+                            style:compData.compType==='chart'?'height:350px':'',
+                            child:[]
+                        })
+                    }
+                }
+                console.log(obj);
+
+                this.conList.splice(index,1,obj)
+            // }
+        },
+
+        handleParentMove(e){
+            // console.log(e.draggedContext);
+            // console.log(e.relatedContext);
+            // // console.log(e.relatedContext.compType);
+            // console.log(e.draggedContext.element.child.length>0&&!e.relatedContext.compType);
+            // if(e.draggedContext.element.child.length>0&&(!e.relatedContext.compType||e.relatedContext.element.compType)) return false
+        },
+
+        // 移除事件 
+        handleChildRemove(e,arr){
+            console.log('child-remove操作------------------->');
+            // 如果都移除了则删除这个
+            // 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){
+                    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
+                }
+            })
+        },
+
+        handleParentRemove(e){
+            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){//只剩一个子盒子了则变成一个大盒子
+                    const styleArr=this.conList[pindex].child[0].style.split(';').filter(s=>s&&(s.indexOf('width')===-1&&s.indexOf('flex')===-1)).join(';')
+                    this.conList[pindex]=this.conList[pindex].child[0]
+                    this.conList[pindex].style=styleArr
+                }
+            }
+        },
+
+        // 富文本编辑组件/图片组件数据变化
+        handleTextChange(e){
+            console.log(e);
+            this.activeContent=e
+            if(this.activeCindex>=0&&this.activeCindex!==''){
+                if(this.conList[this.activePindex].child[this.activeCindex].content){
+                    this.conList[this.activePindex].child[this.activeCindex].content=e
+                }else{
+                    this.$set(this.conList[this.activePindex].child[this.activeCindex],'content',e)
+                }
+            }else{
+                if(this.conList[this.activePindex].content){
+                    this.conList[this.activePindex].content=e
+                }else{
+                    this.$set(this.conList[this.activePindex],'content',e)
+                }
+            }
+        },
+
+        // 当前再编辑哪个
+        handleChoose(item,index,cindex){
+            //{item:数据,index:父序号,cindex:子序号}
+            if(!item.id||this.isDragResize||!['text','img'].includes(item.compType)) return
+            this.activeId=item.id
+            this.showRight=true
+            this.rightType=item.compType
+            this.activeContent=item.content||''
+            this.activePindex=index
+            this.activeCindex=cindex>=0?cindex:''
+        },
+
+        //点击顶部插入图或者图表等类型
+        handleShowRight(item){
+            this.rightType=item.type
+            this.activeId=''
+            this.activeContent=''
+            this.activePindex=''
+            this.activeCindex=''
+            this.showRight=true 
+        },
+
+        // 关闭右侧
+        handleCloseRight(){
+            this.activeId=''
+            this.activeContent=''
+            this.activePindex=''
+            this.activeCindex=''
+            this.showRight=false
+            this.rightType=''
+        },
+
+        getComponentName(item){
+            const temMap=new Map([
+                ['text',TextComp],
+                ['chart',ChartComp],
+                ['img',ImgComp],
+                ['sheet',SheetComp]
+            ])
+            return temMap.get(item.compType)
+        },
+        // 生产随机id
+        getCompId(type){
+            return type+new Date().getTime()
+        },
+
+        // 编辑保存信息
+        handleReportEdit(e){
+            
+            const params={
+                ...e,
+                ReportId:Number(this.$route.query.id)||0
+            }
+            console.log(params);
+            //检查classifynameArr是否有审批流
+            let classify = [e.ClassifyIdFirst,e.ClassifyIdSecond,e.ClassifyIdThird]
+            this.handleCheckClassifyNameArr(classify)
+
+            reportedit({...params}).then(res=>{
+                if(res.Ret===200){
+                    this.$message.success(this.$t('MsgPrompt.saved_msg'))
+
+                    if(this.reportCoopType === 1) {
+                        this.reportInfo.Title=params.Title
+                        this.layoutBaseInfo['研报标题']=params.Title
+                        this.layoutBaseInfo['研报作者']=params.Author
+                        // this.layoutBaseInfo['创建时间']=params.PublishTime
+                        this.reportInfo.ClassifyIdFirst=params.ClassifyIdFirst;
+                        this.reportInfo.ClassifyIdSecond=params.ClassifyIdSecond;
+                        this.reportInfo.ClassifyIdThird=params.ClassifyIdThird;
+                        this.reportInfo.ClassifyNameFirst=params.ClassifyNameFirst;
+                        this.reportInfo.ClassifyNameSecond=params.ClassifyNameSecond;
+                        this.reportInfo.ClassifyNameThird=params.ClassifyNameThird;
+                        this.reportInfo.Abstract=params.Abstract;
+                        this.reportInfo.Author=params.Author;
+                        this.reportInfo.CreateTime=params.CreateTime;
+                        this.reportInfo.IsPublicPublish=params.IsPublicPublish;
+                    }else {
+                        this.$refs.chapterContRef.getReportBaseInfo('notCheck')
+                    }
+
+                    this.showReportBaseInfo=false
+                }
+            })
+        },
+
+        /* 获取动态配置 外部动态链接 */
+        async getPublicSettings() {
+            const res =  await getPublicSettingsApi();
+            if(res.Ret !== 200) return
+            
+            this.$store.commit('SET_DYNAMIC_LINK',res.Data)
+        },
+
+        // 获取报告详情
+        getReportDetail(){
+            const id=this.$route.query.id||0
+            if(!id) return
+
+            reportdetail({
+                ReportId:Number(id)
+            }).then(res=>{
+                if(res.Ret===200){
+                    this.reportInfo=res.Data
+
+                    if(res.Data.PrePublishTime){
+                        this.taskTime=res.Data.PrePublishTime
+                    }
+                    
+                    this.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
+                    this.headImg=res.Data.HeadImg
+                    this.endImg=res.Data.EndImg
+                    this.headImgId=res.Data.HeadResourceId
+                    this.endImgId=res.Data.EndResourceId
+
+                    this.headImgStyle=res.Data.HeadStyle?JSON.parse(res.Data.HeadStyle):[]
+                    this.headImgStyle.map(st =>{
+                        st.value=st.value || st.label
+                    })
+                    this.endImgStyle=res.Data.EndStyle?JSON.parse(res.Data.EndStyle):[]
+                    this.endImgStyle.map(st =>{
+                        st.value=st.value || st.label
+                    })
+                    this.bgColor=res.Data.CanvasColor
+                    this.layoutBaseInfo['研报标题']=res.Data.Title
+                    this.layoutBaseInfo['研报作者']=res.Data.Author
+                    // this.layoutBaseInfo['创建时间']=res.Data.PublishTime
+                    this.$nextTick(()=>{
+                        this.contentChange=false
+                    })
+                    let classify = [res.Data.ClassifyIdFirst,res.Data.ClassifyIdSecond]
+                    this.handleCheckClassifyNameArr(classify)
+                }
+            })
+        },
+
+        // 刷新所有图表和表格
+        handleRefreshAllChart: _.debounce ( async function() {
+            let code_arr = [];
+            let sheet_code_arr = []
+            $('iframe').each((k,i) => {
+                try {
+                    let href = $(i).attr('src');
+                    if(href.includes('chartshow')){
+                        code_arr.push(getUrlParams(href,'code'));
+                    }
+                    if(href.includes('sheetshow')){
+                        sheet_code_arr.push(getUrlParams(href,'code'))
+                    }
+                } catch (err) {
+                }
+            });
+
+            if(!code_arr.length&&!sheet_code_arr.length) return this.$message.warning(this.$t('ReportManage.ReportList.insert_charts_msg'));
+
+            if(this.$route.query.id&&code_arr.length) {
+                let res = await dataBaseInterface.getReportrefreshStatus({
+                    Source: 'report',
+                    PrimaryId: Number(this.$route.query.id),
+                    SubId: this.reportInfo.ReportChapterId
+                });
+                
+                if(!res.Data.RefreshResult) return this.$message.warning(this.$t('ReportManage.ReportList.chart_refreshed_msg'))
+
+                const { Ret,Msg } = await dataBaseInterface.reportRefresh({
+                    ChartInfoCode: code_arr,
+                    Source: 'report',
+                    PrimaryId: Number(this.$route.query.id),
+                    SubId: this.reportInfo.ReportChapterId
+                })
+                
+                if(Ret === 200) {
+                    $('iframe').each((k,i) => {
+                        let href = $(i).attr('src');
+                        if(href.includes('chartshow')){
+                            $(i).attr('src',$(i).attr('src'))
+                        }
+                    });
+                    this.$message.success(Msg);
+                }
+            }
+            if(this.$route.query.id&&sheet_code_arr.length){
+                //获取刷新结果
+                let res = await sheetInterface.getRefreshResult({
+                    Source: 'report',
+                    PrimaryId: Number(this.$route.query.id),
+                    SubId: this.reportInfo.ReportChapterId
+                });
+                if(!res.Data.RefreshResult) return this.$message.warning(/* '表格正在刷新中,请勿重复操作' */this.$t('ReportManage.ReportList.chart_refreshed_msg'))
+                const { Ret,Msg } = await sheetInterface.refreshSheet({
+                    ExcelCodes: sheet_code_arr,
+                    Source: 'report',
+                    PrimaryId: Number(this.$route.query.id),
+                    SubId: this.reportInfo.ReportChapterId
+                })
+                
+                if(Ret === 200) {
+                    $('iframe').each((k,i) => {
+                        let href = $(i).attr('src');
+                        if(href.includes('sheetshow')){
+                            $(i).attr('src',$(i).attr('src'))
+                        }
+                    });
+                    this.$message.success(Msg);
+                }
+            }
+
+        },1000),
+        
+        // 自动/存草稿保存内容
+        handleSaveContent({isAutoSave}){
+            const html=document.getElementById('report-html-content').outerHTML.replace(/contenteditable="true"/g,'contenteditable="false"');
+            return new Promise((resolve,reject)=>{
+                const id=this.$route.query.id||0
+                if(!id) return
+
+                let imgParams = {
+                    HeadImg: this.reportCoopType===1?this.headImg:this.$refs.chapterContRef.reportBase.HeadImg,
+                    EndImg:this.reportCoopType===1?this.endImg:this.$refs.chapterContRef.reportBase.EndImg,
+                    HeadResourceId:this.reportCoopType===1?this.headImgId:this.$refs.chapterContRef.reportBase.HeadResourceId,
+                    EndResourceId:this.reportCoopType===1?this.endImgId:this.$refs.chapterContRef.reportBase.EndResourceId,
+                    CanvasColor:this.reportCoopType===1?this.bgColor:this.$refs.chapterContRef.reportBase.CanvasColor
+                }
+                
+                autosave({
+                    ReportId: Number(this.$route.query.id),
+                    Content:html,
+                    ContentStruct:this.formatContentListElData(),
+                    NoChange:this.contentChange?2:1,
+                    ...imgParams
+                }).then(res=>{
+                    if(res.Ret===200){
+                        resolve(true)
+                        if(!isAutoSave){
+                            this.$message.success(this.$t('MsgPrompt.saved_msg'))
+                        }
+                    }
+                })
+            })
+        },
+
+        // 点击定时发布/发布
+        async handlePublishOpt(type){
+            if(document.getElementById('report-html-content')) { 
+                // 存一次草稿
+                const saveRes=await this.handleSaveContent({isAutoSave:true})
+                if(!saveRes) return
+            }
+
+            if(type==='dsfb'){
+                this.showDSFB=true
+                return
+            }
+            // 发布
+            if(type==='submit'){
+                this.submitReport()
+                return
+            }
+            //截止至ETA1.3.8 智能研报无推送模板消息,所有的reportInfo.MsgIsSend都为1
+            let sendMsg = this.reportCoopType===2 ? this.$refs.chapterContRef.reportBase.MsgIsSend : this.reportInfo.MsgIsSend;
+            if(sendMsg===1){//该报告已经推送过模板消息
+                this.reportPublish({sendMsg:false})
+            }else{
+                const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)
+                this.$confirm(
+                    isPost?this.$t('ReportManage.smart_msg.publishing_messages'):this.$t('ReportManage.smart_msg.should_published_immediately'), 
+                    this.$t('ReportManage.smart_release_prompt_btn'), 
+                    {
+                        confirmButtonText: isPost?this.$t('ReportManage.smart_btn.push'):this.$t('ReportManage.smart_btn.publish'),
+				        cancelButtonText: isPost?this.$t('ReportManage.smart_btn.not_push'):this.$t('Dialog.cancel_btn'),
+                        type: 'warning',
+                        distinguishCancelAndClose:true,
+                    
+                        beforeClose:(action, instance,done)=>{
+                            if(action==='close') {
+                                //右上角
+                                // this.isPublishloading = false;
+                            } else if(action==='cancel') {
+                                //cancelButton
+                                if(isPost){
+                                    this.reportPublish({sendMsg:false})
+                                }
+                            }else {
+                                //confirmButton
+                                this.reportPublish({sendMsg:isPost?true:false})
+                            }
+                            done()
+                        }
+                    }
+                )
+            }
+        },
+        //提交报告
+        submitReport(){
+             this.$confirm(this.$t('ReportManage.smart_msg.submit_approval'),this.$t('Confirm.prompt'),{
+                confirmButtonText: this.$t('Dialog.confirm_btn'),
+                cancelButtonText: this.$t('Dialog.cancel_btn'),
+                type:'warning',
+            }).then(()=>{
+
+                approveInterence.reportCnSubmit({
+                    ReportId:Number(this.$route.query.id)
+                }).then(res=>{
+                    if(res.Ret!==200) return 
+                    this.$message.success(this.$t('ReportManage.smart_msg.submit_success'))
+                    this.$router.replace({ path: '/reportNew' });
+                })
+            })
+        },
+
+        // 定时发布报告
+        async handleSetReportPrepublish(){
+            if(!this.taskTime){
+				this.$message.warning(this.$t('ReportManage.smart_msg.select_push_time'))
+				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(this.$t('ReportManage.smart_msg.than_current_time'))
+				return
+			}
+            // 如果该报告已经推送过模板消息
+            let sendMsg = this.reportCoopType===2 ? this.$refs.chapterContRef.reportBase.MsgIsSend : this.reportInfo.MsgIsSend;
+            if(sendMsg===1){
+                reportSetPrepublish({
+                    ReportId:Number(this.$route.query.id),
+                    PrePublishTime:this.taskTime,
+                    PreMsgSend:0,
+                    ReportUrl:this.generatePdfLinks()
+                }).then(res=>{
+                    if(res.Ret===200){
+                        this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+                        this.$router.replace({ path: '/reportNew' });
+                    }
+                })
+                return
+            }
+
+            const isPost = this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_sendMsg)
+
+           this.$confirm(isPost?this.$t('ReportManage.smart_msg.push_report_msg'):this.$t('ReportManage.smart_msg.is_push_timed'), this.$t('ReportManage.smart_release_prompt_btn'), {
+				confirmButtonText: isPost?this.$t('ReportManage.smart_btn.push'):this.$t('ReportManage.smart_btn.publish'),
+				cancelButtonText: isPost?this.$t('ReportManage.smart_btn.not_push'):this.$t('Dialog.cancel_btn'),
+				type: 'warning',
+				distinguishCancelAndClose:true,
+				beforeClose:(action, instance,done)=>{
+					console.log(action, instance);
+					if(action==='close'||action==='cancel') {
+						//右上角或者不推送
+						if(isPost){
+							reportSetPrepublish({
+								ReportId:Number(this.$route.query.id),
+								PrePublishTime:this.taskTime,
+								PreMsgSend:0,
+                                ReportUrl:this.generatePdfLinks()
+							}).then(res=>{
+								if(res.Ret===200){
+									this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+									this.$router.replace({ path: '/reportNew' });
+								}
+							})
+						}
+					} else {
+						//confirmButton
+						reportSetPrepublish({
+							ReportId:Number(this.$route.query.id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:isPost?1:0,
+                            ReportUrl:this.generatePdfLinks()
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success(this.$t('ReportManage.smart_msg.timed_success'))
+								this.$router.replace({ path: '/reportNew' });
+							}
+						})
+					}
+					done()
+				}
+			})
+        },
+
+        // 发布报告
+        reportPublish({sendMsg}){
+            reportpublish({
+                ReportIds:String(this.$route.query.id),
+                ReportUrl:this.generatePdfLinks()
+            }).then(res=>{
+                if(res.Ret===200){
+                    if(sendMsg){
+                        this.reportSendMsg()
+                    }
+                    this.$message.success(this.$t('MsgPrompt.publish_msg'))
+
+                    setTimeout(() => {
+                        this.$router.replace({ path: '/reportNew' });
+                    },1000)
+                }
+            })
+        },
+        generatePdfLinks(){
+            const baseUrl= localStorage.getItem('dynamicOutLinks') ? JSON.parse(localStorage.getItem('dynamicOutLinks')).ReportViewUrl : '';
+            let waterMarkStr= localStorage.getItem('waterMarkStr') || '';
+
+            let code = this.reportCoopType===2?this.$refs.chapterContRef&&this.$refs.chapterContRef.reportBase.ReportCode:this.reportInfo.ReportCode
+
+            return `${baseUrl}/reportshare_smart_pdf?code=${code}&flag=${waterMarkStr}`
+        },
+        //报告消息推送
+        reportSendMsg(){
+            reportMessageSend({ReportId:Number(this.$route.query.id)}).then(res=>{})
+        },
+
+        // 插入版头版尾
+        handleInsertImgSource(e){
+            console.log(e,'eeee');
+            if(e.type=='1'){
+                this.$message.success(this.$t('ReportManage.ReportList.header_setting_msg'))
+                this.headImg=e.data.ImgUrl
+                this.headImgId = e.data.ResourceId
+                this.headImgStyle=e.data.Style?JSON.parse(e.data.Style):[]
+            }else{
+                this.$message.success(this.$t('ReportManage.ReportList.trailer_setting_msg'))
+                this.endImg=e.data.ImgUrl
+                this.endImgId = e.data.ResourceId
+                this.endImgStyle=e.data.Style?JSON.parse(e.data.Style):[]
+            }
+            this.contentChange=true
+        },
+
+        handleBgColorChange(e){
+            this.bgColor=e||''
+            this.contentChange=true
+        },
+        // 删除版头版尾
+        deleteLayoutPic(type){
+            if(type=='1'){
+                this.headImg=''
+                this.headImgId = 0
+            }else{
+                this.endImg=''
+                this.endImgId = 0
+            }
+            this.contentChange=true
+        }
+    },
+    computed:{
+      topTypeList(){
+           return [
+                {
+                    name:this.$t('ReportManage.ReportList.library_top_type'),
+                    type:'imgSource',
+                    visable: this.reportCoopType!==2,
+                    icon:require('@/assets/img/smartReport/icon04.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.chart_top_type'),
+                    type:'etaChart',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon04.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.eta_top_type'),
+                    type:'etaSheet',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon05.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_top_type'),
+                    type:'statisticAnalysis',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon06.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.price_curve_radio'),
+                    type:'etaPriceChart',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon07.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.sandbox_top_type'),
+                    type:'etaSandBox',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon08.png')
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.semantic_top_type'),
+                    type:'semanticAnalysis',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon09.png')
+                }
+            ]
+      },
+
+      //语言版本
+      currentLang() {
+        return this.$store.state.lang
+      }
+    },
+    created() {
+        this.getPublicSettings()
+        this.reportCoopType = Number(this.$route.query.coopType)
+        this.reportCoopType===1 && this.getReportDetail()
+    },
+    mounted () {
+        window.addEventListener('message',this.setSheetIframeStyle)
+        if(this.reportCoopType===1) {
+            this.timer = setInterval(() => {
+                this.handleSaveContent({isAutoSave:true});
+            }, 6000);
+        }
+    },
+    destroyed() {
+		window.removeEventListener('message',this.setSheetIframeStyle)
+        if (this.timer) {
+			clearInterval(this.timer);
+		}
+	},
+}
+</script>
+
+<style lang="scss">
+// 拖拽时的样式
+.edit-smart-report-page{
+.sortable-ghost{
+    position: relative !important;
+    &::before{
+        content: '' !important;
+        display: block !important;
+        width: 100% !important;
+        height: 10px !important;
+        background-color: rgba(64, 158, 255, 0.74) !important;
+        position: absolute !important;
+        left: 0 !important;
+        top: 0 !important;
+    }
+    // height: 5px !important;
+    // background-color: #0052D9 !important;
+    // overflow: hidden !important;
+    // padding: 0 !important;
+    // min-height: 0 !important;
+    // border: none !important;
+}
+
+.el-color-picker__trigger{
+    &::after{
+        content:'';
+        display: block;
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: #fff;
+    }
+    .el-color-picker__color::after{
+        content: '';
+        display: block;
+        width: 16px;
+        height: 16px;
+        position: absolute;
+        left: 7px;
+        top: 7px;
+        background-image: url('~@/assets/img/smartReport/icon18.png');
+        background-size: cover;
+        background-repeat: no-repeat;
+        z-index: 10;
+    }
+}
+
+}
+</style>
+<style lang='scss' scoped>
+div{
+    box-sizing: border-box;
+}
+.edit-smart-box {  
+    display: flex;
+	overflow: hidden;
+    background: var(--unnamed, #F2F6FA);
+
+    .left-wrap {
+        position: relative;
+		.slide-btn-icon {
+			&.slide-left{
+					right:5px;
+					left: auto;
+			}
+			&.slide-right{
+					left: 0;
+					right: auto;
+			}
+		}
+    }
+}
+
+.edit-smart-report-page{
+    /* min-width: 100vw; */
+    min-height: 100vh;
+    flex: 1;
+    overflow: auto;
+    .top-action-wrap{
+        position: sticky;
+        top: 0px;
+        background-color: #fff;
+        box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.10);
+        height: 60px;
+        display: flex;
+        justify-content: space-between;
+        align-content: center;
+        padding: 0 24px;
+        .title{
+            line-height: 60px;
+            font-size: 16px;
+        }
+        .action-list{
+            display: flex;
+            align-items: center;
+            .action-item{
+                height: 36px;
+                display: flex;
+                align-items: center;
+                border-right: 1px solid #C8CDD9;
+                padding: 0 30px;
+                font-size: 16px;
+                cursor: pointer;
+                img{
+                    width: 16px;
+                    height: 16px;
+                    margin-right: 4px;
+                    position: relative;
+                    top: 2px;
+                }
+                &:last-child{
+                    border-right: none;
+                }
+                &.disabled{
+                    pointer-events: none;
+                    cursor: not-allowed;
+                    color:#999;
+                }
+            }
+        }
+    }
+    .main-wrap{
+        display: flex;
+        justify-content: center;
+    }
+}
+.report-action-wrap{
+    width: 800px;
+    flex-shrink: 0;
+    margin-left: 90px;
+    margin-right: 60px;
+    margin-top: 30px;
+    position: relative;
+    .report-comp-wrap{
+            position: absolute;
+            left: -62px;
+            top: 72px;
+            width: 40px;
+            border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+            background: var(--gary-gy-white, #FFF);
+            border-radius: 4px;
+            overflow: hidden;
+            .comp-item{
+                cursor: move;
+                height: 40px;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                border-bottom: 1px solid var(--gary-gy-5-line, #C8CDD9);
+                &:last-child{
+                    border-bottom: none;
+                }
+                img{
+                    width: 16px;
+                }
+            }
+    }
+    .top-type-list{
+        margin-bottom: 20px;
+        display: flex;
+        align-items: center;
+        background-color: #fff;
+        height: 80px;
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        .item{
+            cursor: pointer;
+            flex: auto;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            border-right: 1px solid #C8CDD9;
+            font-size: 16px;
+            &:last-child{
+                border-right: none;
+            }
+            .icon{
+                width: 20px;
+                height: 20px;
+                // margin-right: 4px;
+            }
+        }
+    }
+    .report-content-box{
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #C8CDD9);
+        background: #FFF;
+        padding: 20px 20px 20px 44px;
+        height: calc(100vh - 210px);
+        position: relative;
+        overflow-y: auto;
+        .html-head-img-box,.html-end-img-box{
+            position: relative;
+            &:hover{
+                .opt-btn-box{
+                    display: block !important;
+                }
+            }
+            .opt-btn-box{
+                position: absolute;
+                left: -36px;
+                padding-right: 8px;
+                top: 0;
+                .del-btn::after{
+                    content: '';
+                    display: block;
+                    width: 28px;
+                    height: 28px;
+                    background-image: url('~@/assets/img/smartReport/icon13.png');
+                    background-size: cover;
+                    cursor: pointer;
+                }
+            }
+            .head-layout-item{
+                position: absolute;
+                overflow: hidden;
+                box-sizing: border-box
+            }
+        }
+    }
+}
+
+
+
+.main-wrap{
+    .report-html-wrap{
+        &::after{
+            content: '';
+            display: block;
+            height: 300px;
+        }
+        min-height: 100%;
+        .report-drag-item-wrap{
+            width: 100%;
+            padding: 6px;
+            min-height: 80px;
+            border: 1px dashed #0052D9;
+            position: relative;
+            margin-bottom: 3px;
+            &:hover{
+                border-style: solid;
+                .opt-btn-box{
+                    display: block !important;
+                }
+                .resize-drag-box{
+                    display: block;
+                }
+            }
+            .opt-btn-box{
+                position: absolute;
+                left: -36px;
+                padding-right: 8px;
+                top: 0;
+                .drag-btn::after{
+                    content: '';
+                    display: block;
+                    width: 28px;
+                    height: 28px;
+                    background-image: url('~@/assets/img/smartReport/icon12.png');
+                    background-size: cover;
+                    cursor: pointer;
+                }
+                .del-btn::after{
+                    content: '';
+                    display: block;
+                    width: 28px;
+                    height: 28px;
+                    background-image: url('~@/assets/img/smartReport/icon13.png');
+                    background-size: cover;
+                    cursor: pointer;
+                }
+            }
+            .resize-drag-box{
+                position: absolute;
+                right: -4px;
+                bottom: -4px;
+                width: 8px;
+                height: 8px;
+                display: none;
+                border: 1px solid #0052D9;
+                cursor: nw-resize;
+            }
+        }
+        .report-drag-item-out{
+            .report-drag-item-wrap_child-wrap{
+                position: absolute;
+                width: 40px;
+                right: 0;
+                top: 0;
+                height: 100%;
+            }
+        }
+        .report-drag-item-wrap_child-wrap{
+            // min-height: 30px;
+        }
+        .report-drag-item-wrap_child_content{
+            min-height: 80px;
+            border: 1px dashed #0052D9;
+            flex: 1;
+            position: relative;
+            &:hover{
+                border-style: solid;
+                .opt-btn-box2{
+                    display: block !important;
+                }
+                .resize-drag-box_lt,
+                .resize-drag-box_lb,
+                .resize-drag-box_rt,
+                .resize-drag-box_rb{
+                    display: block;
+                }
+            }
+            .opt-btn-box2{
+                position: absolute;
+                right: -15px;
+                top: 0;
+                z-index: 10;
+                .drag-btn::after{
+                    content: '';
+                    display: block;
+                    width: 28px;
+                    height: 28px;
+                    background-image: url('~@/assets/img/smartReport/icon12.png');
+                    background-size: cover;
+                    cursor: pointer;
+                }
+                .del-btn::after{
+                    content: '';
+                    display: block;
+                    width: 28px;
+                    height: 28px;
+                    background-image: url('~@/assets/img/smartReport/icon13.png');
+                    background-size: cover;
+                    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);
+        }
+    }
+}
+
+.main-wrap{
+    .right-action-wrap{
+        height: calc(100vh - 60px);
+        overflow: hidden;
+        flex: 1;
+        position: relative;
+        padding-top: 30px;
+        padding-left: 75px;
+        padding-right: 30px;
+        padding-bottom: 30px;
+        &::before{
+            display: block;
+            content: '';
+            width: 1px;
+            height: 100vh;
+            background-color: #C8CDD9;
+            position: absolute;
+            left: 15px;
+            top: 0;
+        }
+        .close-icon{
+            width: 20px;
+            height: 20px;
+            border-radius: 4px;
+            background: #FFF;
+            box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            cursor: pointer;
+            position: absolute;
+            left: 5px;
+            top: 22px;
+            img{
+                width: 16px;
+                height: 16px;
+            }
+        }
+    }
+}
+</style>

+ 392 - 0
src/views/report_manage/reportV2/smartReport/reportDetail.vue

@@ -0,0 +1,392 @@
+<template>
+    <div class="smart-report-detail">
+        <div class="main-box" :style="{backgroundColor:bgColor}">
+
+            <!-- 版头 -->
+            <div class="html-head-img-box" v-if="reportInfo && !!reportInfo.NeedSplice && reportInfo.HeadImg&&$route.query.type!=='previewChapter'">
+                <img :src="reportInfo.HeadImg" alt="" style="display:block;width:100%">
+                <div class="head-layout-item" v-for="item in headImgStyle" :key="item.value"
+                :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
+                    width:item.width,height:item.height,left:item.left,top:item.top
+                }">
+                    {{ layoutBaseInfo[item.value] }}
+                </div>
+            </div>
+
+            <!-- 无版头版尾 -->
+            <div class="no-layout-img-box" v-if="(reportInfo && !!reportInfo.NeedSplice && (!reportInfo.HeadImg) && (!reportInfo.EndImg))||$route.query.type==='previewChapter'">
+                <header>{{reportInfo.Title}}</header>
+                <div style=" box-sizing:border-box; color:#666; font-size:24px; overflow:hidden;">
+                    <span>{{ reportInfo.Author}}</span>
+                    <span style="float:right;" v-if="[2,6].includes(reportInfo.State)">{{reportInfo.PublishTime}}</span>
+                </div>
+            </div>
+
+            <div class="abstract" v-if="reportInfo && !!reportInfo.NeedSplice&&reportInfo.Abstract">
+                <div>摘要: <span v-html="reportInfo.Abstract"></span></div> 
+            </div>
+
+
+            <!-- 内容 -->
+            <template>
+                <!-- 章节报告 -->
+                <template v-if="reportInfo&&reportInfo.CollaborateType===2&&!$route.query.chapterId">
+                    <div class="chapter-item" v-for="item in reportInfo.ChapterList" :key="item.ReportChapterId">
+                        <div style="margin-bottom:10px">
+                            <span class="type" v-if="item.TypeName">{{item.TypeName}}</span>
+                            <span class="title">{{item.Title}}</span>
+                        </div>
+                        <div class="html-wrap" v-html="item.Content"></div>
+                    </div>
+                </template>
+
+                <!-- 单报告 -->
+                <div class="html-wrap" v-html="content" v-else></div>
+            </template>
+
+            <!-- 板尾 -->
+            <div class="html-end-img-box" v-if="reportInfo && !!reportInfo.NeedSplice && reportInfo.EndImg&&$route.query.type!=='previewChapter'">
+                <img :src="reportInfo.EndImg" alt="" style="display:block;width:100%">
+                <div class="head-layout-item" v-for="item in endImgStyle" :key="item.value"
+                :style="{fontFamily:item.family,fontSize:(item.size*2)+'px',fontWeight:item.weight,textAlign:item.align,color:item.color,
+                    width:item.width,height:item.height,left:item.left,top:item.top
+                }">
+                    {{ layoutBaseInfo[item.value] }}
+                </div>
+            </div> 
+        </div>
+
+        <div class="right-opt-box" v-if="$route.query.type!=='preview'&&!reportId">
+            <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;margin-right: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;margin-right:10px;">
+                <span>微信分享</span>
+                <vue-qr 
+                    :text="linkUrl" 
+                    :margin="0" 
+                    colorDark="#333" 
+                    colorLight="#fff" 
+                    :dotScale="1" 
+                    :size="100" 
+                    class="qrcode"
+                ></vue-qr>
+            </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 {
+	reportdetail,
+} from '@/api/modules/reportV2';
+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
+		},
+        //是否开启审批流,若开启,导图按钮在非已审批的状态不显示
+        isApprove(){
+            const type = this.$setting.dynamicOutLinks.ApprovalFlow ||
+                        this.$store.state.dynamicOutLinks.ApprovalFlow ||
+                        JSON.parse(localStorage.getItem('dynamicOutLinks')).ApprovalFlow||''
+            return ['2','3'].includes(type)
+        }
+    },
+    props:{
+        reportId:{//审批详情-预览报告
+            type:Number,
+            default:0
+        },
+        info: { //章节预览
+            type: Object
+        }
+    },
+    watch:{
+        info(nval) {
+            this.reportInfo = nval;
+            this.layoutBaseInfo['研报标题']=this.reportInfo.Title
+            this.layoutBaseInfo['研报作者']=this.reportInfo.Author
+            this.layoutBaseInfo['创建时间']=[2,6].includes(this.reportInfo.State)?this.reportInfo.PublishTime:''
+            this.content=this.reportInfo.Content
+        }
+    },
+    data() {
+        return {
+            /**
+             * NeedSplice 0-不需要 1-需要
+             */
+            reportInfo:null,
+            content:'',
+            bgColor:'',
+            reportImgUrl:'',
+            showReportImg:false,
+            headImgStyle:null,//版头style
+            endImgStyle:null,//版尾style
+            layoutBaseInfo:{
+                研报标题:'',
+                研报作者:'',
+                创建时间:''
+            }
+        }
+    },
+    created() {
+        //内嵌章节预览
+        if(this.info) {
+            this.reportInfo = this.info;
+            this.layoutBaseInfo['研报标题']=this.reportInfo.Title
+            this.layoutBaseInfo['研报作者']=this.reportInfo.Author
+            this.layoutBaseInfo['创建时间']=[2,6].includes(this.reportInfo.State)?this.reportInfo.PublishTime:''
+            this.content=this.reportInfo.Content
+            return 
+        }
+        this.getReportDetail()
+    },
+    methods: {
+        // 获取报告详情
+        getReportDetail(){
+            const id=this.$route.query.id||this.reportId||0
+            if(!id) return
+            this.$emit("reportStartLoading")
+            reportdetail({
+                ReportId:Number(id)
+            }).then(res=>{
+                this.$emit("reportEndLoading")
+                if(res.Ret===200){
+                    this.reportInfo=res.Data || {}
+                    this.headImgStyle=this.reportInfo.HeadStyle?JSON.parse(this.reportInfo.HeadStyle):[]
+                    this.headImgStyle.map(st =>{
+                        st.value=st.value || st.label
+                    })
+                    this.endImgStyle=this.reportInfo.EndStyle?JSON.parse(this.reportInfo.EndStyle):[]
+                    this.endImgStyle.map(st =>{
+                        st.value=st.value || st.label
+                    })
+                    this.layoutBaseInfo['研报标题']=this.reportInfo.Title
+                    this.layoutBaseInfo['研报作者']=this.reportInfo.Author
+                    this.layoutBaseInfo['创建时间']=[2,6].includes(this.reportInfo.State)?this.reportInfo.PublishTime:''
+                    if(['preview','previewChapter'].includes(this.$route.query.type)){
+                       this.content=sessionStorage.getItem('smartReportContent')||res.Data.Content;
+                       this.reportInfo.Abstract = this.$route.query.type==='preview'?this.reportInfo.Abstract : ''; 
+                       this.bgColor=this.$route.query.type==='preview'?(sessionStorage.getItem('smartReportContentBg')||res.Data.CanvasColor):''
+                    }else{
+                        this.content=res.Data.Content
+                        this.bgColor=res.Data.CanvasColor
+                    }
+                }else{
+                    this.$emit("reportError")
+                }
+            })
+        },
+
+        /* 复制链接 */
+		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
+                    // 改为直接下载图片不是展示
+                    this.saveImg(res.Data)
+                }else{
+                    if(res.Ret!==403){
+                        this.$message.warning(res.Msg)
+                    }
+                }
+            })
+        },
+
+        saveImg(imgUrl){
+            let img=new Image()
+            img.setAttribute('crossOrigin', 'anonymous');
+            img.src=imgUrl
+            img.onload=()=>{
+                let canvas = document.createElement("canvas");
+                canvas.width = img.width;
+                canvas.height = img.height;
+                let context = canvas.getContext('2d');
+                context.drawImage(img, 0, 0, img.width, img.height);
+                let dataURL = canvas.toDataURL("image/png", 1);
+                const a=document.createElement('a')
+                a.setAttribute("download",this.reportInfo.Title)
+                a.style.display = "none"
+                a.href=dataURL
+                document.body.appendChild(a);
+                a.click()
+            }
+            img.onerror=(e)=>{
+                console.log(e);
+                this.$message.warning("自动下载图片失败,请手动保存")
+                if(imgUrl){
+                    this.reportImgUrl=imgUrl
+                    this.showReportImg=true
+                }
+            }
+        }
+    },
+}
+</script>
+
+<style lang="scss">
+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{
+        max-width: 1200px;
+        padding: 20px 20px 20px 44px;
+        margin: 20px 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-drag-item-wrap{
+                padding: 6px;
+                margin-bottom: 3px;
+            }
+        }
+        .html-head-img-box,.html-end-img-box{
+            position: relative;
+            .head-layout-item{
+                position: absolute;
+                overflow: hidden;
+                box-sizing: border-box
+            }
+        }
+        .no-layout-img-box{
+            header{
+                padding:10px 0; box-sizing:border-box; font-size:28px; font-weight:500; color:#333;
+            }
+        }
+        .abstract{
+            padding:10px 0; box-sizing:border-box; font-size:22px; line-height:36px;
+            div{
+                padding: 10px 20px;
+                box-sizing: border-box;
+                background: rgba(20, 121, 253, 0.1);
+                color: #4099ef;
+                border-radius: 10px;
+            }
+        }
+    }
+    .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;
+        }
+    }
+
+    .chapter-item{
+        padding: 20px 0;
+        border-bottom: 1px dashed #ccc;
+        .type{
+            font-size: 15px;
+            color: #fff;
+            padding: 5px 10px;
+            background-color: #E6A23C;
+            border-radius: 4px;
+        }
+        .title{
+            font-size: 15px;
+            margin-left: 10px;
+            font-weight: bold;
+        }
+    }
+}
+</style>

+ 6 - 2
src/views/smartReport/editReport.vue

@@ -500,7 +500,7 @@ export default {
                     resArr={
                         compId:3,
                         compType:'chart',
-                        content:`${LINK_CHART_URL}?code=${temarr[0].UniqueCode}`,
+                        content:`${LINK_CHART_URL}?code=${temarr[0].UniqueCode}&lang=${this.currentLang}`,
                         id:this.getCompId(`chart${temarr[0].UniqueCode}_`),
                         style:'height:350px',
                         child:[]
@@ -1181,7 +1181,11 @@ export default {
                     icon:require('@/assets/img/smartReport/icon09.png')
                 }
             ]
-      }
+      },
+       //语言版本
+        currentLang() {
+            return this.$store.state.lang
+        }
     },
     created() {
         this.getPublicSettings()

+ 1 - 1
src/views/system_manage/etaBaseConfig.vue

@@ -651,7 +651,7 @@ export default {
             sectionType:1,//1通用设置 2资源库
 
             reportFromType: [
-                { type:'smartReport',label: /* '智能研报' */ this.$t('SystemManage.BaseConfig.report_type1') },
+                // { type:'smartReport',label: /* '智能研报' */ this.$t('SystemManage.BaseConfig.report_type1') },
                 { type:'report',label: /* '研报列表' */this.$t('SystemManage.BaseConfig.report_type2') },
                 { type:'enReport',label: /* '英文研报' */this.$t('SystemManage.BaseConfig.report_type3') },
             ],

部分文件因为文件数量过多而无法显示