فهرست منبع

Merge branch 'master' of http://8.136.199.33:3000/eta_front/eta_front

Karsa 11 ماه پیش
والد
کامیت
414134673c
42فایلهای تغییر یافته به همراه2046 افزوده شده و 254 حذف شده
  1. 4 2
      src/api/api.js
  2. 21 0
      src/api/modules/sheetApi.js
  3. 20 0
      src/api/modules/smartReport.js
  4. 28 1
      src/api/modules/thirdBaseApi.js
  5. BIN
      src/assets/img/icons/fullsreen.png
  6. BIN
      src/assets/img/icons/more.png
  7. BIN
      src/assets/img/smartReport/icon17.png
  8. BIN
      src/assets/img/smartReport/icon18.png
  9. 130 42
      src/components/lzTable.vue
  10. 9 0
      src/routes/modules/dataRoutes.js
  11. 3 2
      src/utils/buttonConfig.js
  12. 12 12
      src/views/Login.vue
  13. 19 0
      src/views/chartFrame_manage/common/config.js
  14. 1 5
      src/views/chartFrame_manage/common/graph.js
  15. 31 6
      src/views/chartFrame_manage/components/frameContainer.vue
  16. 9 1
      src/views/chartFrame_manage/components/frameToolBar.vue
  17. 9 1
      src/views/chartFrame_manage/css/basePage.scss
  18. 1 1
      src/views/chartFrame_manage/css/customTree.scss
  19. 14 2
      src/views/chartFrame_manage/frameEditor.vue
  20. 16 8
      src/views/chartFrame_manage/index.vue
  21. 564 0
      src/views/dataEntry_manage/thirdBase/YyzxData.vue
  22. 7 1
      src/views/login_manage/EmailModel.vue
  23. 8 5
      src/views/login_manage/MobileModel.vue
  24. 1 1
      src/views/login_manage/modelMixins.js
  25. 84 8
      src/views/mychart_manage/index.vue
  26. 4 1
      src/views/ppt_manage/newVersion/pptCatalog.vue
  27. 4 1
      src/views/ppt_manage/newVersion/pptEnCatalog.vue
  28. 47 25
      src/views/report_manage/mixins/messagePush.js
  29. 6 3
      src/views/smartReport/components/ETAPriceChart.vue
  30. 6 3
      src/views/smartReport/components/ETASandBox.vue
  31. 33 6
      src/views/smartReport/components/ETASheet.vue
  32. 208 0
      src/views/smartReport/components/ImgSource.vue
  33. 6 3
      src/views/smartReport/components/ImportETAChart.vue
  34. 1 1
      src/views/smartReport/components/ImportMyETAChart.vue
  35. 6 3
      src/views/smartReport/components/SemanticAnalysis.vue
  36. 6 3
      src/views/smartReport/components/StatisticAnalysis.vue
  37. 10 0
      src/views/smartReport/components/TextEdit.vue
  38. 119 9
      src/views/smartReport/editReport.vue
  39. 1 1
      src/views/smartReport/reportList.vue
  40. 464 0
      src/views/system_manage/components/smartReportImgSet.vue
  41. 128 91
      src/views/system_manage/etaBaseConfig.vue
  42. 6 6
      src/views/transferPage.vue

+ 4 - 2
src/api/api.js

@@ -10,7 +10,8 @@ import {
   sciDataInterface,
   baiinfoInterface,
   nationalInterface,
-  databankInterface
+  databankInterface,
+  yongyiInterface
 } from './modules/thirdBaseApi';
 
 //手工指标 手工数据 手工数据权限
@@ -112,7 +113,8 @@ export {
   cloudDiskInterface,
   homeInterface,
   businessTripInterence,
-  reportVarietyENInterence
+  reportVarietyENInterence,
+  yongyiInterface
 };
 
 //老接口 研报 ppt等

+ 21 - 0
src/api/modules/sheetApi.js

@@ -287,6 +287,27 @@ export const getMixedCalculateData = params => {
 	return http.post('/datamanage/excel_info/mixed/calculate',params)
 }
 
+/**
+ * 表格一键刷新
+ * @param {Object} params
+ * @param {Array} params.ExcelCodes 表格唯一编码
+ * @param {String} params.Source 来源,枚举值:report、english_report、smart_report
+ * @param {Number} params.ReportId 报告id
+ * @param {Number} params.ReportChapterId 章节id 非章节传0
+ */
+export const refreshSheet = (params)=>{
+    return http.post('/datamanage/excel_info/table/batch_refresh',params)
+}
+/**
+ * 获取表格刷新结果
+ * @param {Object} params
+ * @param {String} params.Source 来源,枚举值:report、english_report、smart_report
+ * @param {Number} params.ReportId 报告id
+ * @param {Number} params.ReportChapterId 章节id 非章节传0
+ */
+export const getRefreshResult = (params)=>{
+    return http.post('/datamanage/excel_info/table/batch_refresh/result',params)
+}
 
 /* =====自定义分析==== */
 

+ 20 - 0
src/api/modules/smartReport.js

@@ -76,6 +76,26 @@ const apiSmartReport={
     //获取上期已发布报告
     getLastReport:params=>{
         return http.get('/smart_report/last_published_report',params)
+    },
+
+    // 资源库列表
+    imgReourceList:params=>{
+        return http.get('/smart_report/resource/list',params)
+    },
+
+    //新增资源库图片
+    imgReourceAdd:params=>{
+        return http.post('/smart_report/resource/add',params)
+    },
+
+    //资源库图片重命名
+    imgReourceRename:params=>{
+        return http.post('/smart_report/resource/rename',params)
+    },
+
+    //资源库图片删除
+    imgReourceDel:params=>{
+        return http.post('/smart_report/resource/remove',params)
     }
 
 }

+ 28 - 1
src/api/modules/thirdBaseApi.js

@@ -720,6 +720,32 @@ const databankInterface = {
     },
 }
 
+/* 涌益咨询 */
+const yongyiInterface={
+	/**
+	 * 分类列表
+	 * @param {} params 
+	 * @returns 
+	 */
+	classifyList: params => {
+		return http.get('/datamanage/yongyi/classify',params);
+	},
+	/**
+	 * 获取指标列表详情
+	 */
+	dataList: params => {
+		return http.get('/datamanage/yongyi/index/data',params);
+	},
+	//单个指标数据
+	getTargetDataList:params=>{
+		return http.get('/datamanage/yongyi/single_data',params);
+	},
+	// 搜索
+	getTargetListByName:params=>{
+		return http.get('/datamanage/yongyi/search_list',params);
+	},
+}
+
 export { 
 	lzDataInterface,
 	glDataInterface,
@@ -730,5 +756,6 @@ export {
   sciDataInterface,
   baiinfoInterface,
   nationalInterface,
-  databankInterface
+  databankInterface,
+  yongyiInterface
 }

BIN
src/assets/img/icons/fullsreen.png


BIN
src/assets/img/icons/more.png


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


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


+ 130 - 42
src/components/lzTable.vue

@@ -65,19 +65,107 @@ export default {
 			defalut:'lz'
 		}
 	},
+	computed: {
+		headerArr(){
+			let arr=['QuotaName','LzCode','Frequency','UnitName','ModifyTime']
+
+			if(this.source==='gl'){
+				arr=['IndexName','IndexCode','FrequencyName','UnitName','UpdateTime']
+			}
+			if(this.source==='smm'){
+				arr=['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+			}
+			if(this.source==='coal'){
+				arr=['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+			}
+			if(this.source==='baiinfo'){
+				arr=['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+			}
+			if(this.source==='yyzx'){
+				arr=['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+			}
+
+			return arr
+		},
+		labelArr(){
+			let temMap=new Map([
+				['QuotaName', '指标名称'],
+				['LzCode', '指标ID'],
+				['Frequency', '频度'],
+				['UnitName', '单位'],
+				['ModifyTime', '更新时间'],
+			])
+
+			if(this.source==='gl'){
+				temMap=new Map([
+					['IndexName', '指标名称'],
+					['IndexCode', '指标ID'],
+					['FrequencyName', '频度'],
+					['UnitName', '单位'],
+					['UpdateTime', '更新时间'],
+				])
+			}
+			if(this.source==='smm'){
+				temMap=new Map([
+					['IndexName', '指标名称'],
+					['IndexCode', '指标ID'],
+					['Frequency', '频度'],
+					['Unit', '单位'],
+					['ModifyTime', '更新时间'],
+				])
+			}
+			if(this.source==='coal'){
+				temMap=new Map([
+					['IndexName', '指标名称'],
+					['IndexCode', '指标ID'],
+					['Frequency', '频度'],
+					['Unit', '单位'],
+					['ModifyTime', '更新时间'],
+				])
+			}
+			if(this.source==='baiinfo'){
+				temMap=new Map([
+					['IndexName', '指标名称'],
+					['IndexCode', '指标ID'],
+					['Frequency', '频度'],
+					['Unit', '单位'],
+					['ModifyTime', '更新时间'],
+				])
+			}
+			if(this.source==='yyzx'){
+				temMap=new Map([
+					['IndexName', '指标名称'],
+					['IndexCode', '指标ID'],
+					['Frequency', '频度'],
+					['Unit', '单位'],
+					['ModifyTime', '更新时间'],
+				])
+			}
+
+			return temMap
+		},
+		dynamic_key(){
+			let key='InputValue'
+			if(['smm','baiinfo','coal','yyzx'].includes(this.source)){
+				key='Value'
+			}
+
+			return key
+		}
+	},
 	data() {
 		return {
-			dynamic_key: (this.source === 'smm'||this.source ==='baiinfo')? 'Value' 
-			:this.source==='coal'?'Value': 'InputValue',
-			headerArr: this.source === 'gl' 
-			? ['IndexName','IndexCode','FrequencyName','UnitName','UpdateTime']
-			: this.source === 'smm' 
-			? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
-			: this.source==='coal'
-			? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
-      : this.source==='baiinfo'
-      ? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
-			:['QuotaName','LzCode','Frequency','UnitName','ModifyTime'],
+			// dynamic_key: (this.source === 'smm'||this.source ==='baiinfo')? 'Value' 
+			// :this.source==='coal'?'Value': 'InputValue',
+	// 		headerArr: this.source === 'gl' 
+	// 		? ['IndexName','IndexCode','FrequencyName','UnitName','UpdateTime']
+	// 		: this.source === 'smm' 
+	// 		? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+	// 		: this.source==='coal'
+	// 		? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+    //   : this.source==='baiinfo'
+    //   ? ['IndexName','IndexCode','Frequency','Unit','ModifyTime']
+	// 		:['QuotaName','LzCode','Frequency','UnitName','ModifyTime'],
 			frequencyType:new Map([
 				[1,'日度'],
 				[2,'周度'],
@@ -86,37 +174,37 @@ export default {
 				[5,'年度'],
 				[99,'无固定频率'],
 			]),
-			labelArr: this.source === 'gl' ? new Map([
-				['IndexName', '指标名称'],
-				['IndexCode', '指标ID'],
-				['FrequencyName', '频度'],
-				['UnitName', '单位'],
-				['UpdateTime', '更新时间'],
-			]): this.source === 'smm' ? new Map([
-				['IndexName', '指标名称'],
-				['IndexCode', '指标ID'],
-				['Frequency', '频度'],
-				['Unit', '单位'],
-				['ModifyTime', '更新时间'],
-			]) :this.source === 'coal' ? new Map([
-				['IndexName', '指标名称'],
-				['IndexCode', '指标ID'],
-				['Frequency', '频度'],
-				['Unit', '单位'],
-				['ModifyTime', '更新时间'],
-			]) :this.source==='baiinfo'?new Map([
-        ['IndexName', '指标名称'],
-				['IndexCode', '指标ID'],
-				['Frequency', '频度'],
-				['Unit', '单位'],
-				['ModifyTime', '更新时间'],
-      ]):new Map([
-				['QuotaName', '指标名称'],
-				['LzCode', '指标ID'],
-				['Frequency', '频度'],
-				['UnitName', '单位'],
-				['ModifyTime', '更新时间'],
-			]),
+			// labelArr: this.source === 'gl' ? new Map([
+			// 	['IndexName', '指标名称'],
+			// 	['IndexCode', '指标ID'],
+			// 	['FrequencyName', '频度'],
+			// 	['UnitName', '单位'],
+			// 	['UpdateTime', '更新时间'],
+			// ]): this.source === 'smm' ? new Map([
+			// 	['IndexName', '指标名称'],
+			// 	['IndexCode', '指标ID'],
+			// 	['Frequency', '频度'],
+			// 	['Unit', '单位'],
+			// 	['ModifyTime', '更新时间'],
+			// ]) :this.source === 'coal' ? new Map([
+			// 	['IndexName', '指标名称'],
+			// 	['IndexCode', '指标ID'],
+			// 	['Frequency', '频度'],
+			// 	['Unit', '单位'],
+			// 	['ModifyTime', '更新时间'],
+			// ]) :this.source==='baiinfo'?new Map([
+        	// 	['IndexName', '指标名称'],
+			// 	['IndexCode', '指标ID'],
+			// 	['Frequency', '频度'],
+			// 	['Unit', '单位'],
+			// 	['ModifyTime', '更新时间'],
+      		// ]):new Map([
+			// 	['QuotaName', '指标名称'],
+			// 	['LzCode', '指标ID'],
+			// 	['Frequency', '频度'],
+			// 	['UnitName', '单位'],
+			// 	['ModifyTime', '更新时间'],
+			// ]),
 		};
 	},
 	methods: {

+ 9 - 0
src/routes/modules/dataRoutes.js

@@ -201,6 +201,15 @@ export default [
           keepAlive: false,
         },
       },
+      {
+        path: "yyzx",
+        component: () => import("@/views/dataEntry_manage/thirdBase/YyzxData.vue"),
+        name: "涌益咨询",
+        hidden: false,
+        meta: {
+          keepAlive: false,
+        },
+      },
     ],
   },
 ];

+ 3 - 2
src/utils/buttonConfig.js

@@ -42,7 +42,7 @@ export const reportManageBtn={
     reportManage_reportView:'smartReportManage:reportView',//研报预览:即是否能点击研报名称跳转预览页面
     reportManage_reportView_wechartShare:'smartReportManage:reportView:wechartShare',//研报预览页面-微信分享
     reportManage_reportView_copyWechat:'smartReportManage:reportView:copyWechat',//研报预览页面-复制链接
-    reportManage_reportView_exportImg:'smartReportManage:reportView:exportImg',//研报预览页面-导出图片
+    reportManage_exportImg:'smartReportManage:exportImg',//导出图片
     reportManage_audioDownload:'smartReportManage:audioDownload',//音频下载
     reportManage_audioUpload:'smartReportManage:audioUpload',//音频上传
     reportManage_reportDel:'smartReportManage:reportDel',//删除研报
@@ -233,12 +233,13 @@ export const dataSourcePermission = {
     eiaData_export:'eiaData:export',
     /*--------国家统计局---- */
     gjtjjData_export:'gjtjjData:export',
-
     /*--------数据报表管理---- */
     /*--------数据源终端管理---- */
     dataSource_account_add:'dataSourceAccount:add',//新增终端账号
     dataSource_account_edit:'dataSourceAccount:edit',//编辑
     dataSource_account_enable:'dataSourceAccount:enable',//禁用/启用
+    /*--------涌益咨询---- */
+    yyzxData_export:'yyzx:exportData'
 }
 
 /*

+ 12 - 12
src/views/Login.vue

@@ -247,15 +247,15 @@ export default {
                                 case "researcher":
                                     path = "/reportlist";
                                     break;
-                                case "compliance": //合规
-                                    path = "/contractapprovallist";
-                                    break;
+                                // case "compliance": //合规
+                                //     path = "/contractapprovallist";
+                                //     break;
                                 case "special_researcher": //特邀研究员
                                     path = "/dataList";
                                     break;
-                                case "special_ficc_seller":
-                                    path = "/meetingCalendar";
-                                    break;
+                                // case "special_ficc_seller":
+                                //     path = "/meetingCalendar";
+                                //     break;
                                 default:
                                     path = await this.getOtherRolePath("myCalendar");
                             }
@@ -474,15 +474,15 @@ export default {
                 case "researcher":
                     path = "/reportlist";
                     break;
-                case "compliance": //合规
-                    path = "/contractapprovallist";
-                    break;
+                // case "compliance": //合规
+                //     path = "/contractapprovallist";
+                //     break;
                 case "special_researcher": //特邀研究员
                     path = "/dataList";
                     break;
-                case "special_ficc_seller":
-                    path = "/meetingCalendar";
-                    break;
+                // case "special_ficc_seller":
+                //     path = "/meetingCalendar";
+                //     break;
                 default:
                     path = await this.getOtherRolePath("myCalendar");
             }

+ 19 - 0
src/views/chartFrame_manage/common/config.js

@@ -10,6 +10,25 @@ const portStyle = {
         }
     }
     }
+//利用NodeTool实现角标
+export const textTool = {
+    name:'button',
+    args:{
+        x:'100%',
+        y:'100%',
+        offset:{x:-12,y:-5},
+        markup:[{
+            tagName:'text',
+            textContent:'aaa',
+            attrs:{
+                fill: '#0052D9',
+                fontSize: 12,
+                textAnchor: 'middle',
+                pointerEvents: 'none',
+            }
+        }]
+    }
+}
 //基础节点
 export const baseNode = {
     shape:'rect',

+ 1 - 5
src/views/chartFrame_manage/common/graph.js

@@ -9,13 +9,9 @@ const viewConfig = {
         restrict:true,//节点移动时无法超出画布
     },
     interacting:function (cellView){ //禁止节点移动
-        /* if(cellView.cell.getData().disableMove){
-            return false
-        } */
-        return false
+        return {'nodeMovable':false,'edgeMovable':false}
     },
     highlighting:{},
-    /* connecting:{}, */
     history:false,//关闭画布撤销/重做能力。
     keyboard:false,
     clipboard: false,

+ 31 - 6
src/views/chartFrame_manage/components/frameContainer.vue

@@ -32,7 +32,7 @@
 <script>
 import { ElDropdownMenu } from 'element-ui';
 import { myGraph } from '../common/graph';
-import { baseNode } from '../common/config';
+import { baseNode , textTool } from '../common/config';
 import FrameToolBar from './frameToolBar.vue';
 export default {
     components:{ElDropdownMenu,FrameToolBar},
@@ -40,6 +40,10 @@ export default {
         FrameworkContent:{ //框架内容
             type:String,
             default:''
+        },
+        Nodes:{
+            type:Array,
+            default:[]
         }
     },
     data() {
@@ -70,9 +74,6 @@ export default {
                 this.currentCell = null
             }
         },
-        FrameworkContent(newVal){//当框架内容发生改变时,画布内容也发生改变
-            newVal.length&&this.gragh&&this.graph.fromJSON(JSON.parse(newVal))
-        }
     },
     computed:{
         contextMenu(){//右键菜单,根据权限配置
@@ -95,6 +96,8 @@ export default {
             this.FrameworkContent.length&&this.graph.fromJSON(JSON.parse(this.FrameworkContent))
             //如果有内容,将画布内容居中
             this.FrameworkContent.length&&this.graph.scrollToContent({ animation: { duration: 600 }})
+            //如果有内容,遍历每个节点,赋值chartNum
+            this.FrameworkContent.length&&this.setNodeInfo()
             //如果是非编辑页,加载完成画布内容后冻结画布
             window.location.pathname.startsWith('/chartframe')&&this.graph.freeze()
             //如果是编辑页,加载完成后清除历史数据
@@ -104,6 +107,17 @@ export default {
         dispose(){
             this.graph&&this.graph.dispose()
         },
+        setNodeInfo(){
+            const nodes = this.graph.getNodes()
+            this.Nodes.forEach(node=>{
+                const currentNode = nodes.find(item=>item.id===node.NodeId)
+                if(currentNode){
+                    currentNode.removeTools()
+                    const toolOption = this.getToolOption({chartNum:node.ChartNum||0,color:currentNode.attrs.label.fill})
+                    currentNode.addTools(toolOption)
+                }
+            })
+        },
         //添加/编辑节点
         editNode(node){
             //获取视口范围
@@ -114,6 +128,9 @@ export default {
                 currentNode.data.id=node.nodeLink.MyChartClassifyId
                 currentNode.label=node.nodeName
                 currentNode.data.nodeLink = node.nodeLink
+                currentNode.removeTools()
+                const toolOption = this.getToolOption({chartNum:node.nodeLink.ChartNum,color:currentNode.attrs.label.fill})
+                currentNode.addTools(toolOption)
             }else{
                 //在视口范围内添加节点
                 this.graph.addNode({
@@ -125,12 +142,19 @@ export default {
                     height:50,
                     data:{
                         id:node.nodeLink.MyChartClassifyId,//存储节点对应的myETA分类id
-                        nodeLink:node.nodeLink
+                        nodeLink:node.nodeLink,
                     },
-                    label:node.nodeName||''
+                    label:node.nodeName||'',
+                    tools:[this.getToolOption({chartNum:node.nodeLink.ChartNum,color:baseNode.attrs.label.fill})]
                 }})
             }
         },
+        getToolOption({chartNum,color}){
+            const options = _.cloneDeep(textTool)
+            options.args.markup[0].textContent = chartNum +''
+            options.args.markup[0].attrs.fill = color
+            return options
+        },
         //点击右键菜单事件
         handleContext(key){
             const select_cell = this.graph.getSelectedCells()
@@ -191,6 +215,7 @@ export default {
         getContentNodes(){
             return this.graph.getNodes().map(node=>{
                 return {
+                    NodeId:node.id,
                     NodeName:node.label,
                     MyChartClassifyId:Number(node.data.id)
                 }

+ 9 - 1
src/views/chartFrame_manage/components/frameToolBar.vue

@@ -115,7 +115,7 @@
                             :class="{'img-disabled':!isSelectNode&&!isSelectEdge,'actived':isSelectNode||isSelectEdge}">
                     </label>
                     <input type="color" id="storke" style="width: 0;height: 0;visibility: hidden;" 
-                        :value="cellStyle.stroke"
+                        :value="nodeStyle.stroke"
                         @input="valueChange"/>
                     <span class="disabled" v-if="!isSelectNode&&!isSelectEdge"></span>
                 </span>
@@ -311,7 +311,15 @@ export default {
                 if(styleMap[id]){
                     attr = this.isSelectNode?styleMap[id][0]:styleMap[id][1]
                 } 
+                
                 this.currentCell.attr(attr,value)
+                //改变节点字体颜色时,角标的颜色也一起改变
+                if(attr==='label/fill'){
+                    let tool = this.currentCell.getTools().items[0]
+                    tool.args.markup[0].attrs.fill = value
+                    this.currentCell.removeTools()
+                    this.currentCell.addTools(tool)
+                }
             }
         },
         changeCellStyle({attr,value}){

+ 9 - 1
src/views/chartFrame_manage/css/basePage.scss

@@ -57,12 +57,20 @@
                 overflow-y: auto;
             } */
             .public-catalog{
+                .title{
+                    cursor: pointer;
+                    span{
+                        margin-left: 5px;
+                    }
+                }
                 .catalog-tree{
-                    margin: 20px 0;
+                   /*  margin: 20px 0; */
+                   margin-top:20px;
                     min-height: 100px;
                 }
             }
             .my-list{
+                margin-top: 20px;
                 .classify-item{
                     display: flex;
                     align-items: center;

+ 1 - 1
src/views/chartFrame_manage/css/customTree.scss

@@ -1,4 +1,4 @@
-.chart-frame-wrap{
+.chart-frame-wrap,.tree-wrap{
     .catalog-tree{
         .custom-tree-node {
             display: flex !important;

+ 14 - 2
src/views/chartFrame_manage/frameEditor.vue

@@ -3,7 +3,8 @@
     <div class="frame-editor-wrap">
         <div class="option-wrap">
             <el-input style="width:240px;" placeholder="请输入框架名称" v-model.trim="frameDetail.FrameworkName"></el-input>
-            <el-button type="primary" style="margin-left:auto;" @click="handleEditNode({})"
+            <el-button type="primary" plain style="margin-left:auto;" @click="returnListPage">返回</el-button>
+            <el-button type="primary" style="margin-left:20px;" @click="handleEditNode({})"
                 v-if="permissionBtn.isShowBtn('chartFramePermission','chartframe_my_editNode')">添加节点</el-button>
             <el-button type="primary" style="margin-left:20px;" @click="saveFrame"
                 v-if="permissionBtn.isShowBtn('chartFramePermission','chartframe_my_saveFrame')">保存</el-button>
@@ -12,6 +13,7 @@
             <!-- 沙盘图组件 -->
             <FrameContainer ref="container"
                 :FrameworkContent="frameDetail.FrameworkContent"
+                :Nodes="frameDetail.Nodes"
                 @editNode="handleEditNode"
                 @framePic="getFramePic"
             />
@@ -70,6 +72,7 @@ export default {
             frameDetail:{
                 FrameworkName:'',
                 FrameworkContent:'',
+                Nodes:[]
             },
             lockLoding:null,
             modifyNode: {},//正在编辑的节点
@@ -151,6 +154,11 @@ export default {
                     this.$router.replace({path:'/editframe',query:{frameId:this.frameId}})
                 })
             }
+            //重新加载一次画布
+            this.$refs.container.dispose()
+            this.$nextTick(()=>{
+                this.$refs.container.init()
+            })
         },
         getMyList(){
             mychartInterface.classifyList().then((res)=>{
@@ -163,7 +171,7 @@ export default {
             if(this.frameId){
                 const res = await chartFrameInterface.getFrameDetail({ChartFrameworkId:Number(this.frameId)})
                 if(res.Ret!==200) return 
-                this.frameDetail = res.Data||{FrameworkName:'',FrameworkContent:''}
+                this.frameDetail = res.Data||{FrameworkName:'',FrameworkContent:'',Nodes:[]}
             }
             //获取到框架内容后再加载graph
             this.$nextTick(()=>{
@@ -171,6 +179,10 @@ export default {
             })
             
         },
+        //返回至列表页,并选中当前页的框架(如果是编辑)
+        returnListPage(){
+            this.$router.push({path:'/chartframe',query:{frameId:this.frameId||''}})
+        }
     },
     mounted(){
         this.getMyList()

+ 16 - 8
src/views/chartFrame_manage/index.vue

@@ -34,8 +34,8 @@
             </div>
             <div class="catalog-list">
                 <div class="public-catalog">
-                    <p>公共框架</p>
-                    <div class="catalog-tree">
+                    <p @click="expandPublic = !expandPublic" class="title">公共框架<span><i :class="{'el-icon-arrow-down':!expandPublic,'el-icon-arrow-up':expandPublic}"></i></span></p>
+                    <div class="catalog-tree" v-show="expandPublic">
                         <el-tree
                             ref="catalogTree"
                             class="catalog-tree other-tree"
@@ -167,7 +167,8 @@
                     <div class="frame-wrap">
                         <!--沙盘图组件-->
                         <FrameContainer ref="container"
-                            :FrameworkContent="currentFrame.FrameworkContent"
+                            :FrameworkContent="currentFrameDetail.FrameworkContent"
+                            :Nodes="currentFrameDetail.Nodes"
                             @showDialog="handleShowDialog"/>
                     </div>
                 </div>
@@ -243,7 +244,7 @@
 
 <script>
 import draggable from 'vuedraggable';
-import FrameContainer from './components/frameContainer.vue';
+import FrameContainer from './components/frameContainer';
 import chartDetail from '@/views/mychart_manage/components/chartDetailDia.vue';
 import { mychartInterface,chartFrameInterface } from '@/api/api.js';
 import {copyBlob} from '@/utils/svgToblob.js';
@@ -273,6 +274,7 @@ export default {
     data() {
         return {
             isSlideLeft:false,//控制左侧目录栏是否显示
+            expandPublic:false,//控制公共框架展开收起
 
             /* drag 我的框架相关 */
             dragStartIndex:0,
@@ -291,6 +293,7 @@ export default {
             currentList:[],//选择公共框架时,框架列表
             myFrameList:[],//我的框架列表
             currentFrame:{},//选择的框架
+            currentFrameDetail:{},//选中的框架详情
             /* frame node */
             myETADetailDialogShow:false,//点击节点时,弹出myeta图表详情弹框
             modifyFrame:{},//正在修改的框架
@@ -391,16 +394,21 @@ export default {
                 this.currentFrame={}
             }
         },
-        handleInitGraph(){
+        async handleInitGraph(){
+            //获取框架详情
+            if(this.currentFrame.ChartFrameworkId){
+                const res = await chartFrameInterface.getFrameDetail({ChartFrameworkId:Number(this.currentFrame.ChartFrameworkId)})
+                this.currentFrameDetail = res.Data||{}
+            }
             //判断一下框架内容是否是合法的JSON,否则置为空
             try{
-                JSON.parse(this.currentFrame.FrameworkContent)
+                JSON.parse(this.currentFrameDetail.FrameworkContent)
             }catch(e){
-                this.currentFrame.FrameworkContent = ''
+                this.currentFrameDetail.FrameworkContent = ''
             }
             this.$nextTick(()=>{
                 //若框架有内容,才加载画布
-                this.currentFrame.FrameworkContent&&this.$refs.container.init()
+                this.currentFrameDetail.FrameworkContent&&this.$refs.container.init()
             })
         },
         /* 拖动相关 */

+ 564 - 0
src/views/dataEntry_manage/thirdBase/YyzxData.vue

@@ -0,0 +1,564 @@
+<template>
+  <div class="smmTarget-container target-container" id="box">
+    <span
+        v-show="!isLeftWrapShow"
+        class="slide-btn-icon slide-right"
+        @click="isLeftWrapShow = !isLeftWrapShow"
+    >
+        <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+    </span>
+    <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
+        <span
+            v-show="isLeftWrapShow"
+            class="slide-btn-icon slide-left"
+            @click="isLeftWrapShow = !isLeftWrapShow"
+        >
+            <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
+        </span>
+      <div class="left-top">
+        <el-button
+          v-permission="permissionBtn.dataSourcePermission.yyzxData_export"
+          style="width: 100%"
+          type="primary"
+          plain
+          size="medium"
+          @click="exportClick"
+          :loading="btnload"
+          :disabled="!select_classify&&!leftSearchTradeCode"
+          >导出Excel</el-button
+        >
+        <el-autocomplete
+          style="margin: 20px 0; width: 100%"
+          prefix-icon="el-icon-search"
+          v-model="leftSearchVal"
+          :fetch-suggestions="handleLeftSearch"
+          :trigger-on-focus="false"
+          placeholder="指标名称/指标ID"
+          @select="handleSelectLeftSearchval"
+          popper-class="el-autocomplete-suggestion-data-entry"
+          clearable
+        >
+          <template slot-scope="scope">
+            <div v-if="scope.item.nodata" style="text-align: center">
+              暂无数据
+            </div>
+            <div v-else>
+              {{ scope.item.IndexName }}
+            </div>
+          </template>
+        </el-autocomplete>
+      </div>
+      <div class="scroll-wrap">
+        <el-tree
+          ref="treeRef"
+          class="target_tree"
+          :data="classifyList"
+          node-key="ClassifyId"
+          :props="{
+            label: 'ClassifyName',
+            children: 'Children',
+          }"
+          :current-node-key="select_classify"
+          :expand-on-click-node="false"
+          check-strictly
+          highlight-current
+          empty-text="暂无分类"
+          @current-change="nodeChangeHandle"
+        >
+        </el-tree>
+      </div>
+      <span
+        class="move-btn resize"
+        v-drag
+        id="resize"
+        @mousemove="dynamicNode && resetNodeStyle(dynamicNode)"
+      >
+      </span>
+    </div>
+    <div
+      class="right-cont minHeight"
+      id="right"
+      v-loading="dataloading"
+      element-loading-text="获取数据中..."
+    >
+      <template v-if="rightShow">
+        <div class="right-box" @scroll="scrollHandle">
+          <div class="data-header">
+            <lz-table
+              :tableOption="tableOption"
+              tableType="header"
+              ref="table"
+              source="yyzx"
+              @editTarget="editTargetByTable"
+            />
+          </div>
+          <div class="data-cont" v-if="dateArr.length">
+            <lz-table
+              :tableOption="tableOption"
+              tableType="data"
+              :dateArr="dateArr"
+              source="yyzx"
+            />
+          </div>
+          <div v-else class="nodata"></div>
+        </div>
+      </template>
+      <div v-else class="nodata-cont">
+        <tableNoData text="暂无数据"/>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import lzTable from "@/components/lzTable.vue";
+import { yongyiInterface } from "@/api/api.js";
+export default {
+  name: "Yyzx",
+  components: { lzTable },
+  directives: {
+    drag(el, bindings) {
+      el.onmousedown = function (e) {
+        var init = e.clientX;
+        // console.log(init);
+        var box = $('#box')[0];
+        // console.log(box.clientWidth)
+        let total_wid = box.offsetWidth;
+        var left = $('#left')[0];
+        var right = $('#right')[0];
+        var initWidth = left.offsetWidth;
+        document.onmousemove = function (e) {
+          var end = e.clientX;
+          var newWidth = end - init + initWidth;
+          left.style.width = newWidth + 'px';
+          right.style.width = newWidth > 320 ? total_wid - newWidth + 'px' : total_wid - 320 + 'px';
+        };
+        document.onmouseup = function () {
+          document.onmousemove = document.onmouseup = null;
+          e.releaseCapture && e.releaseCapture();
+        };
+        e.setCapture && e.setCapture();
+        return false;
+      };
+    }
+  }, 
+  data() {
+    return {
+      isLeftWrapShow:true,
+      exportBase:process.env.VUE_APP_API_ROOT + "/datamanage/yongyi/export", //ssm数据导出接口
+      dataloading: false,
+      rightShow: false,
+      select_classify: 0,
+      classifyList: [],
+      tableOption: [],
+      dateArr: [], //最长的日期数组
+      btnload: false,
+      page_no: 1,
+      page_size: 20,
+      havemore: true, //是否还有数据
+
+      leftSearchVal: "", //左侧搜索值
+      leftSearchTradeCode: "", //如果是搜索选择的 则有此code
+      isShowSingleData: false, //右侧是否展示的是单个指标数据
+    };
+  },
+  methods: {
+    /* 获取分类 */
+    getClassify() {
+      yongyiInterface.classifyList().then((res) => {
+        if (res.Ret !== 200) return;
+        this.classifyList = res.Data.List || [];
+      });
+    },
+    /* 获取数据 */
+    getDataList: _.throttle(function () {
+      this.isShowSingleData = false;
+      this.dataloading = true;
+      yongyiInterface
+        .dataList({
+          ClassifyId: this.select_classify,
+          PageSize: this.page_size,
+          CurrentIndex: this.page_no,
+        })
+        .then((res) => {
+          this.rightShow = true;
+          if (res.Ret !== 200) return;
+
+          // 找出最多的页码 判断是否还有数据
+          let page_arrs = res.Data.map((item) => item.Paging.Pages);
+          let totalPage = Math.max.apply(Math, page_arrs);
+          this.havemore = this.page_no < totalPage ? true : false;
+
+          // 合并数据
+          if (this.page_no === 1) {
+            this.tableOption = res.Data;
+          } else {
+            this.tableOption.forEach((item) => {
+              res.Data.forEach((_item) => {
+                if (item.IndexCode === _item.IndexCode) {
+                  item.DataList = item.DataList.concat(_item.DataList);
+                }
+              });
+            });
+          }
+
+          // 合并所有指标中的日期 作为日期数组
+          let arr = res.Data.map((item) => {
+            return item.DataList;
+          });
+
+          let obj = [];
+          for (let i of arr) {
+            for (let j of i) {
+              obj.push(j.DataTime);
+            }
+          }
+          let arr2 = [...new Set(obj)].sort().reverse();
+          let concatArr = [...new Set([...this.dateArr, ...arr2])]
+            .sort()
+            .reverse();
+          this.dateArr = this.page_no === 1 ? arr2 : concatArr;
+
+          /* 不满6个追加6个空的显示一排 别问 问就是为了美观  */
+          if (this.tableOption.length < 7)
+            for (let i = 0; i < 7; i++) {
+              this.tableOption.push({
+                DataList: [],
+              });
+              if (this.tableOption.length >= 7) break;
+            }
+
+          //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
+          if (this.dateArr.length < 12)
+            for (let i = 0; i < 12; i++) {
+              this.dateArr.push("");
+              if (this.dateArr.length >= 12) break;
+            }
+
+          this.dataloading = false;
+          this.page_no === 1 &&
+            this.$nextTick(() => {
+              this.rightShow && this.initWidth();
+            });
+        });
+    }, 200),
+    // 获取单个指标数据
+    async getTargetDataList(code) {
+      this.isShowSingleData = true;
+      this.dataloading = true;
+      try {
+        const res = await yongyiInterface.getTargetDataList({
+          IndexCode: code,
+        });
+        this.rightShow = true;
+        if (res.Ret !== 200) return;
+        const DataList = res.Data.Data || [];
+        // 设置为没有更多数据
+        this.haveMore = false;
+        // 合并数据
+        this.tableOption = [
+          {
+            DataList: DataList,
+            ...res.Data,
+          },
+        ];
+        // 这里是单个指标所以不用合并日期
+        const arr = DataList.map((item) => item.DataTime);
+        this.dateArr = [...new Set(arr)].sort().reverse();
+        /* 不满6个追加6个空的显示一排 别问 问就是为了美观  */
+        for (let i = 0; i < 7; i++) {
+          this.tableOption.push({
+            DataList: [],
+          });
+          if (this.tableOption.length >= 7) break;
+        }
+        //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
+        if (this.dateArr.length < 12)
+          for (let i = 0; i < 12; i++) {
+            this.dateArr.push("");
+            if (this.dateArr.length >= 12) break;
+          }
+        this.select_quota = res.Data.IndexName;
+        this.select_Unit = res.Data.Unit;
+        this.select_frequency = res.Data.Frequency;
+        this.select_ModifyTime = res.Data.ModifyTime || "";
+        this.dataloading = false;
+        this.rightShow && this.initWidth();
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    initWidth() {
+      this.$nextTick(() => {
+        $(".right-box")[0].style.width =
+          this.$refs.table.$el.clientWidth + 5 + "px";
+        $(".right-box")[0].scrollTop = 0;
+        $(".right-box")[0].scrollLeft = 0;
+      });
+    },
+    /* 无频度的异常显示处理 7*12*/
+    nodataDeal() {
+      this.tableOption = [];
+      this.dateArr = [];
+      for (let i = 0; i < 7; i++) {
+        this.tableOption.push({
+          DataList: [],
+        });
+        if (this.tableOption.length >= 7) break;
+      }
+      for (let i = 0; i < 12; i++) {
+        this.dateArr.push("");
+        if (this.dateArr.length >= 12) break;
+      }
+    },
+    /* 滚动加载 */
+    scrollHandle(e) {
+      if (this.isShowSingleData) return;
+      const dom = e.target;
+      let total = dom.scrollTop + dom.clientHeight;
+      if (total >= dom.scrollHeight && this.havemore) {
+        this.page_no++;
+        console.log("load下一页");
+        this.getDataList();
+      }
+    },
+    /* 数据导出 */
+    exportClick() {
+      this.btnload = true;
+      const link = document.createElement("a");
+      link.href = this.exportDataUrl;
+      link.download = "";
+      link.click();
+      setTimeout(() => {
+        this.btnload = false;
+      }, 5000);
+    },
+    //左侧搜索
+    async handleLeftSearch(query, cb) {
+      cb([]);
+      if (!query) return;
+      const res = await yongyiInterface.getTargetListByName({
+        Keyword: query,
+      });
+      if (res.Ret === 200) {
+        let arr = res.Data || [];
+        if (!arr.length) {
+          cb([{ nodata: true }]);
+        } else {
+          cb(arr);
+        }
+      }
+    },
+    // 选中左侧搜索值
+    handleSelectLeftSearchval(e) {
+      if (!e.IndexCode) return;
+      this.leftSearchTradeCode = e.IndexCode;
+      this.leftSearchVal = e.IndexName;
+
+      // 获取单独指标数据
+      this.getTargetDataList(e.IndexCode);
+    },
+
+    getTargetData(code, arr) {
+      for (const item of arr) {
+        if (item.BaseFromBaiinfoIndexCode === code) return item;
+        if (item.Children && item.Children.length) {
+          const _item = this.getTargetData(code, item.Children);
+          if (_item) return _item;
+        }
+      }
+    },
+    // 对[#,;]转义
+    escapeStr(str) {
+      return str.replace(/#/g, escape("#")).replace(/;/g, escape(";")); 
+    },
+  
+    //改变选中节点
+    nodeChangeHandle(data, node) {
+      if (data.ClassifyId === this.select_classify) return;
+      this.select_classify = data.ClassifyId;
+      this.leftSearchVal=''
+      this.page_no = 1;
+      this.page_size = 20;
+      this.getDataList()
+    },
+   
+  },
+  computed: {
+    exportDataUrl() {
+      // 数据导出接口
+      let urlStr = this.exportBase;
+      // token
+      urlStr += `?${localStorage.getItem("auth") || ""}`;
+      if (this.isShowSingleData) {
+        // 指标id
+        urlStr += `&IndexCode=${
+          this.isShowSingleData ? this.leftSearchTradeCode : ""
+        }`;
+      } else {
+        // 目录id
+        urlStr += `&ClassifyId=${
+          this.isShowSingleData ? "" : this.select_classify
+        }`;
+      }
+      return this.escapeStr(urlStr);
+    },
+  },
+  created() {},
+  mounted() {
+    this.getClassify();
+  },
+};
+</script>
+<style lang="scss">
+@import "../css/customtree.scss";
+@import "../css/baseTargetPage.scss";
+.smmTarget-dialog-cont {
+  .el-cascader {
+    .el-input {
+      width: 100% !important;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.smmTarget-container {
+  display: flex;
+  * {
+    box-sizing: border-box;
+  }
+  .minHeight {
+    height: calc(100vh - 120px);
+    background-color: #fff;
+    box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
+    border-radius: 4px;
+  }
+  div::-webkit-scrollbar {
+    width: 5px !important;
+  }
+  .left-cont {
+    min-width: 300px;
+    width: 300px;
+    margin-right: 20px;
+    padding: 30px 0;
+    overflow: hidden;
+    position: relative;
+    .left-top {
+      padding: 0 20px;
+    }
+    .scroll-wrap {
+      padding: 0 10px;
+      height: calc(100vh - 280px);
+      overflow-y: auto;
+      .target_tree {
+        color: #333;
+        .label-input .el-input__inner {
+          height: 25px;
+          line-height: 25px;
+        }
+        .custom-tree-node {
+          display: flex !important;
+          justify-content: space-between;
+          align-items: center;
+          display: block;
+          flex: 1;
+          .node_label {
+            margin-right: 2px;
+          }
+          .el-icon-view {
+            color: #409eff;
+            font-size: 18px;
+            margin-left: 5px;
+          }
+        }
+      }
+      .add-cont {
+        margin: 50px 0 20px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: #409eff;
+        font-size: 16px;
+        cursor: pointer;
+      }
+    }
+    .move-btn {
+      height: 100%;
+      width: 4px;
+      position: absolute;
+      right: 0px;
+      top: 0;
+      &:hover {
+        cursor: col-resize;
+      }
+    }
+    .classify-list {
+      padding: 0 20px;
+      /* margin-top: 20px; */
+      height: calc(100vh - 280px);
+      overflow-y: auto;
+      .classify-item {
+        font-size: 14px;
+        color: #666;
+        margin-bottom: 20px;
+        &:hover {
+          cursor: pointer;
+          color: #409eff;
+        }
+        &.act {
+          color: #409eff;
+        }
+      }
+    }
+  }
+  .right-cont {
+    width: 82%;
+    padding: 30px;
+    .right-box {
+      max-width: 100%;
+      max-height: calc(100vh - 230px);
+      border-left: 1px solid #dcdfe6;
+      border-right: 1px solid #dcdfe6;
+      overflow: auto;
+      .data-header {
+        width: 100%;
+        position: sticky;
+        top: 0;
+        z-index: 2;
+      }
+      .data-cont {
+        height: calc(100vh - 444px);
+      }
+      .nodata {
+        height: calc(100vh - 460px);
+        border: 1px solid #dcdfe6;
+        font-size: 16px;
+        color: #999;
+      }
+    }
+    .frequency-list {
+      margin-top: 20px;
+      display: flex;
+      flex-wrap: wrap;
+      .frequency-btn {
+        width: 112px;
+        margin: 0 30px 10px 0;
+      }
+    }
+    .nodata-cont {
+      width: 150px !important;
+      text-align: center;
+      color: #666;
+      font-size: 16px;
+      margin: 0 auto;
+    }
+  }
+}
+.dialog-cont {
+  padding-left: 50px;
+}
+.dia-bot {
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 7 - 1
src/views/login_manage/EmailModel.vue

@@ -73,6 +73,7 @@ export default {
             timer:0,
             codeStr:'获取验证码',
             codeCountDown:60,
+            isGetNewCode:false,
             form:{
                 email:'',
                 picCode:'',
@@ -98,10 +99,13 @@ export default {
     methods: {
         checkForm(){
             //首先检查是否是重新获取验证码
-            if(this.codeStr==='重新获取'){
+            if(this.codeStr==='重新获取'&&!this.isGetNewCode){
                 //引导用户重新输入图形验证码
+                this.$message.warning('重新获取需再次输入图形验证码')
                 this.getCodePic()
                 this.form.picCode = ''
+                this.isGetNewCode = true
+                return
             }
             //检查邮箱和图形验证码是否正确
             const {email,picCode} = this.form
@@ -123,7 +127,9 @@ export default {
             }).then(res=>{
                 if(res.Ret!==200) return 
                 this.$message.success('验证码已发送')
+                this.isGetNewCode = false
                 //60秒倒计时
+                this.codeCountDown = 60
                 this.countDown()
                 this.timer = setInterval(()=>{
                     this.countDown()

+ 8 - 5
src/views/login_manage/MobileModel.vue

@@ -83,6 +83,7 @@ export default {
             timer:0,
             codeStr:'获取验证码',
             codeCountDown:60,
+            isGetNewCode:false,
             form:{
                 mobile:'',
                 picCode:'',
@@ -109,10 +110,13 @@ export default {
     methods: {
         checkForm(){
             //首先检查是否是重新获取验证码
-            if(this.codeStr==='重新获取'){
+            if(this.codeStr==='重新获取'&&!this.isGetNewCode){
                 //引导用户重新输入图形验证码
+                this.$message.warning('重新获取需再次输入图形验证码')
                 this.getCodePic()
                 this.form.picCode = ''
+                this.isGetNewCode = true
+                return
             }
             //检查手机号和图形验证码是否正确
             const {picCode,mobile} = this.form
@@ -124,10 +128,7 @@ export default {
                 this.$message.warning('请输入正确的手机号')
                 return
             }
-            /* this.countDown()
-                this.timer = setInterval(()=>{
-                    this.countDown()
-                },1000) */
+
             //通过请求发送验证码
             departInterence.getCodeVerify({
                 VerifyType:1,
@@ -139,7 +140,9 @@ export default {
             }).then(res=>{
                 if(res.Ret!==200) return 
                 this.$message.success('验证码已发送')
+                this.isGetNewCode = false
                 //60秒倒计时
+                this.codeCountDown = 60
                 this.countDown()
                 this.timer = setInterval(()=>{
                     this.countDown()

+ 1 - 1
src/views/login_manage/modelMixins.js

@@ -21,7 +21,7 @@ export default {
         },
         countDown(){
             /* if(!this.timer) return */
-            console.log('click down')
+            //console.log('click down')
             this.codeCountDown--
             this.codeStr=`重新获取(${this.codeCountDown})秒`
             if(this.codeCountDown<=0){

+ 84 - 8
src/views/mychart_manage/index.vue

@@ -48,8 +48,8 @@
       </div>
       <div class="left-bottom">
         <div class="public-classify" v-if="publicClassifyList.length">
-          <h3 class="classify-type">公共图库</h3>
-          <ul class="public-ul">
+          <h3 @click="expandPublic = !expandPublic" class="classify-type">公共图库<span><i :class="{'el-icon-arrow-down':!expandPublic,'el-icon-arrow-up':expandPublic}"></i></span></h3>
+          <!-- <ul class="public-ul">
             <li
               :class="[
                 'classify-item',
@@ -74,7 +74,32 @@
                 </el-dropdown>
               </div>
             </li>
-          </ul>
+          </ul> -->
+          <div class="tree-wrap" v-show="expandPublic">
+                <el-tree
+                    ref="catalogTree"
+                    class="catalog-tree other-tree"
+                    empty-text="暂无图库"
+                    :data="publicClassifyList"
+                    node-key="nodeKeyId"
+                    :expand-on-click-node="false"
+                    @current-change="(data,node)=>{nodeChange(data,node)}"
+                    >
+                    <div class="custom-tree-node" slot-scope="{ data,node }">
+                        <span class="tree-label">{{ data.name }}</span>
+                        <div class="right-item right-item-box" >
+                            <el-dropdown @command="handleCommand" trigger="click" v-if="isShowDropPublic&&data.MyChartClassifyId">
+                            <span class="el-dropdown-link"> 
+                                <i class="el-icon-more" style="font-size: 16px;transform: rotate(90deg);cursor: pointer"/>
+                            </span>
+                            <el-dropdown-menu slot="dropdown">
+                                <el-dropdown-item :command="{key:'copy'}" :disabled="select_classify_userid === roleId">复制</el-dropdown-item>
+                            </el-dropdown-menu>
+                            </el-dropdown>
+                        </div>
+                    </div>
+                </el-tree>
+            </div>
         </div>
         <div class="classify" v-if="classifyList.length">
           <h3 class="classify-type">我的图库</h3>
@@ -166,7 +191,7 @@
         
         <div class="cont-top">
           <span>共{{ total }}张图表</span>
-          <span v-if="ispublic === 1">分享人: {{ publicClassifyList.find(item => item.MyChartClassifyId === select_classify).RealName}}</span>
+          <span v-if="ispublic === 1">分享人: {{ RealName }}</span>
         </div>
         <div
           class="chart-public-list"
@@ -229,7 +254,7 @@
         </div>
       </div>
       <div v-else class="nodata">
-        <span v-if="ispublic === 1" class="sharer">分享人: {{ publicClassifyList.find(item => item.MyChartClassifyId === select_classify).RealName}}</span>
+        <span v-if="ispublic === 1" class="sharer">分享人: {{ RealName }}</span>
         <tableNoData text="暂无图表"/>
       </div>
     </div>
@@ -324,6 +349,8 @@ export default {
   },
   data() {
     return {
+      expandPublic:false,
+      RealName:'',
       haveData: true,
       isSlideLeft: false, //收起分类
       search_txt: '',
@@ -473,10 +500,36 @@ export default {
     getPublicClassify() {
       mychartInterface.publicClassify().then((res) => {
         if(res.Ret !== 200) return;
-        this.publicClassifyList = res.Data ? res.Data.List.map(item => ({
+        /* this.publicClassifyList = res.Data ? res.Data.List.map(item => ({
           ...item,
           fromPublic: 1
-        })) : [];
+        })) : []; */
+        this.publicClassifyList = res.Data?res.Data.List||[]:[]
+        /* this.publicClassifyList = [{
+            MenuAdminId:204,
+            MenuName:"ficc销售name",
+            Items:[{
+                MyChartClassifyId:370,
+                MyChartClassifyName:"图库2.0",
+                RealName:'ficc销售'
+            }]
+        }] */
+        this.publicClassifyList = this.publicClassifyList.map(list=>{
+            list.name = list.MenuName
+            list.nodeKeyId = 'list' + list.MenuAdminId
+            if(list.Items){
+                list.children = list.Items.map(item=>{
+                    return {
+                        ...item,
+                        ...{
+                            nodeKeyId:'item'+ item.MyChartClassifyId,
+                            name:item.MyChartClassifyName
+                        }
+                    }
+                })
+            }
+            return list
+        })
       })
     },
 
@@ -550,9 +603,28 @@ export default {
 			if(!this.search_have_more) return;
 			this.searchApi(this.current_search,++this.search_page);
 		},
-
+    nodeChange(data,node){
+        if(node.level===1){
+            this.select_classify = 0
+            this.haveData = false
+            this.total = 0
+            this.page_no = 1
+            this.chartList = []
+            this.ispublic=''
+            return
+        }
+        this.RealName = data.RealName
+        this.chooseClassify({
+            MyChartClassifyId:data.MyChartClassifyId,
+            fromPublic:1,
+            AdminId:data.AdminId
+        })
+    },
     /* 切换分类 */
     chooseClassify({MyChartClassifyId,fromPublic,AdminId}) {
+      if(fromPublic!==1){
+        this.$refs.catalogTree.setCurrentKey(null)
+      }
       this.select_classify = MyChartClassifyId;
       this.ispublic = fromPublic;
       this.select_classify_userid = AdminId;
@@ -936,6 +1008,7 @@ export default {
 };
 </script>
 <style lang="scss">
+@import "../chartFrame_manage/css/customTree.scss";
 .mychart_container {
   position: relative;
   .right-item-box {
@@ -1059,6 +1132,9 @@ export default {
         margin-bottom: 20px;
         /* .public-ul {
         } */
+        .tree-wrap{
+            padding:15px;
+        }
       }
     }
     .noclassify {

+ 4 - 1
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -596,7 +596,10 @@ export default {
       //若有人在编辑,则显示编辑中
       if(this.pptToolList.find(i=>i.key==='edit')){
         const {Editor={}} = pptDetail
-        const labelName = Editor.IsEditing?`${Editor.Editor}编辑中...`:'编辑'
+        let labelName = '编辑'
+        if(Editor.IsEditing&&Editor.AdminId!==Number(localStorage.getItem('AdminId'))){
+            labelName = `${Editor.Editor}编辑中...`
+        }
         this.pptToolList.map(i=>{
             if(i.key==='edit'){
                 i.label = labelName

+ 4 - 1
src/views/ppt_manage/newVersion/pptEnCatalog.vue

@@ -564,7 +564,10 @@ export default {
       //若有人在编辑,则显示编辑中
       if(this.pptToolList.find(i=>i.key==='edit')){
         const {Editor={}} = pptDetail
-        const labelName = Editor.IsEditing?`${Editor.Editor}编辑中...`:'编辑'
+        let labelName = '编辑'
+        if(Editor.IsEditing&&Editor.AdminId!==Number(localStorage.getItem('AdminId'))){
+            labelName = `${Editor.Editor}编辑中...`
+        }
         this.pptToolList.map(i=>{
             if(i.key==='edit'){
                 i.label = labelName

+ 47 - 25
src/views/report_manage/mixins/messagePush.js

@@ -1,4 +1,5 @@
 import { reportadd, reportedit, messagePushPost,dataBaseInterface,reportMessageSend } from "@/api/api.js";
+import * as sheetInterface from '@/api/modules/sheetApi.js';
 import { getUrlParams } from '@/utils/common'
 export default {
   data() {
@@ -84,50 +85,71 @@ export default {
       });
     },
 
-    //刷报告中的所有图表  
+    //刷报告中的所有图表和表格
     refreshReport: _.debounce ( async function() {
       let code_arr = [];
+      let sheet_code_arr = []
       $('iframe').each((k,i) => {
         try {
           let href = $(i).attr('src');
-          code_arr.push(getUrlParams(href,'code'));
-    
+          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) return this.$message.warning('请插入图表');
+      if(!code_arr.length&&!sheet_code_arr.length) return this.$message.warning('请插入图表或表格')
 
-      if(this.$route.query.id) {
+      const fromPage = this.$route.path === "/reportEnEditor" ? "english_report" : "report";
+      if(this.$route.query.id&&code_arr.length) {
         let res = await dataBaseInterface.getReportrefreshStatus({
-          Source: 'report',
+          Source: fromPage,
           ReportId: Number(this.$route.query.id),
           ReportChapterId: 0
         });
         
         if(!res.Data.RefreshResult) return this.$message.warning('图表正在刷新中,请勿重复操作')
+        const { Ret,Msg } = await dataBaseInterface.reportRefresh({
+            ChartInfoCode: code_arr
+          })
+          
+          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);
+          }
       }
 
-      // const loading = this.$loading({
-      //   lock: true,
-      //   text: '刷新中..',
-      //   spinner: 'el-icon-loading',
-      //   background: 'rgba(0, 0, 0, 0.02)'
-      // });
-
-      const { Ret,Msg } = await dataBaseInterface.reportRefresh({
-        ChartInfoCode: code_arr
-      })
-  
-      // loading.close();
-      
-      if(Ret === 200) {
-        $('iframe').each((k,i) => {
-          $(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,
+            ReportId: Number(this.$route.query.id),
+            ReportChapterId: 0
+          });
+        if(!res.Data.RefreshResult) return this.$message.warning('表格正在刷新中,请勿重复操作')
+        const { Ret,Msg } = await sheetInterface.refreshSheet({
+            ExcelCodes: sheet_code_arr
+          })
+          
+          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),
   },
 };

+ 6 - 3
src/views/smartReport/components/ETAPriceChart.vue

@@ -21,7 +21,7 @@
                 v-model="isShowMe" 
                 @change="handleIsShowMeChange"
             >只看我的</el-checkbox>
-            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
                 <draggable
                     :list="list"
                     :group="{ name: 'component', pull: 'clone', put: false }"
@@ -52,7 +52,8 @@ export default {
             list:[],
             page:1,
             pageSize:20,
-            finished:false
+            finished:false,
+            loading:false
         }
     },
     created(){
@@ -96,7 +97,9 @@ export default {
                 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 =
@@ -107,7 +110,7 @@ export default {
         },
 
         handleLoadMore(){
-            if(this.finished) return
+            if(this.finished||this.loading) return
             this.page++
             this.getChartList()
         }

+ 6 - 3
src/views/smartReport/components/ETASandBox.vue

@@ -16,7 +16,7 @@
             </div>
         </div>
         <div class="main-box">
-            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
                 <draggable
                     :list="list"
                     :group="{ name: 'component', pull: 'clone', put: false }"
@@ -46,7 +46,8 @@ export default {
             list:[],
             page:1,
             pageSize:20,
-            finished:false
+            finished:false,
+            loading:false
         }
     },
     created(){
@@ -88,7 +89,9 @@ export default {
                 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 =
@@ -99,7 +102,7 @@ export default {
         },
 
         handleLoadMore(){
-            if(this.finished) return
+            if(this.finished||this.loading) return
             this.page++
             this.getSandBoxList()
         }

+ 33 - 6
src/views/smartReport/components/ETASheet.vue

@@ -12,6 +12,7 @@
 			/>
         </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 }"
@@ -26,6 +27,7 @@
                 </div>
             </draggable>
             <tableNoData text="暂无数据" size="mini" v-if="list.length===0"/>
+            </div>
         </div>
     </div>
 </template>
@@ -36,7 +38,11 @@ export default {
     data() {
         return {
             keyword:'',
-            list:[]
+            list:[],
+            page:1,
+            pageSize:20,
+            finished:false,
+            loading:false
         }
     },
     created(){
@@ -60,19 +66,34 @@ export default {
         },
 
         handleSearch(){
+            this.list=[]
+            this.page=1
+            this.finished=false
             this.getSheetList()
         },
         getSheetList() {
-            this.list=[]
+            this.loading=true
             sheetInterface.sheetList({
                 Keyword: this.keyword,
-                CurrentIndex: 1,
-                PageSize: 10000,
+                CurrentIndex: this.page,
+                PageSize: this.pageSize,
             }).then((res) => {
+                this.loading=false
                 if (res.Ret !== 200) return;
-                this.list = res.Data.List || [];
+                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>
@@ -96,7 +117,13 @@ div{
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;
         padding: 20px;
-        overflow-y: auto;
+        display: flex;
+        flex-direction: column;
+        .list-wrap{
+            flex: 1;
+            overflow-y: auto;
+
+        }
         .sheet-list-box{
             display: flex;
             flex-wrap: wrap;

+ 208 - 0
src/views/smartReport/components/ImgSource.vue

@@ -0,0 +1,208 @@
+<template>
+    <div class="statistic-analysis-wrap">
+        <div class="top-box">
+            <div class="left-card">
+                <span>选择图片</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+					placeholder="请输入图片名称"
+					v-model="keyword"
+					size="medium"
+                    @input="handleSearch"
+                    style="width:240px"
+				/>
+                <el-select placeholder="请选择图片类型" v-model="type" style="width:240px" @change="handleSearch">
+                    <el-option label="版头" :value="1"></el-option>
+                    <el-option label="版尾" :value="2"></el-option>
+                </el-select>
+            </div>
+        </div>
+        <div class="main-box">
+            <!-- <div class="type-select-box">
+                <span style="margin-right:20px">版面设置</span>
+                <el-radio-group v-model="setType">
+                    <el-radio :label="1">版头</el-radio>
+                    <el-radio :label="2">版尾</el-radio>
+                </el-radio-group>
+            </div> -->
+            <div style="flex:1;overflow-y: auto;padding:20px 0">
+            <tableNoData text="暂无数据" 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">取消</el-button>
+                <el-button type="primary" @click="handleSave">保存</el-button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import {apiSmartReport}  from '@/api/modules/smartReport'
+export default {
+    data() {
+        return {
+            keyword:'',
+            type: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.getImgList()
+        },
+
+        handleSelectItem(e){
+            this.selectItem=e
+        },
+
+        handleClose(){
+            this.$emit('close')
+        },
+
+        handleSave(){
+            // if(!this.setType){
+            //     this.$message.warning('请选择设置的版面类型')
+            //     return
+            // }
+            if(!this.selectItem){
+                this.$message.warning('请选择版图')
+                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: 200px;
+            }
+        }
+    }
+}
+</style>

+ 6 - 3
src/views/smartReport/components/ImportETAChart.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="import-eta-chart-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+    <div class="import-eta-chart-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
             <el-checkbox
                 class="onlyshowme-box"
                 v-model="isShowMe" 
@@ -32,7 +32,8 @@ export default {
             pageSize:20,
             list:[],
             finished:false,
-            keyword:''
+            keyword:'',
+            loading:false
         }
     },
     created() {
@@ -55,12 +56,14 @@ export default {
         },
 
         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]
@@ -76,7 +79,7 @@ export default {
         },
 
         handleLoadMore(){
-            if(this.finished) return
+            if(this.finished||this.loading) return
             this.page++
             this.getETAChartList()
         },

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

@@ -38,7 +38,7 @@ export default {
         return {
             myChartClassifyList:[],
             selectMyChartClassify:'',
-            pageSize:10000,
+            pageSize:20,
 			CurrentIndex: 1,
 			list:[],
             loading:false,

+ 6 - 3
src/views/smartReport/components/SemanticAnalysis.vue

@@ -16,7 +16,7 @@
             </div>
         </div>
         <div class="main-box">
-            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
                 <draggable
                     :list="list"
                     :group="{ name: 'component', pull: 'clone', put: false }"
@@ -46,7 +46,8 @@ export default {
             list:[],
             page:1,
             pageSize:20,
-            finished:false
+            finished:false,
+            loading:false
         }
     },
     created(){
@@ -88,7 +89,9 @@ export default {
                 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 =
@@ -99,7 +102,7 @@ export default {
         },
 
         handleLoadMore(){
-            if(this.finished) return
+            if(this.finished||this.loading) return
             this.page++
             this.getSemanticList()
         }

+ 6 - 3
src/views/smartReport/components/StatisticAnalysis.vue

@@ -26,7 +26,7 @@
                 v-model="isShowMe" 
                 @change="handleIsShowMeChange"
             >只看我的</el-checkbox>
-            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
+            <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
                 <draggable
                     :list="list"
                     :group="{ name: 'component', pull: 'clone', put: false }"
@@ -81,7 +81,8 @@ export default {
             list:[],
             page:1,
             pageSize:20,
-            finished:false
+            finished:false,
+            loading:false
         }
     },
     created(){
@@ -135,6 +136,7 @@ export default {
                 PageSize: this.pageSize,
                 IsShowMe: this.isShowMe,
             };
+            this.loading=true
             let res = null;
             if (this.activeType === '相关性') {
                 res = await chartRelevanceApi.searchChart(params);
@@ -145,6 +147,7 @@ export default {
             } else if (this.activeType === '跨品种分析') {
                 res = await crossVarietyInterface.searchChart(params);
             }
+            this.loading=false
 
             if (res.Ret !== 200) return;
             const arr = res.Data.List || [];
@@ -156,7 +159,7 @@ export default {
         },
 
         handleLoadMore(){
-            if(this.finished) return
+            if(this.finished||this.loading) return
             this.page++
             this.getChartList()
         }

+ 10 - 0
src/views/smartReport/components/TextEdit.vue

@@ -69,6 +69,16 @@ export default {
                 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 () {

+ 119 - 9
src/views/smartReport/editReport.vue

@@ -55,23 +55,35 @@
                     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;">
+                        <el-color-picker v-model="bgColor" @change="handleBgColorChange"></el-color-picker>
+                    </li>
                 </draggable>
 
-                <div class="report-content-box">
+                <div class="report-content-box" id="report-content-box">
+                    <div class="html-head-img-box">
+                        <div class="opt-btn-box" style="display: none;">
+                            <div class="del-btn" @click.stop="headImg=''"></div>
+                        </div>
+                        <img :src="headImg" alt="" style="display:block;width:100%">
+                    </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"
+                        :style="{backgroundColor:bgColor}"
                     >
                         <div 
                             :class="[
@@ -132,6 +144,12 @@
                             </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>
                 </div>
             </div>
 
@@ -168,6 +186,8 @@
                 <ETASandBox v-if="rightType==='etaSandBox'"/>
                 <!-- 语义分析 -->
                 <SemanticAnalysis v-if="rightType==='semanticAnalysis'"/>
+                <!-- 版图资源库 -->
+                <ImgSource v-if="rightType==='imgSource'" @change="handleInsertImgSource" @close="handleCloseRight"/>
                 </div>
                 </div>
             </div>
@@ -226,6 +246,7 @@ import ETAPriceChart from './components/ETAPriceChart.vue'
 import ETASandBox from './components/ETASandBox.vue'
 import SemanticAnalysis from './components/SemanticAnalysis.vue'
 import { getUrlParams } from '@/utils/common'
+import ImgSource from './components/ImgSource.vue'
 export default {
     name:"smartReportEdit",
     components: {
@@ -242,7 +263,8 @@ export default {
         StatisticAnalysis,
         ETAPriceChart,
         ETASandBox,
-        SemanticAnalysis
+        SemanticAnalysis,
+        ImgSource
     },
     watch:{
         'taskTime'(){
@@ -283,6 +305,11 @@ export default {
             showReportBaseInfo:false,
 
             topTypeList:[
+                {
+                    name:'版图资源库',
+                    type:'imgSource',
+                    icon:require('@/assets/img/smartReport/icon04.png')
+                },
                 {
                     name:'图库',
                     type:'etaChart',
@@ -358,6 +385,10 @@ export default {
             contentChange:false,//内容是否发生变化
 
             isDragResize:false,//是否正在拖动缩放
+
+            bgColor:'',//背景色
+            headImg:'',//版头图片
+            endImg:'',//版尾图片
         }
     },
     methods: {
@@ -459,7 +490,7 @@ export default {
 
         // 跳转预览
         handlePreviewReport(){
-            const htmlStr=$('.report-html-wrap').html()
+            const htmlStr=document.getElementById('report-content-box').outerHTML;
             sessionStorage.setItem('smartReportContent', htmlStr);
 			let { href } = this.$router.resolve({ 
                 path: '/smartReportDetail',
@@ -762,11 +793,15 @@ export default {
 
         // 编辑保存报告
         handleReportEdit(e){
+            const html=document.getElementById('report-content-box').outerHTML;
             const params={
                 SmartReportId:Number(this.$route.query.id)||0,
                 ...e,
-                Content:$('.report-html-wrap').html(),
-                ContentStruct:JSON.stringify(this.conList)
+                Content:html,
+                ContentStruct:JSON.stringify(this.conList),
+                HeadImg:this.headImg,
+                EndImg:this.endImg,
+                CanvasColor:this.bgColor
             }
             console.log(params);
             apiSmartReport.reportEdit({...params}).then(res=>{
@@ -796,6 +831,9 @@ export default {
                 if(res.Ret===200){
                     this.reportInfo=res.Data
                     this.conList=res.Data.ContentStruct?JSON.parse(res.Data.ContentStruct):[]
+                    this.headImg=res.Data.HeadImg
+                    this.endImg=res.Data.EndImg
+                    this.bgColor=res.Data.CanvasColor
                     this.$nextTick(()=>{
                         this.contentChange=false
                     })
@@ -850,14 +888,18 @@ export default {
         
         // 自动/存草稿保存内容
         handleSaveContent({isAutoSave}){
+            const html=document.getElementById('report-content-box').outerHTML;
             return new Promise((resolve,reject)=>{
                 const id=this.$route.query.id||0
                 if(!id) return
                 apiSmartReport.saveReportContent({
                     SmartReportId:Number(id),
-                    Content:$('.report-html-wrap').html(),
+                    Content:html,
                     ContentStruct:JSON.stringify(this.conList),
                     NoChange:this.contentChange?2:1,
+                    HeadImg:this.headImg,
+                    EndImg:this.endImg,
+                    CanvasColor:this.bgColor
                 }).then(res=>{
                     if(res.Ret===200){
                         resolve(true)
@@ -1006,6 +1048,23 @@ export default {
         //报告消息推送
         reportSendMsg(){
             apiSmartReport.reportMsgSend({SmartReportId:Number(this.$route.query.id)}).then(res=>{})
+        },
+
+        // 插入版头版尾
+        handleInsertImgSource(e){
+            if(e.type=='1'){
+                this.$message.success('版头设置成功')
+                this.headImg=e.data.ImgUrl
+            }else{
+                this.$message.success('版尾设置成功')
+                this.endImg=e.data.ImgUrl
+            }
+            this.contentChange=true
+        },
+
+        handleBgColorChange(e){
+            this.bgColor=e||''
+            this.contentChange=true
         }
     },
     created() {
@@ -1049,6 +1108,33 @@ export default {
     // 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>
@@ -1138,13 +1224,14 @@ div{
         display: flex;
         align-items: center;
         background-color: #fff;
-        height: 50px;
+        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;
@@ -1155,7 +1242,7 @@ div{
             .icon{
                 width: 20px;
                 height: 20px;
-                margin-right: 4px;
+                // margin-right: 4px;
             }
         }
     }
@@ -1164,9 +1251,32 @@ div{
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;
         padding: 20px 20px 20px 44px;
-        height: calc(100vh - 180px);
+        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;
+                }
+            }
+        }
     }
 }
 

+ 1 - 1
src/views/smartReport/reportList.vue

@@ -309,7 +309,7 @@
                                 >取消发布</span>
                                 <span
                                     v-if="scope.row.DetailImgUrl"
-                                    v-permission="permissionBtn.smartReportManageBtn.reportManage_reportView_exportImg"
+                                    v-permission="permissionBtn.smartReportManageBtn.reportManage_exportImg"
                                     @click="handleDownReportImg(scope.row.DetailImgUrl,scope.row.Title)"
                                     style="cursor: pointer; color: #4099ef;display:inline-block"
                                 >图片下载</span>

+ 464 - 0
src/views/system_manage/components/smartReportImgSet.vue

@@ -0,0 +1,464 @@
+<template>
+    <div class="smart-report-img-set-page">
+        <div class="top-wrap">
+            <el-input v-model="keyword" placeholder="请输入图片名称" clearable style="width:200px;margin-right:20px" @input="handleSearch"></el-input>
+            <el-select placeholder="请选择图片类型" v-model="type" clearable style="width:200px" @change="handleSearch">
+                <el-option label="版头" :value="1"></el-option>
+                <el-option label="版尾" :value="2"></el-option>
+            </el-select>
+            <el-button type="primary" style="float:right" @click="handleShowUploadPop">上传图片</el-button>
+        </div>
+
+        <div class="select-status-box" v-if="selectIds.length>0">
+            <el-checkbox 
+                :indeterminate="isIndeterminate" 
+                v-model="checkAll" 
+                @change="handleCheckAllChange"
+            >全选</el-checkbox>
+            <span>已选择{{selectIds.length}}项</span>
+            <span @click="selectIds=[]" style="color:#1146DB;margin-left:20px;cursor: pointer;">取消选择</span>
+            <span @click="handleBatchDel" style="color:#1146DB;margin-left:20px;cursor: pointer;">删除</span>
+        </div>
+
+
+        <ul class="img-list-wrap">
+            <li class="img-item" v-for="item in list" :key="item.ResourceId">
+                <div :class="['select-box',selectIds.includes(item.ResourceId)?'select-box-active':'']" @click="handleSelectItem(item)"></div>
+                <div class="opt-box">
+                    <div class="item" @click="handleShowImgFull(item)">
+                        <img src="~@/assets/img/icons/fullsreen.png" alt="">
+                    </div>
+                    <el-dropdown @command="handleClickOpt">
+                    <div class="item">
+                        <img src="~@/assets/img/icons/more.png" alt="">
+                    </div>
+                    <el-dropdown-menu slot="dropdown">
+                        <el-dropdown-item :command="{type:'rename',data:item}">重命名</el-dropdown-item>
+                        <el-dropdown-item :command="{type:'del',data:item}">删除</el-dropdown-item>
+                    </el-dropdown-menu>
+                    </el-dropdown>
+                </div>
+                <img class="img" :src="item.ImgUrl" alt="">
+                <p class="name">{{item.ImgName}}</p>
+            </li>
+        </ul>
+        <tableNoData text="暂无数据" v-if="list.length===0"/>
+        <!-- <el-col :span="24" class="toolbar">
+            <el-pagination
+                layout="total,prev,pager,next"
+                background
+                @current-change="handleCurrentChange"
+                :page-size="pageSize"
+                :total="total"
+                style="float: right"
+            />
+        </el-col> -->
+
+        <!-- 上传图片弹窗 -->
+        <el-dialog
+            :visible.sync="uploadImgPop"
+            :title="formData.id?'重命名':'上传图片'"
+            :close-on-click-modal="false"
+            :append-to-body="true"
+            @close="cancelHandle"
+            custom-class="classify-dialog"
+            center
+            width="650px"
+            v-dialogDrag
+        >
+            
+            <el-form 
+                :model="formData" 
+                :rules="formRules" 
+                ref="ruleForm" 
+                label-width="100px" 
+                class="upload-img-form"
+            >
+                <el-form-item label="图片名称" prop="name">
+                    <el-input v-model="formData.name" placeholder="请输入图片名称"></el-input>
+                </el-form-item>
+                <el-form-item label="图片类型" prop="type">
+                    <el-radio-group v-model="formData.type" :disabled="formData.id">
+                        <el-radio :label="1">版头</el-radio>
+                        <el-radio :label="2">版尾</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item 
+                    label="上传图片" 
+                    prop="imgUrl"
+                >
+                    <el-upload 
+                        action="" 
+                        accept="image/*" 
+                        :http-request="handleUploadImg" 
+                        :show-file-list="false"
+                        :disabled="formData.id"
+                    >
+                        <div class="upload-box">
+                            <template v-if="!formData.imgUrl">
+                                <i class="el-icon-plus" style="font-size: 24px;"></i>
+                            </template>
+                            <template v-else>
+                                <img class="upload-img" :src="formData.imgUrl" alt="">
+                            </template>
+                        </div>
+                    </el-upload>
+                    <p>支持jpg、jpeg、png等格式,建议上传版头800*200,版尾800*80</p>
+                </el-form-item>
+                <div style="text-align: center;padding: 30px 0;">
+                    <el-button type="primary" plain style="width:120px;" @click="handleCloseImgUpload">取消</el-button>
+                    <el-button type="primary" style="margin-left:20px;width:120px;" @click="handleSave">确定</el-button>
+                </div>
+            </el-form>
+            
+        </el-dialog>
+
+        <el-image-viewer 
+            v-if="showViewer" 
+            :on-close="()=>{this.picShowList=[];this.showViewer = false}" 
+            :url-list="picShowList" 
+        />
+    </div>
+</template>
+
+<script>
+import {bannerupload} from '@/api/api.js';
+import {apiSmartReport}  from '@/api/modules/smartReport'
+import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
+export default {
+    components:{ElImageViewer},
+    data() {
+        return {
+            keyword:'',
+            type:'',
+            page:1,
+            pageSize:1000,
+            list:[],
+            total:0,
+
+            uploadImgPop:false,
+            formData:{
+                id:0,
+                name:'',
+                type:'',
+                imgUrl:''
+            },
+            formRules:{
+                name:[{ required: true, message: '请输入图片名称', trigger: 'blur' }],
+                type:[{ required: true, message: '请选择图片类型', trigger: 'change' }],
+                imgUrl:[{ required: true, message: '请上传图片', trigger: 'change' }]
+            },
+
+            showViewer:false,
+            picShowList:[],
+
+            delIds:[],//要删除的id集合
+            selectIds:[],
+
+            isIndeterminate:false,
+            checkAll:false
+        }
+    },
+    created() {
+        this.getImgList()
+    },
+    methods: {
+        handleSelectItem(e){
+            const index=this.selectIds.indexOf(e.ResourceId)
+            if(index>-1){
+                this.selectIds.splice(index,1)
+            }else{
+                this.selectIds.push(e.ResourceId)
+            }
+
+            this.checkAll=this.selectIds.length===this.list.length?true:false
+            this.isIndeterminate=this.selectIds.length>0&&this.selectIds.length<this.list.length
+        },
+        handleCheckAllChange(val){
+            if(val){
+                this.selectIds=this.list.map(item=>item.ResourceId)
+            }else{
+                this.selectIds=[]
+            }
+        },
+
+        //分页页码跳转
+        handleCurrentChange(current) {
+            this.page = current;
+            this.getImgList();
+        },
+
+
+        //资源库列表
+        async getImgList(){
+            // 获取列表数据重置选择数据
+            this.selectIds=[]
+            this.isIndeterminate=false
+            this.checkAll=false
+            this.delIds=[]
+            
+            const res=await apiSmartReport.imgReourceList({
+                CurrentIndex:this.page,
+                PageSize:this.pageSize,
+                Type:this.type,
+                Keyword:this.keyword
+            })
+            if(res.Ret===200){
+                this.list=res.Data.List||[]
+                this.total=res.Data.Paging.Totals
+            }
+        },
+
+        handleSearch(){
+            this.page=1
+            this.getImgList()
+        },
+
+        handleUploadImg(file){
+            //图片大小和格式限制
+            const {size,type} = file.file
+            let form = new FormData();
+            form.append('file',file.file);
+            bannerupload(form).then(res=>{
+                // console.log(res);
+                if(res.Ret!==200) return 
+                this.formData.imgUrl=res.Data.ResourceUrl
+            })
+        
+        },
+
+        handleSave(){
+            this.$refs.ruleForm.validate((valid)=>{
+                if(valid){
+                    const params={
+                        Type:this.formData.type,
+                        ImgUrl:this.formData.imgUrl,
+                        ImgName:this.formData.name
+                    }
+                    if(this.formData.id){
+                        // 编辑
+                        apiSmartReport.imgReourceRename({
+                            ResourceId:this.formData.id,
+                            ImgName:this.formData.name
+                        }).then(res=>{
+                            if(res.Ret===200){
+                                this.$message.success('修改成功')
+                                this.page=1
+                                this.getImgList()
+                                this.handleCloseImgUpload()
+                            }
+                        })
+                        return
+                    }
+                    apiSmartReport.imgReourceAdd(params).then(res=>{
+                        if(res.Ret===200){
+                            this.$message.success('新增成功')
+                            this.page=1
+                            this.getImgList()
+                            this.handleCloseImgUpload()
+                        }
+                    })
+                }
+            })
+        },
+
+        handleCloseImgUpload(){
+            this.uploadImgPop=false
+            this.formData.id=0
+            this.$refs.ruleForm.resetFields()
+        },
+
+        handleShowImgFull(e){
+            console.log(e);
+            this.picShowList=[e.ImgUrl]
+            this.showViewer=true
+        },
+
+        handleClickOpt(e){
+            if(e.type==='del'){
+                this.delIds=[e.data.ResourceId]
+                this.handleImgDel()
+            }
+            if(e.type==='rename'){
+                this.formData.id=e.data.ResourceId
+                this.formData.name=e.data.ImgName
+                this.formData.type=e.data.Type
+                this.formData.imgUrl=e.data.ImgUrl
+                this.uploadImgPop=true
+            }
+        },
+
+        handleShowUploadPop(){
+            this.formData.id=0
+            this.formData.name=''
+            this.formData.type=''
+            this.formData.imgUrl=''
+            this.uploadImgPop=true
+        },
+
+        handleBatchDel(){
+            this.delIds=this.selectIds
+            this.handleImgDel()
+        },
+
+        handleImgDel(){
+            this.$confirm('是否确认删除选中图片?','提示',{
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(()=>{
+                apiSmartReport.imgReourceDel({ResourceIds:this.delIds.join(',')}).then(res=>{
+                    if(res.Ret===200){
+                        this.$message.success('删除成功')
+                        this.page=1
+                        this.getImgList()
+                    }
+                })
+            })
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.smart-report-img-set-page{
+    padding: 30px;
+    padding-bottom: 100px;
+    .select-status-box{
+        background-color: #F8F8F8;
+        padding: 10px 20px;
+        margin-top: 20px;
+    }
+}
+.img-list-wrap{
+    margin-top: 20px;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    .img-item{
+        position: relative;
+        width: 160px;
+        cursor: pointer;
+        .img{
+            display: block;
+            width: 100%;
+            height: 160px;
+            background-color: var(--gary-gy-3-disabled, #EBEFF6);
+            object-fit: contain !important;
+            box-sizing: border-box;
+            &:hover{
+                border: 1px solid #3375e1;
+            }
+        }
+        .name{
+            margin-top: 5px;
+            display: -webkit-box;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            -webkit-line-clamp: 2;
+            line-break: anywhere;
+            -webkit-box-orient: vertical;
+        }
+        .select-box{
+            position: absolute;
+            left: 1px;
+            top: 1px;
+            width: 12px;
+            height: 12px;
+            background-color: #EBEFF6;
+            display: none;
+        }
+        .select-box-active{
+            background-image: url('~@/assets/img/smartReport/icon17.png');
+            background-repeat: no-repeat;
+            background-size: cover;
+            display: block;
+        }
+        .opt-box{
+            display: none;
+            position: absolute;
+            top: 10px;
+            right: 10px;
+            z-index: 5;
+            .item{
+                width: 24px;
+                height: 24px;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                background-color: #fff;
+                border-radius: 50%;
+                margin-left: 10px;
+                img{
+                    width: 16px;
+                    height: 16px;
+                }
+            }
+        }
+        &:hover{
+            .opt-box{
+                display: flex;
+            }
+            .select-box{
+                display: block;
+            }
+        }
+    }
+}
+.upload-img-form{
+    .el-upload {
+        .upload-box {
+            position: relative;
+            width: 120px;
+            height: 120px;
+            background-color: #F5F7F9;
+            border: 1px dashed #DCDFE6;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            box-sizing: border-box;
+            padding: 4px;
+            overflow: hidden;
+
+            &:hover {
+                border: 1px dashed #3375e1;
+
+                .upload-mask {
+                    opacity: 1;
+                }
+            }
+
+            .form-hint {
+                margin-top: 10px;
+                color: #999999;
+            }
+
+            .upload-img,
+            .upload-mask {
+                width: 100%;
+                height: 100%;
+            }
+
+            .upload-mask {
+                position: absolute;
+                left: 0;
+                top: 0;
+                cursor: default;
+                text-align: center;
+                color: #fff;
+                opacity: 0;
+                font-size: 20px;
+                background-color: rgba(0, 0, 0, .5);
+                transition: opacity .3s;
+                z-index: 2;
+                line-height: 120px;
+
+                .mask-icon {
+                    cursor: pointer;
+                }
+            }
+        }
+    }
+}
+</style>

+ 128 - 91
src/views/system_manage/etaBaseConfig.vue

@@ -1,55 +1,30 @@
 <template>
     <div class="eta-base-config">
-        <el-form  :model="formData" :rules="rules" label-position="top" class="base-config-form"
-            label-width="120px" ref="baseConfigForm">
-            <div class="part-base part">
-                <div class="side">
-                    <el-form-item label="公司名称" prop="CompanyName">
-                        <el-input type="text" v-model="formData.CompanyName" placeholder="请输入公司名称" />
-                        <ConfigAnnotation picHintText="" picName="CompanyName" @showImage="previewImage"/>
-                    </el-form-item>
-                    <el-form-item label="公司水印" prop="CompanyWatermark" class="watermark">
-                        <ImgUpload 
-                            :imgUrl="formData.CompanyWatermark"
-                            @showImage="showImage"
-                            @upload="(file)=>handleUploadImage(file,'CompanyWatermark')"
-                            @remove="deleteFormImg('CompanyWatermark')"
-                            />
-                        <!-- 后面可能会有新的选项 -->
-                        <div style="position: absolute;top: -40px;left: 100px;display:flex;gap:0 20px">
-                            <el-checkbox-group v-if="isShowYBChart"
-                                v-model="checkList" >
-                                <el-checkbox label="研报图表"></el-checkbox>
-                            </el-checkbox-group>
-                            <div>
-                                <el-checkbox label="研报分享" v-model="formData.WatermarkReport"></el-checkbox>
-                                <el-tooltip 
-                                    effect="dark" 
-                                    content="研报详情分享页水印,水印内容为分享人用户名称+手机号(无手机号时为邮箱地址)" 
-                                    placement="top"
-                                >
-                                    <i class="el-icon-warning"></i>
-                                </el-tooltip>
-                            </div>
-                            
-                        </div>
-                        <ConfigAnnotation picName="CompanyWatermark" @showImage="previewImage"/>
-                    </el-form-item>
-                </div>
-                <div class="side">
-                    <el-form-item label="免责声明" prop="Disclaimer" class="disclaimer">
-                    <div class="rich-editor-wrap">
-                        <froala :id="`disclaimer-editor`"
-                            :ref="`disclaimerEditor`" 
-                            :tag="'textarea'" 
-                            :config="disclaimerConfig" v-model="formData.Disclaimer">
-                        </froala>
-                    </div>
-                    <ConfigAnnotation picHintText="" picName="Disclaimer" @showImage="previewImage"/>
-                </el-form-item>
+        <div class="nav-type-box">
+            <span :class="[sectionType===1?'active':'']" @click="sectionType=1">通用设置</span>
+            <span :class="[sectionType===2?'active':'']" @click="sectionType=2">资源库</span>
+        </div>
+        <!-- 通用设置 -->
+        <template v-if="sectionType==1">
+        <el-form  
+            :model="formData" 
+            :rules="rules" 
+            label-position="top" 
+            class="base-config-form"
+            label-width="120px" 
+            ref="baseConfigForm"
+        >
+            <div class="part-type-box" style="margin-bottom:40px">
+                <el-button type="primary" :plain="partType===1?false:true" @click="partType=1" :style="{width:'120px',border:'none',color:partType==1?'#fff':'#333'}">登录设置</el-button>
+                <el-button type="primary" :plain="partType===2?false:true" @click="partType=2" :style="{width:'120px',border:'none',color:partType==2?'#fff':'#333'}">研报设置</el-button>
+                <el-button type="primary" :plain="partType===3?false:true" v-if="isShowPPT||isShowEnPPT" @click="partType=3" :style="{width:'120px',border:'none',color:partType==3?'#fff':'#333'}">PPT配置</el-button>
+                <div class="btn-wrap" style="text-align: center;float:right">
+                    <el-button type="primary" plain style="width:120px;" @click="cancel">取消</el-button>
+                    <el-button type="primary"  style="margin-left:20px;width:120px;" @click="saveBaseConfig">保存</el-button>
                 </div>
             </div>
-            <div class="part-base-tow part" >
+            <!-- 登录设置模块 -->
+            <div class="part" v-show="partType===1">
                 <div class="side">
                     <!-- <el-form-item label="国内短信模板" prop="LoginSmsTpId" >
                         <div class="form-item-type-two sms-type">
@@ -101,12 +76,79 @@
                         <ConfigAnnotation picName="emailContentTemplate" @showImage="previewImage" picHintText=""/>
                     </el-form-item>
                 </div>
+            </div>
+            <!-- 研报设置 -->
+            <div class="part" v-show="partType===2">
+                <div class="side">
+                    <el-form-item label="公司名称" prop="CompanyName">
+                        <el-input type="text" v-model="formData.CompanyName" placeholder="请输入公司名称" />
+                        <ConfigAnnotation picHintText="" picName="CompanyName" @showImage="previewImage"/>
+                    </el-form-item>
+                    <el-form-item label="公司水印" prop="CompanyWatermark" class="watermark">
+                        <ImgUpload 
+                            :imgUrl="formData.CompanyWatermark"
+                            @showImage="showImage"
+                            @upload="(file)=>handleUploadImage(file,'CompanyWatermark')"
+                            @remove="deleteFormImg('CompanyWatermark')"
+                            />
+                        <!-- 后面可能会有新的选项 -->
+                        <div style="position: absolute;top: -40px;left: 100px;display:flex;gap:0 20px">
+                            <el-checkbox-group v-if="isShowYBChart"
+                                v-model="checkList" >
+                                <el-checkbox label="研报图表"></el-checkbox>
+                            </el-checkbox-group>
+                            <div>
+                                <el-checkbox label="研报分享" v-model="formData.WatermarkReport"></el-checkbox>
+                                <el-tooltip 
+                                    effect="dark" 
+                                    content="研报详情分享页水印,水印内容为分享人用户名称+手机号(无手机号时为邮箱地址)" 
+                                    placement="top"
+                                >
+                                    <i class="el-icon-warning"></i>
+                                </el-tooltip>
+                            </div>
+                            
+                        </div>
+                        <ConfigAnnotation picName="CompanyWatermark" @showImage="previewImage"/>
+                    </el-form-item>
+                    <el-form-item label="免责声明" prop="Disclaimer" class="disclaimer">
+                        <div class="rich-editor-wrap">
+                            <froala :id="`disclaimer-editor`"
+                                :ref="`disclaimerEditor`" 
+                                :tag="'textarea'" 
+                                :config="disclaimerConfig" v-model="formData.Disclaimer">
+                            </froala>
+                        </div>
+                        <ConfigAnnotation picHintText="" picName="Disclaimer" @showImage="previewImage"/>
+                    </el-form-item>
+                    <div v-if="isShowXunFei">
+                        <!-- 科大讯飞 -->
+                        <div style="width:100%;">
+                            <span style="color:#606266;">科大讯飞服务</span> 
+                            <el-switch v-model="Iflytek"></el-switch>
+                        </div>
+                        <template v-if="Iflytek">
+                            <el-form-item label="APPID" prop="XfAppid">
+                                <el-input type="text" v-model="formData.XfAppid" placeholder="请输入APPID" />
+                            </el-form-item>
+                            <el-form-item label="APIKey" prop="XfApiKey">
+                                <el-input type="text" v-model="formData.XfApiKey" placeholder="请输入APIKey" />
+                            </el-form-item>
+                            <el-form-item label="APISecret" prop="XfApiSecret">
+                                <el-input type="text" v-model="formData.XfApiSecret" placeholder="请输入APISecret" />
+                            </el-form-item>
+                            <el-form-item label="vcn(voice_name)" prop="XfVcn">
+                                <el-input type="text" v-model="formData.XfVcn" placeholder="请输入voice_name" />
+                            </el-form-item>
+                        </template>
+                    </div>
+                </div>
                 <div class="side">
-                    <el-form-item label="中文研报分享标题" prop="H5ShareName">
-                        <el-input type="text" v-model="formData.H5ShareName" placeholder="请输入中文研报分享标题" />
+                    <el-form-item label="中文研报分享抬头" prop="H5ShareName">
+                        <el-input type="text" v-model="formData.H5ShareName" placeholder="请输入中文研报分享抬头" />
                     </el-form-item>
-                    <el-form-item label="英文研报分享标题" prop="H5ShareEnName">
-                        <el-input type="text" v-model="formData.H5ShareEnName" placeholder="请输入英文研报分享标题" />
+                    <el-form-item label="英文研报分享抬头" prop="H5ShareEnName">
+                        <el-input type="text" v-model="formData.H5ShareEnName" placeholder="请输入英文研报分享抬头" />
                     </el-form-item>
                     <el-form-item label="关联公众号" prop="WxAppId">
                         <el-input type="text" v-model.trim="formData.WxAppId" placeholder="请输入AppID" />
@@ -130,7 +172,8 @@
                     </el-form-item>
                 </div>
             </div>
-            <div class="part-ppt part" v-if="isShowPPT||isShowEnPPT">
+            <!-- PPT配置 -->
+            <div class="part" v-if="isShowPPT||isShowEnPPT" v-show="partType===3">
                 <el-radio-group v-model="pptLang" style="margin-bottom: 22px;">
                     <el-radio-button label="cn">中文PPT</el-radio-button>
                     <el-radio-button label="en">英文PPT</el-radio-button>
@@ -235,37 +278,12 @@
                     </el-form-item>
                 </div>
             </div>
-            <div class="part-Iflytek part" 
-                v-if="isShowXunFei">
-                <!-- 科大讯飞 -->
-                <div style="width:100%;">
-                    <span style="color:#606266;">科大讯飞服务</span> 
-                    <el-switch v-model="Iflytek"></el-switch>
-                </div>
-                <template v-if="Iflytek">
-                    <div class="side">
-                        <el-form-item label="APPID" prop="XfAppid">
-                            <el-input type="text" v-model="formData.XfAppid" placeholder="请输入APPID" />
-                        </el-form-item>
-                        <el-form-item label="APIKey" prop="XfApiKey">
-                            <el-input type="text" v-model="formData.XfApiKey" placeholder="请输入APIKey" />
-                        </el-form-item>
-                    </div>
-                    <div class="side">
-                        <el-form-item label="APISecret" prop="XfApiSecret">
-                            <el-input type="text" v-model="formData.XfApiSecret" placeholder="请输入APISecret" />
-                        </el-form-item>
-                        <el-form-item label="vcn(voice_name)" prop="XfVcn">
-                            <el-input type="text" v-model="formData.XfVcn" placeholder="请输入voice_name" />
-                        </el-form-item>
-                    </div>
-                </template>
-            </div>
         </el-form>
-        <div class="btn-wrap" style="text-align: center;padding: 90px 0 60px 0;">
-            <el-button type="primary" plain style="width:200px;" @click="cancel">取消</el-button>
-            <el-button type="primary"  style="margin-left:50px;width:200px;" @click="saveBaseConfig">保存</el-button>
-        </div>
+        
+        </template>
+        <!-- 资源库 -->
+        <smartReportImgSet v-if="sectionType==2"/>
+
         <el-image-viewer 
             v-if="showViewer" 
             :on-close="()=>{this.picShowList=[];this.showViewer = false}" 
@@ -278,11 +296,12 @@ import ImgThumbnail from './components/imgThumbnail.vue';
 import ImgUpload from './components/imgUpload.vue';
 import ConfigAnnotation from './components/configAnnotation.vue';
 import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
+import smartReportImgSet from './components/smartReportImgSet.vue'
 
 import {bannerupload} from '@/api/api.js';
 import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
 export default {
-    components: { ConfigAnnotation , ElImageViewer , ImgThumbnail , ImgUpload},
+    components: { ConfigAnnotation , ElImageViewer , ImgThumbnail , ImgUpload,smartReportImgSet},
     data() {
         let ListValidator = (rule,value,callback)=>{
             if(!value.length){
@@ -412,6 +431,11 @@ export default {
             /* loading */
             configLoading:null,
 
+            partType:1,//1登陆设置 2研报设置 3PPT配置
+
+            sectionType:1,//1通用设置 2资源库
+
+
         };
     },
     computed:{
@@ -628,10 +652,29 @@ export default {
 <style scoped lang="scss">
 .eta-base-config{
     box-sizing: border-box;
-    padding:30px;
+    // padding:30px;
     border-radius: 4px;
     background-color: #fff;
+    .nav-type-box{
+        display: flex;
+        align-items: center;
+        border-bottom: 1px solid #E7E7E7;
+        span{
+            display: block;
+            height: 100%;
+            line-height: 32px;
+            padding: 8px;
+            cursor: pointer;
+            margin-right: 10px;
+            color: rgba($color: #000000, $alpha: 0.6);
+        }
+        .active{
+            color: #0052D9;
+            border-bottom: 2px solid #0052D9;
+        }
+    }
     .base-config-form{
+        padding: 30px;
         .el-form-item{
             width:100%;
         }
@@ -640,12 +683,6 @@ export default {
             display: flex;
             justify-content: space-between;
             flex-wrap: wrap;
-            &:not(:last-child){
-                border-bottom: 1px solid #DCDFE6;
-            }
-            &:not(:first-child){
-                margin-top: 50px;
-            }
             .side{
                 width:45%;
                 .form-item-type-two{

+ 6 - 6
src/views/transferPage.vue

@@ -41,15 +41,15 @@ export default {
 						case "researcher":
 						path = "/reportlist";
 						break;
-						case "compliance": //合规
-						path = "/contractapprovallist";
-						break;
+						// case "compliance": //合规
+						// path = "/contractapprovallist";
+						// break;
 						case "special_researcher": //特邀研究员
 						path = "/dataList";
 						break;
-						case "special_ficc_seller":
-						path = "/meetingCalendar";
-						break;
+						// case "special_ficc_seller":
+						// path = "/meetingCalendar";
+						// break;
 						default:
 						path = await this.getOtherRolePath("myCalendar");
 					}