فهرست منبع

Merge branch 'master' into eta1.0.2

Karsa 1 سال پیش
والد
کامیت
e529bbc754
100فایلهای تغییر یافته به همراه6276 افزوده شده و 748 حذف شده
  1. 1 0
      .gitignore
  2. 7 0
      README.md
  3. 13 1
      index.html
  4. 12 2
      src/api/api.js
  5. 1 1
      src/api/crypto.js
  6. 1 1
      src/api/http.js
  7. 36 0
      src/api/modules/chartApi.js
  8. 37 0
      src/api/modules/etaBaseConfigApi.js
  9. 22 0
      src/api/modules/home.js
  10. 13 2
      src/api/modules/oldApi.js
  11. 8 0
      src/api/modules/pptApi.js
  12. 8 0
      src/api/modules/pptEnApi.js
  13. 5 0
      src/api/modules/reportEnApi.js
  14. 4 0
      src/api/modules/semanticsApi.js
  15. 74 0
      src/api/modules/setApi.js
  16. BIN
      src/assets/img/eta_base_config/outlink.png
  17. BIN
      src/assets/img/home/email_icon.png
  18. BIN
      src/assets/img/home/login_logo.png
  19. BIN
      src/assets/img/home/phone_icon.png
  20. BIN
      src/assets/img/questionnaire.png
  21. 154 0
      src/components/questionnaireDia.vue
  22. 29 3
      src/main.js
  23. 1 1
      src/mixins/index.js
  24. 3 1
      src/mixins/theme.js
  25. 19 7
      src/routes/modules/chartRoutes.js
  26. 5 1
      src/routes/modules/futuresRoutes.js
  27. 23 1
      src/routes/modules/oldRoutes.js
  28. 289 0
      src/utils/TimeOnPage.js
  29. 8 0
      src/utils/buttonConfig.js
  30. 7 5
      src/utils/common.js
  31. 47 0
      src/utils/commonOptions.js
  32. 84 34
      src/views/Home.vue
  33. 446 150
      src/views/Login.vue
  34. 8 16
      src/views/chartRelevance_manage/components/chartCard.vue
  35. 8 0
      src/views/chartRelevance_manage/fittingEquationChartEditor.vue
  36. 2 2
      src/views/chartRelevance_manage/fittingEquationList.vue
  37. 2 2
      src/views/chartRelevance_manage/list.vue
  38. 8 0
      src/views/chartRelevance_manage/relevanceChartEditor.vue
  39. 8 0
      src/views/chartRelevance_manage/statisticFeatureChartEditor.vue
  40. 2 2
      src/views/chartRelevance_manage/statisticFeatureList.vue
  41. 4 3
      src/views/classify_manage/classifyEnlist.vue
  42. 2 2
      src/views/classify_manage/classifylist.vue
  43. 23 10
      src/views/dataEntry_manage/chartSetting.vue
  44. 25 12
      src/views/dataEntry_manage/codecount/index.vue
  45. 1 1
      src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue
  46. 780 0
      src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue
  47. 1 1
      src/views/dataEntry_manage/databaseComponents/createChart.vue
  48. 150 0
      src/views/dataEntry_manage/databaseComponents/edbDetailData.vue
  49. 780 0
      src/views/dataEntry_manage/databaseComponents/smoothEdbDialog.vue
  50. 23 1
      src/views/dataEntry_manage/databaseComponents/util.js
  51. 462 159
      src/views/dataEntry_manage/databaseList.vue
  52. 8 0
      src/views/dataEntry_manage/onlineExcelCopy.vue
  53. 1 1
      src/views/dataEntry_manage/targetList.vue
  54. 8 0
      src/views/datasheet_manage/customSheetEdit.vue
  55. 8 0
      src/views/datasheet_manage/mixedSheetEdit.vue
  56. 16 0
      src/views/futures_manage/chartEditor.vue
  57. 2 1
      src/views/futures_manage/commodityChartBase.vue
  58. 139 0
      src/views/login_manage/EmailModel.vue
  59. 339 0
      src/views/login_manage/ForgetPassModel.vue
  60. 156 0
      src/views/login_manage/MobileModel.vue
  61. 117 0
      src/views/login_manage/OrdinaryModel.vue
  62. 108 0
      src/views/login_manage/components/CaptchaInput.vue
  63. 99 0
      src/views/login_manage/components/ModelSteps.vue
  64. 79 0
      src/views/login_manage/components/VerificationBox.vue
  65. 111 0
      src/views/login_manage/css/formStyle.scss
  66. 34 0
      src/views/login_manage/modelMixins.js
  67. 23 9
      src/views/ppt_manage/mixins/pptMixins.js
  68. 9 9
      src/views/ppt_manage/newVersion/components/Cover.vue
  69. 7 7
      src/views/ppt_manage/newVersion/components/CoverEn.vue
  70. 3 1
      src/views/ppt_manage/newVersion/components/catalog/pptContent.vue
  71. 3 1
      src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue
  72. 26 11
      src/views/ppt_manage/newVersion/components/editor/ChooseCover.vue
  73. 26 10
      src/views/ppt_manage/newVersion/components/editor/ChooseCoverEn.vue
  74. 120 0
      src/views/ppt_manage/newVersion/components/editor/InsertSemantics.vue
  75. 28 14
      src/views/ppt_manage/newVersion/pptCatalog.vue
  76. 7 2
      src/views/ppt_manage/newVersion/pptEditor.vue
  77. 32 18
      src/views/ppt_manage/newVersion/pptEnCatalog.vue
  78. 8 2
      src/views/ppt_manage/newVersion/pptEnEditor.vue
  79. 3 3
      src/views/ppt_manage/newVersion/pptEnPublish.vue
  80. 3 3
      src/views/ppt_manage/newVersion/pptPublish.vue
  81. 18 0
      src/views/ppt_manage/newVersion/utils/untils.js
  82. 2 2
      src/views/predictEdb_manage/addPredicEdb.vue
  83. 16 10
      src/views/predictEdb_manage/components/chartInfo.vue
  84. 104 41
      src/views/predictEdb_manage/components/childData.vue
  85. 2 2
      src/views/predictEdb_manage/components/classifyDia.vue
  86. 112 3
      src/views/predictEdb_manage/components/edbDetail.vue
  87. 155 35
      src/views/predictEdb_manage/predictEdb.vue
  88. 93 4
      src/views/report_manage/addreportNew.vue
  89. 121 0
      src/views/report_manage/components/importSemantics.vue
  90. 1 1
      src/views/report_manage/dayOrWeek.vue
  91. 100 90
      src/views/report_manage/editChapterReport.vue
  92. 109 2
      src/views/report_manage/editreportNew.vue
  93. 7 5
      src/views/report_manage/mixins/messagePush.js
  94. 28 0
      src/views/report_manage/mixins/reportMixin.js
  95. 103 2
      src/views/report_manage/reportEn/reportEditor.vue
  96. 48 10
      src/views/report_manage/reportEn/reportlist.vue
  97. 2 2
      src/views/report_manage/reportVariety.vue
  98. 53 11
      src/views/report_manage/reportlist.vue
  99. 18 2
      src/views/resetpassword.vue
  100. 15 13
      src/views/sandbox_manage/sandFlow/index.vue

+ 1 - 0
.gitignore

@@ -17,3 +17,4 @@
 
 /static/dll.vendor.js
 /.idea
+/static/base_config.js

+ 7 - 0
README.md

@@ -8,6 +8,13 @@
 ### branch
 - master  debug  sandbox
 
+### pack
+- 在static/下新建base_config.js
+- base_config.js用于导出正式环境加密用的key,`window.key='对应环境的密钥'`
+- 在index.html中引入
+- 在src/api/crypto.js中,将key替换成window.key
+- 打包完成后,发布不同环境,只需要更改base_config.js中的密钥
+
 ### link
 - http://8.136.199.33:7778 弘则测试
 - https://eta.hzinsights.com 弘则正式

+ 13 - 1
index.html

@@ -12,6 +12,7 @@
 	<link rel="icon" type="image/x-icon" href="./static/fa.ico" id="icon"/>
 	<script src="./static/js/vue.js"></script>  <!-- 开发版,开发过程中使用此方案-->
 	<script src="./static/js/main.js"></script>  <!-- 生产版,打包的时候使用此方案 -->
+	<script src="./static/base_config.js"></script>  <!-- key -->
 	<!-- 引入组件库 -->
 	
 	<!-- oss SDK -->
@@ -25,7 +26,18 @@
 	
 	<!-- dataTables -->
 	<link rel="stylesheet" type="text/css" href="./static/css/jquery.dataTables.css"/>
-
+    <!-- 隐藏Edge在密码输入框的icon -->
+    <style>
+        input[type="password"]::-ms-reveal{
+            display: none;
+        }
+        input[type="password"]::-ms-clear{
+            display: none;
+        }
+        input[type="password"]::-o-reveal{
+            display: none;
+        }
+    </style>
 	<script>
 		var _hmt = _hmt || [];
 		(function() {

+ 12 - 2
src/api/api.js

@@ -56,6 +56,8 @@ import interactiveInterface from './modules/interactive';
 // 共享网盘
 import cloudDiskInterface from './modules/cloudDisk';
 
+import homeInterface from './modules/home'
+
 //视频管理模块
 import videoInterface from './modules/videoApi'
 
@@ -105,6 +107,7 @@ export {
   baiinfoInterface,
   nationalInterface,
   cloudDiskInterface,
+  homeInterface,
   businessTripInterence,
   reportVarietyENInterence
 };
@@ -116,6 +119,7 @@ const {
   userLogin,
   modifyPwd,
   checkPwd,
+  timeOnPage,
   reportlist,
   reportpublish,
   reportpublishcancle,
@@ -130,6 +134,7 @@ const {
   reportauthor,
   getDraft,
   autosave,
+  reportSetPrepublish,
   classifylist,
   classifyparent,
   classifyadd,
@@ -182,13 +187,16 @@ const {
   reportMessageSend,
   weekReportValidAudio,
   getUserUuid,
-  getBusinessCode
+  getBusinessCode,
+  recordActiveLogin
+
 } = oldApis;
 
 export {
   userLogin,
   modifyPwd,
   checkPwd,
+  timeOnPage,
   reportlist,
   reportpublish,
   reportpublishcancle,
@@ -203,6 +211,7 @@ export {
   reportauthor,
   getDraft,
   autosave,
+  reportSetPrepublish,
   classifylist,
   classifyparent,
   classifyadd,
@@ -255,6 +264,7 @@ export {
   reportMessageSend,
   weekReportValidAudio,
   getUserUuid,
-  getBusinessCode
+  getBusinessCode,
+  recordActiveLogin
 };
 

+ 1 - 1
src/api/crypto.js

@@ -1,4 +1,4 @@
-const key = '6WpHp4vSvLVQK8SLioNZ7WMq'; //eta
+const key = window.key||'6WpHp4vSvLVQK8SLioNZ7WMq'; //eta
 // const key = 'cJ3b1I4YBlTc85vnxy36xip2'; //逸诺
 // const key = 'bvS3kVp7QIZoD70fPk1wk41n'; //试用
 

+ 1 - 1
src/api/http.js

@@ -51,13 +51,13 @@ function checkStatus(response) {
     } else if (res.Ret == 403) {
       bus.$message.error(res.Msg);
     } else if (res.Ret === 408) {
+      localStorage.setItem("auth", "")
       bus
         .$alert(res.Msg, "提示", {
           showClose: false,
         })
         .then(() => {
           window.location.href = window.location.origin + '/login';
-
         });
     }
     return res;

+ 36 - 0
src/api/modules/chartApi.js

@@ -374,6 +374,14 @@ const dataBaseInterface = {
 		return http.post('/datamanage/edb_info/calculate/compute_correlation',params)
 	},
 
+	/**
+	 * 代码运算的sourceList
+	 * @param {*} params 
+	 */
+	getCodecountEdbSources: params => {
+		return http.get('/datamanage/edb_source/list/python')
+	},
+
 
 	//========================================chart
 	// /**
@@ -862,6 +870,34 @@ const dataBaseInterface = {
 	getDataSource:(params)=>{
 		return http.get('datamanage/edb_source/list',params)
 	},
+	/**
+	 * 指标图表列表
+	 * @param {Number} PageSize 
+	 * @param {Number} CurrentIndex
+	 * @param {Number} ClassifyId
+	 * @param {Number} AdminId
+	 * @param {Boolean} IsOnlyMe
+	 */
+	getEdbChartList:(params)=>{
+		return http.get('/datamanage/edb_info/chart/list',params)
+	},
+	/**
+	 * 保存指标上下限
+	 * @param {*} params 
+	 * @returns 
+	 */
+	saveEdbChartLimit:(params)=>{
+		return http.post('/datamanage/edb_info/modify',params)
+	},
+	/**
+	 * 保存指标缩略图
+	 * @param {Number} EdbInfoId 
+	 * @param {String} ImageUrl 
+	 * @returns 
+	 */
+	saveEdbChartImg:(params)=>{
+		return http.post('/datamanage/edb_info/image/set',params)
+	}
 	
 }
 

+ 37 - 0
src/api/modules/etaBaseConfigApi.js

@@ -7,4 +7,41 @@ export const etaBaseConfigInterence = {
     saveBaseConfig:params=>{
         return http.post('/business_conf/save',params)
     }
+}
+
+// 外部链接配置 接口
+export const outlinkConfigInterence = {
+    /**
+     * 外部链接列表
+     * @param params.CurrentIndex 页码-number
+     * @param params.PageSize 每页数据量-number
+     * @param params.SortParam 排序字段-string
+     * @param params.SortType 排序类型-string desc/asc/""
+     * @returns 
+     */
+    getOutlinkList:params=>{
+        return http.get('/out_link/list',params)
+    },
+    // 外部链接列表全部
+    getOutlinkListAll:params=>{
+        return http.get('/out_link/all',params)
+    },
+    /** 
+     * 新增/编辑
+     * @param params.Id Id-number-不传ID表示新增,传了ID表示编辑
+     * @param params.Title 菜单名称-string
+     * @param params.Url 页面链接-string
+     * @returns 
+     */
+    outlinkSave:params=>{
+        return http.post('/out_link/save',params)
+    },
+    /** 
+     * 删除
+     * @param params.Id Id-number
+     * @returns 
+     */
+    outlinkDelete:params=>{
+        return http.post('/out_link/del',params)
+    }
 }

+ 22 - 0
src/api/modules/home.js

@@ -0,0 +1,22 @@
+import http from "@/api/http.js"
+
+/* 首页请求的接口  */
+const homeInterface = {
+	/**
+	 * 问卷调查详情接口
+	 */
+	getQuestionnaireDetail: () => {
+		return http.get('/eta_trial/questionnaire/popup')
+	},
+  /**
+ * 问卷调查详情 - 提交答案
+ * List[index].QuestionnaireId  题目Id
+  List[index].integerOptions 答案 多选用 ~# 隔开
+  List[index].Type 问题类型
+ */
+	questionnaireSubmit: (params) => {
+		return http.post('/eta_trial/questionnaire/commit',params)
+	}
+}
+
+export default homeInterface

+ 13 - 2
src/api/modules/oldApi.js

@@ -5,7 +5,9 @@ import http from "@/api/http.js"
 //  const modifyPwd = params => { return http.post('/modifyPwd',params); };  //修改密码
  const modifyPwd = params => { return http.post('/sysuser/modify/pwd',params); };  //修改密码
  const checkPwd = params => { return http.get('/sysuser/check_pwd'); };  //判断是否为初始密码
-
+ 
+	//用户累计停留时长 ActiveTime(s) Part
+ const timeOnPage = params =>{return http.post('/eta_trial/user/active',params)}
  const reportlist = params => { return http.get('/report/list',params); };  //获取报告列表
  const reportpublish = params => { return http.post('/report/publish',params); };  //批量发布报告
  const reportpublishcancle = params => { return http.post('/report/publish/cancle',params); };  //取消发布报告
@@ -20,6 +22,7 @@ import http from "@/api/http.js"
  const reportauthor = params => { return http.get('/report/author',params); };  //获取作者
  const getDraft = params => { return http.get('/report/getDraft',params); };  //获取草稿
  const autosave = params => { return http.post('/report/saveReportContent',params); };  //保存
+ const reportSetPrepublish=params=>{return http.post('/report/pre_publish',params);};//报告设置定时发布
 
  const classifylist = params => { return http.get('/classify/list',params); };  //获取分类列表
  const classifyparent = params => { return http.get('/classify/parent',params); };  //获取父级分类
@@ -296,6 +299,11 @@ const getBusinessCode=params=>{
 	return http.get('/business_conf/code_encrypt',params)
 }
 
+// 获取商家code "ActiveTime":99
+const recordActiveLogin=params=>{
+	return http.post('/eta_trial/user/login_duration',params)
+}
+
 /**
  * 获取动态配配置 系统内部动态链接
  * @param {*} params 
@@ -308,6 +316,7 @@ export {
 	userLogin,
 	modifyPwd,
 	checkPwd,
+	timeOnPage,
 	reportlist,
 	reportpublish,
 	reportpublishcancle,
@@ -322,6 +331,7 @@ export {
 	reportauthor,
 	getDraft,
 	autosave,
+	reportSetPrepublish,
 	classifylist,
 	classifyparent,
 	classifyadd,
@@ -375,5 +385,6 @@ export {
 	weekReportValidAudio,
 	getUserUuid,
 	getBusinessCode,
-	getPublicSettingsApi
+	getPublicSettingsApi,
+	recordActiveLogin
 }

+ 8 - 0
src/api/modules/pptApi.js

@@ -146,6 +146,14 @@ export default{
     searchPPTByKeyWorld:params=>{
       return http.get('/pptv2/share/ppt/list',params)
     },
+    /**
+     * 搜索PPT,范围为 我的+公共
+     * @param {String} Keyword 
+     * @returns 
+     */
+    searchPPTByKeyWorldV2:params=>{
+        return http.get('/pptv2/ppt/search',params)
+    },
     /**
      * 移动目录里的ppt
      * GroupPptId

+ 8 - 0
src/api/modules/pptEnApi.js

@@ -131,6 +131,14 @@ export const pptEnInterface = {
     searchPPTByKeyWorld:params=>{
       return http.get('/ppt_english/share/ppt/list',params)
     },
+    /**
+     * 搜索PPT,范围为 我的+公共
+     * @param {String} Keyword 
+     * @returns 
+     */
+    searchPPTByKeyWorldV2:params=>{
+        return http.get('/ppt_english/ppt/search',params)
+      },
     /**
      * 移动目录里的ppt
      * GroupPptId

+ 5 - 0
src/api/modules/reportEnApi.js

@@ -162,6 +162,11 @@ export const markReport=params => {
   return http.post('/english_report/mark',params)
 }
 
+//定时发布报告
+export const enReportPrepblish=params=>{
+	return http.post('/english_report/pre_publish',params)
+}
+
 /* 发送日志 */
 export const logInterface = {
 	/**

+ 4 - 0
src/api/modules/semanticsApi.js

@@ -270,6 +270,10 @@ const semanticInterface = {
    */
   moveCompare:params => {
       return http.post('/semantic_analysis/compare/move',params)
+  },
+  //对比文档列表数据
+  compareSearch:params=>{
+    return http.get('/semantic_analysis/compare/search',params)
   }
 }
 

+ 74 - 0
src/api/modules/setApi.js

@@ -260,7 +260,81 @@ const departInterence = {
 	//获取用户所有的按钮权限
 	getRoleBtnAuth:params=>{
 		return http.get('/system/role/menu/buttons',params)
+	},
+	/**
+	 * 获取图形验证码 返回Base64格式数据
+	 * @returns 
+	 */
+	getCodePic:params=>{
+		return http.get('/user_login/get_captcha',params)
+	},
+	/**
+	 * 获取短信/邮箱验证码
+	 * @param {Number} VerifyType 验证方式: 1-手机号; 2-邮箱
+	 * @param {String} CaptchaId 图形验证码ID
+	 * @param {String} CaptchaCode 图形验证码的值
+	 * @param {String} Mobile 手机号 验证方式为1时必填
+	 * @param {String} Email 邮箱 验证方式为2时必填
+	 * @param {String} TelAreaCode 手机区号
+	 * @param {Number} Source 来源:1-登录;3-忘记密码
+	 * @returns 
+	 */
+	getCodeVerify:params=>{
+		return http.post('/user_login/verify_code',params)
+	},
+	/**
+	 * ETA1.4后,用户登录
+	 * @param {Number} LoginType 登录方式: 1-账号; 2-手机号; 3-邮箱
+	 * @param {String} Username 用户名
+	 * @param {String} Password 密码
+	 * @param {String} Mobile 手机号
+	 * @param {String} Email 邮箱
+	 * @param {String} VerifyCode 手机号/邮箱的验证码
+	 * @returns 
+	 */
+	userLogin:params=>{
+		return http.post('/user_login/login',params)
+	},
+	/**
+	 * 忘记密码账号校验,获取账号信息
+	 * @param {String} CaptchaId 图形验证码ID
+	 * @param {String} CaptchaCode 图形验证码
+	 * @param {String} UserName 账号
+	 * @returns 
+	 */
+	accountCheck:params=>{
+		return http.post('/user_login/forget/account_get',params)
+	},
+	/**
+	 * 忘记密码-手机/邮箱的验证码校验
+	 * @param {Number} FindType 密码找回方式:1-手机号;2-邮箱
+	 * @param {String} VerifyCode 验证码
+	 * @param {String} UserName 用户名
+	 * @param {String} Mobile 找回方式为手机号时必填
+	 * @param {String} Email 找回方式为邮箱时必填
+	 * @returns 
+	 */
+	checkCodeVerify:params=>{
+		return http.post('/user_login/forget/code_verify',params)
+	},
+	/**
+	 * 忘记密码-重置密码
+	 * @param {String} UserName 
+	 * @param {String} Password 
+	 * @param {String} RePassword 
+	 * @returns 
+	 */
+	resetPass:params=>{
+		return http.post('/user_login/forget/reset_pass',params)
+	},
+	/**
+	 * 获取手机号区号
+	 * @returns 
+	 */
+	getPhoneAreaCode:params=>{
+		return http.get('/user_login/area_code/list',params)
 	}
+
 }
 
 /* 视频管理 */

BIN
src/assets/img/eta_base_config/outlink.png


BIN
src/assets/img/home/email_icon.png


BIN
src/assets/img/home/login_logo.png


BIN
src/assets/img/home/phone_icon.png


BIN
src/assets/img/questionnaire.png


+ 154 - 0
src/components/questionnaireDia.vue

@@ -0,0 +1,154 @@
+<template>
+  <div >
+    <el-dialog
+      title="问卷调查"
+      :visible.sync="dialogVisiblePwd"
+      :append-to-body="true"
+      :close-on-click-modal="false"
+      @closed="handleClosed"
+      width="780px"
+      top="5vh"
+    >
+      <div style="padding: 10px 40px 0;" class="questionnaire-container" id="questionnaire-container">
+        <div class="questionnaire-title">
+          {{ questionList[0]&&questionList[0].Option?questionList[0].Option[0]:'尊敬的用户,感谢您使用系统,以下是对系统使用的调研问卷,我们期待您真实的反馈' }}
+        </div>
+        <el-form :model="quesitionForm" ref="questionRef" label-position="top" size="small">
+          <el-form-item :label="index+1+'.'+item.Question" :prop="item.QuestionnaireId+''" 
+          :rules="item.IsMust?{required:true,message:'该题为必答题',trigger:['blur','change']}:''"
+          v-for="(item,index) in questionList.slice(1)" :key="item.QuestionnaireId">
+            <el-radio-group v-model="quesitionForm[item.QuestionnaireId]" v-if="item.Type==1">
+              <el-radio :label="it" v-for="(it,ind) in item.Option" :key="it">{{ it }}</el-radio>
+            </el-radio-group>
+            <el-checkbox-group v-model="quesitionForm[item.QuestionnaireId]"
+            v-else-if="item.Type==2">
+              <el-checkbox  :label="it" v-for="(it,ind) in item.Option" :key="it">{{ it }}</el-checkbox>
+            </el-checkbox-group>
+            <el-input v-else rows="5" v-model="quesitionForm[item.QuestionnaireId]" type="textarea" placeholder="请输入文本"></el-input>
+          </el-form-item>
+        </el-form>
+        <div style="text-align: center;padding:40px 0 ;">
+          <el-button @click="submitQuestion(1)" type="primary" style="width: 120px;" size="40">提交</el-button>
+          <el-button @click="submitQuestion(0)" style="width: 120px;margin-left: 28px;" size="40">以后再填</el-button>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {  homeInterface } from "api/api.js";
+
+  export default {
+    name:'questionnaireDia',
+    data() {
+      return {
+        quesitionForm:{}
+      }
+    },
+    watch:{
+      questionList:{
+        handler:function(value,old){
+          // console.log(value);
+          // 初始化数据
+          value.map((item,index) =>{
+            if(index ==0)  return
+            if(item.Type==2){
+              this.$set(this.quesitionForm,item.QuestionnaireId,[])
+            }else{
+              this.$set(this.quesitionForm,item.QuestionnaireId,'')
+            }
+
+          })
+          console.log(this.quesitionForm);
+        },
+        deep:true,
+        immediate:true
+      }
+    },
+    props:{
+      dialogVisiblePwd: {
+        type: Boolean,
+        default: false,
+      },
+      questionList:{
+        type: Array,
+        default: () =>[],
+      }
+    },
+    methods:{
+      submitQuestion(isFill){
+        if(isFill!=1){
+          homeInterface.questionnaireSubmit({List:[],IsFill:isFill}).then(res=>{
+            if(res.Ret == 200){
+              this.$emit('update:dialogVisiblePwd',false)
+            }
+          })
+        }else{
+          this.$refs.questionRef.validate((valid)=>{
+            if(valid){
+              let paramList = this.questionList.map((item)=>{
+                if(item.Type==4 || this.quesitionForm[item.QuestionnaireId].length==0) return undefined
+                return {
+                  QuestionnaireId:item.QuestionnaireId,
+                  Options:Array.isArray(this.quesitionForm[item.QuestionnaireId])?
+                  this.quesitionForm[item.QuestionnaireId].join('~#'):this.quesitionForm[item.QuestionnaireId],
+                  Type:item.Type
+                }
+              }).filter(Boolean)
+              // console.log(paramList);
+              if(paramList.length==0){
+                this.$emit('update:dialogVisiblePwd',false)
+                return 
+              }
+              homeInterface.questionnaireSubmit({List:paramList,IsFill:isFill}).then(res=>{
+                if(res.Ret == 200){
+                  this.$message.success('提交成功')
+                  this.$emit('submitSuccess')
+                  this.$emit('update:dialogVisiblePwd',false)
+                }
+              })
+            }
+          })
+        }
+      },
+      handleClosed(){
+        this.$refs.questionRef.resetFields()
+        this.$emit('update:dialogVisiblePwd',false)
+      }
+    },
+    created(){
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .questionnaire-container{
+    .questionnaire-title{
+      font-weight: 500;
+      font-size: 16px;
+      color: #333333;
+      margin-bottom: 15px;
+    }
+
+  }
+</style>
+<style lang="scss">
+  #questionnaire-container{
+    .el-form-item__label{
+      font-weight: 5000;
+      font-size: 16px;
+      color: #333333;
+    }
+    .el-radio__label,.el-checkbox__label,.el-textarea__inner{
+      color: #666666;
+    }
+    .el-checkbox-group,.el-radio-group{
+      margin-left: -40px;
+    }
+    .el-radio,.el-checkbox{
+      margin-right: 0;
+      margin-left: 40px;
+    }
+  }
+</style>

+ 29 - 3
src/main.js

@@ -18,6 +18,9 @@ Vue.use(ElementUI);
 Vue.use(VueRouter);
 Vue.use(Vuex);
 
+import{endCalc,optionTimeCalc,init}from'@/utils/TimeOnPage.js';
+
+
 import setting from '@/mixins/theme.js'
 Vue.prototype.$setting = setting;
 
@@ -141,7 +144,7 @@ router.beforeEach(async(to, from, next) => {
   } */
 
   let auth = localStorage.getItem("auth") || false;
-  if (to.path != "/login" && to.path!='/temppage' && !auth) {
+  if (to.path != "/login" && to.path!='/temppage' &&to.path!='/fogetpassword' && !auth) {
     window.location.href =  window.location.origin + '/login';
     return false;
   }
@@ -173,12 +176,35 @@ router.beforeEach(async(to, from, next) => {
   }
 });
 
+
 router.afterEach((to, from, next) => {
   // 改变页面标题
   document.title = to.matched[to.matched.length - 1].name
-    ? `ETA-${to.matched[to.matched.length - 1].name}`
-    : "ETA";
+  ? `${setting.name}-${to.matched[to.matched.length - 1].name}`
+  : setting.name;
+
   window.scrollTo(0, 0);
+  if(stores.state.hasTrialUserPermisson){
+
+    sessionStorage.setItem('preTitle',from.name||'')
+
+    if(!stores.state.hasDoPageListening){
+      // 初始化需要放在 页面设置标题后,才能拿到正确的标题
+      init()
+      stores.mutations.SET_PAGE_EVENT_LISTENER(stores.state,true)
+    }
+
+    const routerChangeType = sessionStorage.getItem('routerChangeType')
+    if(routerChangeType==='popstate'){
+      const IsActive = sessionStorage.getItem('IsActive')
+      if(IsActive=='1'){
+        endCalc('popstate',Number(sessionStorage.getItem('popStayTime')||0))
+      }
+      optionTimeCalc()
+      sessionStorage.removeItem('routerChangeType')
+      sessionStorage.removeItem('popStayTime')
+    }
+  }
 });
 
 Vue.config.devtools = true;

+ 1 - 1
src/mixins/index.js

@@ -9,7 +9,7 @@ const mixins = {
 			if(time==='0001-01-01 00:00:00'||time==='0000-00-00 00:00:00'){
 				return '--'
 			}else{
-				return time.replace(/-/g,'.')
+				return time?time.replace(/-/g,'.'):''
 			}
 			
 		},

+ 3 - 1
src/mixins/theme.js

@@ -2,7 +2,7 @@
 一些动态配置和一些全局自定义东西 
 */
 export default {
-	name: '后台管理系统',
+	name: 'ETA',
   theme_color: '#0052D9',
   menu_bg:'#fff',//菜单栏背景色
   //跳转外部系统
@@ -28,5 +28,7 @@ export default {
   ],
   login_bg: require('@/assets/img/login_bg.png'),//登录页的大图
   login_logo: require('@/assets/img/login_logo.png'),
+  g_logo: require('@/assets/img/home/logo.png'),
+  g_mini_logo: require('@/assets/img/home/eta_mini.png'),
   dynamicOutLinks:{}//动态的外部link链接
 }

+ 19 - 7
src/routes/modules/chartRoutes.js

@@ -103,12 +103,12 @@ export default [
 			},
 			{
 				path:"addCustomSheet",
-				name:"表格编辑",
+				name:"添加表格",
 				component:()=>import('@/views/datasheet_manage/customSheetEdit.vue')
 			},
 			{
 				path:"addMixedSheet",
-				name:"表格编辑",
+				name:"添加表格",
 				component:()=>import('@/views/datasheet_manage/mixedSheetEdit.vue')
 			},
 			{
@@ -199,12 +199,20 @@ export default [
 			{
 				path: 'fittingEquationChartEditor',
 				name: '添加图表',
-				component: () => import('@/views/chartRelevance_manage/fittingEquationChartEditor.vue')
+				component: () => import('@/views/chartRelevance_manage/fittingEquationChartEditor.vue'),
+				meta: { 
+					pathFrom: "fittingEquationList",
+          			pathName: "拟合方程曲线",
+				}
 			},
 			{
 				path: 'relevancechartEditor',
-				name: '图表编辑',
-				component:()=>import('@/views/chartRelevance_manage/relevanceChartEditor.vue')
+				name: '编辑图表',
+				component:()=>import('@/views/chartRelevance_manage/relevanceChartEditor.vue'),
+				meta: { 
+					pathFrom: "chartrelevance",
+          			pathName: "相关性图表",
+				}
 			},
 			{
 				path: 'statisticFeatureList',
@@ -213,8 +221,12 @@ export default [
 			},
 			{
 				path: 'statisticFeatureChartEditor',
-				name: '图表编辑',
-				component:()=>import('@/views/chartRelevance_manage/statisticFeatureChartEditor.vue')
+				name: '编辑图表',
+				component:()=>import('@/views/chartRelevance_manage/statisticFeatureChartEditor.vue'),
+				meta: { 
+					pathFrom: "statisticFeatureList",
+          			pathName: "统计特征",
+				}
 			}
 		]
 	},

+ 5 - 1
src/routes/modules/futuresRoutes.js

@@ -20,7 +20,11 @@ export default [
       {
 				path: "addCommodityChart",
 				name: "编辑图表",
-				component: () => import('@/views/futures_manage/chartEditor.vue')
+				component: () => import('@/views/futures_manage/chartEditor.vue'),
+				meta: { 
+					pathFrom: "commordityChartBase",
+          			pathName: "商品价格曲线",
+				}
 			},
     ]
   }  

+ 23 - 1
src/routes/modules/oldRoutes.js

@@ -187,7 +187,7 @@ export default [
         path: "reportEnEditor",
         component: () =>
           import("@/views/report_manage/reportEn/reportEditor.vue"),
-        name: "英文研报编辑",
+        name: "添加英文研报",
         hidden: false,
       },
       {
@@ -300,6 +300,28 @@ export default [
         name: "基本配置",
         hidden: true,
       },
+      {
+        path: "outlinkListConfig",
+        component: () => import("@/views/system_manage/outlinkListConfig.vue"),
+        name: "外部链接配置",
+        hidden: true,
+      },
     ],
   },
+  // 外部链接
+  {    
+    path: "/",
+    component: home,
+    name: "外部链接",
+    hidden: false,
+    icon_path: require("@/assets/img/home/set_ico.png"),
+    children: [
+      {
+        path: "outlinkList",
+        component: () => import("@/views/system_manage/outlinkList.vue"),
+        name: "外部链接",
+        hidden: true,
+      },
+    ]
+  }
 ];

+ 289 - 0
src/utils/TimeOnPage.js

@@ -0,0 +1,289 @@
+//计算账号累计活跃时长
+import setting from '@/mixins/theme.js'
+import {timeOnPage , recordActiveLogin} from '@/api/api.js';
+//活跃时间间隔 (s)
+const TimeInterval = 60*10
+//页面停留时间 (s)
+let stayTime = 0
+
+
+//活跃时间记录计时器 1分钟记录一次
+let intervalTimer=null
+
+export const openLoginTimer=()=>{
+  // 登录时间
+  localStorage.setItem("loginTime",new Date())
+
+  clearInterval(intervalTimer)
+  intervalTimer = setInterval(()=>{
+    // let inactiveTime = time || new Date()
+    let ActiveTime=0
+    if(localStorage.getItem('loginTime')){
+      ActiveTime = (new Date()-new Date(localStorage.getItem('loginTime')))/1000
+      console.log("1分钟间隔记录时长",ActiveTime+'s');
+      recordActiveLogin({ActiveTime:Math.round(ActiveTime)}).then(res=>{
+        if(res.Ret!==200) return
+      })
+    }
+  },1000*60)
+}
+
+export const recordActiveLoginFun=(time)=>{
+  let inactiveTime = time || new Date()
+  let ActiveTime=0
+  if(localStorage.getItem('loginTime')){
+    ActiveTime = (inactiveTime-new Date(localStorage.getItem('loginTime')))/1000
+    console.log("结束计算时长",ActiveTime+'s');
+    recordActiveLogin({ActiveTime:Math.round(ActiveTime)}).then(res=>{
+      if(res.Ret!==200) return
+    }).finally(()=>{
+      // 清除工作
+      clearInterval(intervalTimer)
+      localStorage.removeItem('loginTime')
+    })
+  }
+}
+
+let timer = null
+
+//打开计时器
+export const optionTimeCalc = ()=>{
+  const IsActive = sessionStorage.getItem('IsActive')
+  if(Number(IsActive)===0){
+    //console.log('打开计时器')
+    sessionStorage.setItem('IsActive',1)
+    timeStr = new Date().getTime()
+    startCalc()
+  }
+  
+}
+//开始计时
+export const startCalc = ()=>{
+  sessionStorage.setItem('preTitle',document.title)
+  timer = setInterval(()=>{
+    stayTime++
+    
+    if(stayTime>=TimeInterval){
+      endCalc('timeup',0)
+    }
+  },1000)
+}
+
+//结束计时
+export const endCalc = (type,intervalT)=>{
+  //console.log('关闭计时器')
+  clearInterval(timer)
+  const IsActive = sessionStorage.getItem('IsActive')
+  if(Number(IsActive) && localStorage.getItem('auth')){
+     sendTOPInfo(type,intervalT)
+  }
+  stayTime = 0
+  /* if(type==='timeup'){
+    sessionStorage.setItem('IsActive',0)
+  } */
+  timeStr = new Date().getTime()
+  sessionStorage.setItem('IsActive',0)
+}
+
+// 退出登录时的结算
+export const loginEndCalc=()=>{
+  let t = new Date().getTime() - timeStr
+  //console.log('待了时长replacestate:'+ t)
+  const IsActive = sessionStorage.getItem('IsActive')
+  if(Number(IsActive)){
+    endCalc('logout',t)
+  }
+}
+
+//发送活跃时长数据
+export const sendTOPInfo = (type,intervalT)=>{
+  //获取上一个页面标题
+  const Title = sessionStorage.getItem('preTitle')
+  //console.log('发送活跃时长数据 ↓↓↓')
+  //获取计时间隔时间和页面名称
+  if(type==='timeup'){
+    console.table([{'停留时间(timeup)':stayTime+' s','停留页面':Title}])
+  }else{
+    console.table([{'停留时间(other)':Number(intervalT)/1000+' s','停留页面':Title,'触发类型':type}])
+  }
+  const Part = Title.split('-').length>1?Title.split('-')[1]:Title
+  const ActiveTime = type==='timeup'?stayTime:Number(intervalT)/1000
+  //发送数据
+  if(!Part.length||Part==setting.name) return
+  if(ActiveTime>TimeInterval*12) return
+  console.log("ActiveTime:",ActiveTime,"Part:",Part)
+  timeOnPage({
+    ActiveTime:Math.round(ActiveTime),
+    Part:Part
+  }).then(res=>{
+    if(res.Ret!==200) return
+  })
+}
+
+//路由监听部分 
+//source https://juejin.cn/post/6905913200060366862#heading-2
+
+
+let timeStr=null
+let rewriteHis = function(type){
+  let origin = window.history[type]
+  return function(){
+    let rs = origin.apply(this, arguments)
+    let e = new Event(type.toLocaleLowerCase())
+    e.arguments = arguments
+    window.dispatchEvent(e)
+    return rs
+  }
+}
+
+export function init(){
+  const unloadT = sessionStorage.getItem('unloadT')
+  const IsActive = sessionStorage.getItem('IsActive')
+  if(unloadT){
+    //console.log('刷新该页呆了时长',unloadT)
+    sessionStorage.removeItem('unloadT')
+    sessionStorage.setItem('preTitle',document.title)
+    if(Number(IsActive)){
+      endCalc('unload',unloadT)
+    }
+  }
+  timeStr = new Date().getTime()
+  optionTimeCalc()
+
+  if((!localStorage.getItem("loginTime")) && localStorage.getItem('auth')){
+    // 初始化的时候 先重置最近登录时长
+    recordActiveLogin({ActiveTime:0}).then(res=>{
+      if(res.Ret!==200) return
+    })
+    openLoginTimer()
+  }
+}
+
+export const doPageEventListener=function(){
+
+  // init() 放在router.afterEach中,不然一开始拿不到正确的页面标题
+
+  window.history.pushState = rewriteHis('pushState')
+
+  window.history.replaceState = rewriteHis('replaceState')
+
+  //刷新加载完成 
+  // 因为监听改位置了,每次路由刷新时,由于需要等待接口返回,需要先判断是否有 权限才能监听,这时候onload已经执行了,根本监听不到
+  // window.addEventListener('load',(e)=>{
+    // const unloadT = sessionStorage.getItem('unloadT')
+    // const IsActive = sessionStorage.getItem('IsActive')
+    // if(unloadT){
+    //   //console.log('刷新该页呆了时长',unloadT)
+    //   sessionStorage.removeItem('unloadT')
+    //   sessionStorage.setItem('preTitle',document.title)
+    //   if(Number(IsActive)){
+    //     endCalc('unload',unloadT)
+    //   }
+    // }
+    // timeStr = new Date().getTime()
+    // optionTimeCalc()
+  
+    // if((!localStorage.getItem("loginTime")) && localStorage.getItem('auth')){
+    //   // 初始化的时候 先重置最近登录时长
+    //   recordActiveLogin({ActiveTime:0}).then(res=>{
+    //     if(res.Ret!==200) return
+    //   })
+    //   openLoginTimer()
+    // }
+  // })
+  //刷新离开页面
+  window.addEventListener('beforeunload',(e)=>{
+    console.log('beforeunload')
+    let t = new Date().getTime() - timeStr
+    const IsActive = sessionStorage.getItem('IsActive')
+    if(Number(IsActive)){
+      sessionStorage.setItem('unloadT',t)
+    }
+  })
+
+  //刷新离开页面
+  window.addEventListener('unload',(e)=>{
+    console.log('unload')
+    recordActiveLoginFun()
+    // 猜测在unload这里 浏览器不会等待异步返回 清除工作在这进行
+    clearInterval(intervalTimer)
+    localStorage.removeItem('loginTime')
+  })
+
+  //popstate会在router.before/afterEach 之前触发,所以这里不对计时操作,操作放到before/afterEach
+  window.addEventListener('popstate',(e)=>{
+    //console.log('popState',e)
+    let t = new Date().getTime() - timeStr
+    timeStr = new Date().getTime()
+    //console.log('待了时长popstate:'+ t)
+    sessionStorage.setItem('routerChangeType','popstate')
+    sessionStorage.setItem('popStayTime',t)
+  })
+  
+  window.addEventListener('pushstate',()=>{
+    let t = new Date().getTime() - timeStr
+    timeStr = new Date().getTime()
+    //console.log('待了时长pushstate:'+ t)
+    const IsActive = sessionStorage.getItem('IsActive')
+    if(Number(IsActive)){
+      endCalc('pushstate',t)
+    }
+    optionTimeCalc()
+  })
+  
+  window.addEventListener('replacestate',()=>{
+    let t = new Date().getTime() - timeStr
+    timeStr = new Date().getTime()
+    //console.log('待了时长replacestate:'+ t)
+    const IsActive = sessionStorage.getItem('IsActive')
+    if(Number(IsActive)){
+      endCalc('replacestate',t)
+    }
+    optionTimeCalc()
+  })
+  
+  //页面监听
+  /* document.addEventListener('visibilitychange', function () {
+    // 用户离开了当前页面
+    if (document.visibilityState === 'hidden') {
+      console.log('hidden')
+      const IsActive = sessionStorage.getItem('IsActive')
+      if(Number(IsActive)){
+        let t = new Date().getTime() - timeStr
+        timeStr = new Date().getTime()
+        endCalc('hidden',t)
+      }
+    }
+  
+    // 用户打开或回到页面
+    if (document.visibilityState === 'visible') {
+      console.log('visible')
+      const IsActive = sessionStorage.getItem('IsActive')
+      if(IsActive==='0'){
+        timeStr = new Date().getTime()
+        optionTimeCalc()
+      }
+    }
+  }); */
+  document.addEventListener('click',(e)=>{
+
+    //console.log('click',e,e.composedPath())
+    //只计算displayMain 的click
+    const path = e.composedPath()
+    const contentIndex = path.findIndex((item)=>{return item.className==="content-container"})
+    if(contentIndex===-1) return 
+    //console.log('合法的click')
+    const IsActive = sessionStorage.getItem('IsActive')
+    if(Number(IsActive)===0){
+      optionTimeCalc()
+    }else{
+      //console.log('重置活跃计时')
+      //重置活跃时间
+      stayTime = 0
+    }
+  })
+}
+
+
+
+

+ 8 - 0
src/utils/buttonConfig.js

@@ -469,4 +469,12 @@ export const baseConfigPermission = {
     etaBaseConfig_watermark:'etaBaseConfig:watermark',
     etaBaseConfig_watermark_ybChart:'etaBaseConfig:watermark:ybChart',//如果没权限,表单不显示也不校验
 
+}
+
+/*-----------外部链接配置-------- */
+export const outlinkConfigPermission = {
+    outlinkListConfig_list:'outlinkListConfig:list',//查看列表
+    outlinkListConfig_add:'outlinkListConfig:add',//添加
+    outlinkListConfig_edit:'outlinkListConfig:edit',//编辑
+    outlinkListConfig_del:'outlinkListConfig:del',//删除
 }

+ 7 - 5
src/utils/common.js

@@ -39,8 +39,10 @@ export function downloadByFlow(data,type,fileName) {
     window.URL.revokeObjectURL(blob) //释放掉 blob 对象
   }
 
-// export default {
-//     getBrowser,
-//     getNetworkType,
-//     getSystemInfo
-// }
+/* 获取地址栏参数值 */
+export function getUrlParams(str=window.location.href,key) {
+  let obj = {};
+	str.split('?')[1].split('&').map(i => obj[(i.split('=')[0])] = i.split('=')[1]);
+
+  return obj[key]
+}

+ 47 - 0
src/utils/commonOptions.js

@@ -0,0 +1,47 @@
+
+//验证密码的正则 产品定的规则是:8位及以上,包含数字、大写字母、小写字母、特殊字符中的三个类型
+export const patternPassWord = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/
+export function checkPassWord(pwd){
+    let num = 0
+    const patternArr = [
+        /^(?=.*[0-9])/,
+        /^(?=.*[a-z])/,
+        /^(?=.*[A-Z])/,
+        /^(?=.*[@#$%^&+=.])/,
+    ]
+    patternArr.forEach(pattern=>{
+        if(pattern.test(pwd)){
+            num++
+        }
+    })
+    if(pwd.length<8){
+        num = 0
+    }
+    return num>=3
+}
+//验证手机号的正则 仅支持国内大陆的
+export const patternPhone = /0?(13|14|15|18|17)[0-9]{9}/
+export function isMobileNo(account) {
+    // 手机号正则
+    var isChinaMobile = new RegExp(
+      "(^1(3[4-9]|4[78]|5[0-27-9]|7[28]|8[2-478]|98)\\d{8}$)"
+    ); // 中国移动
+    // 手机段:134,135,136,137,138,139,147,148[卫星通信],150,151,152,157,158,159,172,178,182,183,184,187,188,198
+    var isChinaUnicom = new RegExp(
+      "(^1(3[0-2]|4[56]|5[56]|66|7[156]|8[56])\\d{8}$)"
+    ); // 中国联通
+    // 手机段:130,131,132,145,146[卫星通信],155,156,166,171,175,176,185,186
+    var isChinaTelcom = new RegExp("(^1(33|49|53|7[347]|8[019]|99)\\d{8}$)"); // 中国电信
+    // 手机段:133,149,153,173,174,177,180,181,189,199
+    var isOtherTelphone = new RegExp("(^170\\d{8}$)");
+    // 虚拟运营商170号段
+    if (isChinaMobile.test(account)) {
+      return true;
+    } else if (isChinaUnicom.test(account)) {
+      return true;
+    } else if (isChinaTelcom.test(account)) {
+      return true;
+    } else return isOtherTelphone.test(account);
+  }
+//验证邮箱的正则
+export const patternEmail = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/

+ 84 - 34
src/views/Home.vue

@@ -7,13 +7,13 @@
           <img
             class="logo"
             v-if="!isCollapse"
-            src="~@/assets/img/home/logo.png"
+            :src="$setting.g_logo"
           />
           <!-- 折叠侧边栏logo尺寸 -->
           <img
             class="logo_coll"
             v-else
-            src="~@/assets/img/home/eta_mini.png"
+            :src="$setting.g_mini_logo"
           />
         </div>
         <div
@@ -243,6 +243,10 @@
                     >
                   </el-dropdown-menu>
                 </el-dropdown>
+                <div class="userinfo-fingerpost">
+                  <img src="~@/assets/img/questionnaire.png" v-if="isQuestionShow" @click="showQuestionDia=true"
+                style="width: 84px;height: 24; cursor: pointer;" />
+                </div>
               </div>
 
               <el-dropdown trigger="click" style="width:130px;">
@@ -292,7 +296,9 @@
 
     <!-- //重置初始密码 -->
     <pwd-dlg :dialogVisiblePwd="dialogVisiblePwd" />
-    
+    <!-- 问卷调查弹窗 -->
+    <questionnaire-dia :dialogVisiblePwd.sync="showQuestionDia" @submitSuccess="questionSubmitSuccess"
+    :questionList="questionList"></questionnaire-dia>
   </div>
 </template>
 
@@ -303,15 +309,21 @@ import {
   customInterence,
   roadshowInterence,
   getBusinessCode,
+  homeInterface
 } from "api/api.js";
 import { getPublicSettingsApi } from '@/api/modules/oldApi';
 import PwdDlg from "@/components/pwdDlg.vue";
 import questionMsgDia from "@/components/questionMsgDia.vue";
+import questionnaireDia from "../components/questionnaireDia.vue";
 import EventBus from "@/api/bus.js";
+
+import {recordActiveLoginFun,loginEndCalc} from "@/utils/TimeOnPage.js"
+
 export default {
   components: {
     PwdDlg,
     questionMsgDia,
+    questionnaireDia,
   },
   inject: ["reload"],
   filters: {
@@ -371,7 +383,11 @@ export default {
         return this.permissionBtn.checkPermissionBtn(
             this.permissionBtn.baseConfigPermission.sysJump_updateLog
         )
-    }
+    },
+		// 是否是eta试用
+    isTrail(){
+			return this.$store.state.hasTrialUserPermisson
+		}
   },
   data() {
     return {
@@ -415,7 +431,12 @@ export default {
       flag2: false, //显示合同提示红点
       flag3: false, //显示用印提示红点
       dialogVisiblePwd: false, //初始密码的弹框
-
+      //  ----------------问卷调查弹窗
+      showQuestionDia:false,
+      // 问卷调查icon是否展示
+      isQuestionShow:false,
+      // 问题列表
+      questionList:[],
       flag4: false,
       flag5: false, //显示ETA试用相关的红点
       flag6: false, //显示出差相关的红点
@@ -443,6 +464,7 @@ export default {
 
       //链接系统
       linkSystems: this.$setting.linkSystems,
+      bus_code:"",
     };
   },
   created() {
@@ -456,6 +478,9 @@ export default {
       this.isShowApprovalNotice = true;
     }
     this.resetLinkSys()
+    this.getBusinessCodeFun()
+    
+    this.getQuestionStaus()
   },
   mounted() {
     if (sessionStorage.getItem("hasGetMenu")) {
@@ -467,6 +492,13 @@ export default {
     this.getPublicSettings();
   },
   methods: {
+    // 获取商家Code
+    getBusinessCodeFun(){
+      getBusinessCode().then(res=>{
+        if(res.Ret!==200) return 
+        this.bus_code = res.Data||''
+      })
+    },
     //判断是否为初始密码
     async isInitialPwd() {
       const res = await checkPwd();
@@ -637,7 +669,27 @@ export default {
         this.roadshowFeedbackList = Data;
       });
     },
-
+    // 获取用户的问卷调查状态
+    getQuestionStaus(){
+      if(!this.isTrail){
+        this.showQuestionDia=false
+        this.isQuestionShow=false
+        this.questionList=[]
+        return 
+      }
+      homeInterface.getQuestionnaireDetail().then(res=>{
+        // console.log(res);
+        if(res.Ret == 200){
+          this.showQuestionDia=!!res.Data.IsPopup && (!!res.Data.IsShow)
+          this.isQuestionShow = !!res.Data.IsShow
+          this.questionList = res.Data.Question.List || []
+        }
+      })
+    },
+    // 问卷提交成功
+    questionSubmitSuccess(){
+      this.isQuestionShow=false
+    },
     // 操作指南的跳转
     toOperation() {
       // this.$router.replace({name: '/fingerpost', params: {id: 1}})
@@ -646,16 +698,10 @@ export default {
       //   query: { contractid: this.contractId },
       // });
       // window.open(href, "_blank");
-      // 获取商家
-      getBusinessCode().then(res=>{
-        if(res.Ret!==200) return 
-        const bus_code = res.Data||''
-        //打开帮助文档
-        const href = `${process.env.VUE_APP_ETA_HELP_DOCS}?bus_code=${bus_code}`
-        console.log(href);
-        // const href = `http://192.168.77.13:3033/help/index?bus_code=${bus_code}`
-        window.open(href, "_blank");
-      })
+      //打开帮助文档
+      const href = `${process.env.VUE_APP_ETA_HELP_DOCS}?bus_code=${this.bus_code}`
+      // const href = `http://192.168.77.13:3033/help/index?bus_code=${this.bus_code}`
+      window.open(href, "_blank");
     },
     // 跳转去其他的系统
     async linkToOtherMS({path,key}) {
@@ -736,28 +782,32 @@ export default {
         type: "warning",
       })
         .then(() => {
-          localStorage.setItem("auth", "");
-          localStorage.setItem("userName", "");
-          localStorage.setItem("Role", "");
-          localStorage.setItem("RoleType", "");
-          localStorage.setItem("AdminId", "");
-          localStorage.setItem("AdminName", "");
-          localStorage.setItem("ManageType", "");
-          localStorage.setItem("RoleIdentity", "");
-          that.$router.push("/login");
+          if(this.isTrail){
+            // 结算活跃计时
+            loginEndCalc()
+            // 结算登录计时
+            recordActiveLoginFun()
+          }
+          setTimeout(() => {
+            // 退出登录时可能有一些请求需要发送或者处理
+            localStorage.setItem("auth", "");
+            localStorage.setItem("userName", "");
+            localStorage.setItem("Role", "");
+            localStorage.setItem("RoleType", "");
+            localStorage.setItem("AdminId", "");
+            localStorage.setItem("AdminName", "");
+            localStorage.setItem("ManageType", "");
+            localStorage.setItem("RoleIdentity", "");
+
+            that.$router.push("/login");
+          }, 10);
         })
         .catch(() => {});
     },
     toDoc(){
-        //获取商家code
-        getBusinessCode().then(res=>{
-            if(res.Ret!==200) return 
-            const bus_code = res.Data||''
-            //打开更新日志项目
-            const href = `${process.env.VUE_APP_ETA_DOCS}?bus_code=${bus_code}`
-            window.open(href, "_blank");
-        })
-        
+      //打开更新日志项目
+      const href = `${process.env.VUE_APP_ETA_DOCS}?bus_code=${this.bus_code}`
+      window.open(href, "_blank");
     },
     collapseHandle () {
       //折叠导航栏

+ 446 - 150
src/views/Login.vue

@@ -1,10 +1,10 @@
 <template>
-  <div id="login">
+	<div id="login">
 		<div id="login_wrapper">
       
-			<img class="login-bg" :src="$setting.login_bg" alt />
-      <img class="login-icon" :src="$setting.login_logo">
-			<el-form
+            <img class="login-bg" :src="$setting.login_bg" alt />
+            <img class="login-icon" :src="$setting.login_logo" />
+			<!-- <el-form
 				:model="ruleForm"
 				:rules="rules"
 				ref="ruleForm"
@@ -63,168 +63,464 @@
 						>登录</el-button
 					>
 				</el-form-item>
-			</el-form>
+			</el-form>  -->
+			<div class="login-box" id="login-container" v-if="activeModel!=='forgetPassModel'">
+				<span class="login-title">ETA — 让投研领先市场半步</span>
+				<el-tabs v-model="activeModel" @tab-click="handleClick">
+					<el-tab-pane label="账号登录" name="ordinaryModel">
+						<OrdinaryModel ref="ordinaryModel"
+							:loginCheck="loginCheck"
+							:accountCheck="accountCheck"
+							@clearnHint="clearnHint"
+							@changeModel="changeModel('forgetPassModel')"
+						/>
+					</el-tab-pane>
+					<el-tab-pane label="手机号登录" name="mobileModel">
+						<MobileModel ref="mobileModel"
+							:areaCode="areaCode"
+						/>
+					</el-tab-pane>
+					<el-tab-pane label="邮箱登录" name="emailModel">
+						<EmailModel ref="emailModel"/>
+					</el-tab-pane>
+				</el-tabs>
+				<el-button
+					type="primary"
+					size="medium"
+					@click.native="handleLogin"
+					:loading="logining"
+					class="submit_btn"
+					>登录</el-button>
+			</div>
+			<div class="login-box" v-else>
+				<ForgetPassModel 
+					ref="forgetPassModel"
+					:autoAccount="$refs.ordinaryModel?$refs.ordinaryModel.form.account:''"
+					@changeModel="changeModel('ordinaryModel')"/>
+			</div>
 		</div>
+		<!-- 验证弹窗 -->
+		<el-dialog
+			class="check-dialog"
+			:visible.sync="isCheckDialogShow"
+			:close-on-click-modal="false"
+			:modal-append-to-body="false"
+			width="30%"
+			@close="isCheckDialogShow = false"
+			>
+			<el-tabs v-model="checkActiveModel" @tab-click="handleClick">
+				<el-tab-pane label="手机号验证" name="checkMobileModel">
+						<MobileModel ref="checkMobileModel"
+							:areaCode="areaCode"
+						/>
+					</el-tab-pane>
+					<el-tab-pane label="邮箱验证" name="checkEmailModel">
+						<EmailModel ref="checkEmailModel"/>
+					</el-tab-pane>
+			</el-tabs>
+			<span slot="footer" class="dialog-footer">
+				<el-button 
+					type="primary" 
+					:loading="checkLogining"
+					@click="submitCheck">提 交</el-button>
+			</span>
+		</el-dialog>
 	</div>
 </template>
 
 <script>
-import { userLogin, departInterence } from "@/api/api.js";
+import { userLogin, departInterence,recordActiveLogin } from "@/api/api.js";
 import http from "@/api/http.js";
 import md5 from "@/utils/md5.js";
+
+import EmailModel from "./login_manage/EmailModel.vue";
+import ForgetPassModel from "./login_manage/ForgetPassModel.vue";
+import MobileModel from "./login_manage/MobileModel.vue";
+import OrdinaryModel from "./login_manage/OrdinaryModel.vue";
+
 export default {
+    components: { OrdinaryModel, MobileModel, EmailModel, ForgetPassModel },
   data() {
     return {
-      b: new http.Base64(),
-      logining: false, //登录loadding
-      ruleForm: {
-        account: "",
-        checkPass: "",
-      },
-      rules: {
-        account: [
-          {
-            required: true,
-            message: "请输入用户名",
-            trigger: "blur",
-          },
-        ],
-        checkPass: [
-          {
-            required: true,
-            message: "请输入密码",
-            trigger: "blur",
-          },
-        ],
-      },
-      checked: false, //是否保持登录状态
-      visible: true, //密码输入类型
-    };
-  },
-  created() {
-    this.keyupSubmit(); //回车登录
-    let userAccount = localStorage.getItem("account") || null;
-    let userCheckPass = localStorage.getItem("checkPass") || null;
-    if (userAccount) {
-      this.ruleForm.account = this.b.decode(userAccount);
-      this.ruleForm.checkPass = this.b.decode(userCheckPass);
-      this.checked = true;
-    }
-  },
-  methods: {
-    keyupSubmit() {
-      //回车登录
-      document.onkeydown = (e) => {
-        let keyval = window.event.keyCode;
-        if (keyval === 13) {
-          this.handleSubmit2();
-        }
-      };
+        b: new http.Base64(),
+        logining: false, //登录loadding
+        ruleForm: {
+            account: "",
+            checkPass: "",
+        },
+        rules: {
+            account: [
+            {
+                required: true,
+                message: "请输入用户名",
+                trigger: "blur",
+            },
+            ],
+            checkPass: [
+            {
+                required: true,
+                message: "请输入密码",
+                trigger: "blur",
+            },
+            ],
+        },
+        checked: false, //是否保持登录状态
+        visible: true, //密码输入类型
+
+        activeModel: 'ordinaryModel',
+        /* form check 错误提示标识*/
+        loginCheck:false, //账号或密码错误
+        accountCheck:false,//账号异常:多次输错密码、长时间未登录
+        accountForbidden:false,//账号被禁用
+        mobileCheck:false,//手机号未绑定
+        emailCheck:false,//邮箱未绑定
+        areaCode:[],
+
+        isCheckDialogShow:false,
+        checkActiveModel:'checkMobileModel'
+        };
     },
-    handleSubmit2() {
-      //登录
-      let that = this;
-      this.$refs.ruleForm.validate((valid) => {
-        if (valid) {
-          that.logining = true;
-          var loginParams = {
-            Username: that.ruleForm.account,
-            Password: md5.hex_md5(that.ruleForm.checkPass),
-            IsRemember: this.checked,
-          };
-          userLogin(loginParams).then(async (res) => {
-            if (res.Ret === 200) {
-              localStorage.setItem("auth", res.Data.Authorization);
-              localStorage.setItem("userName", res.Data.RealName);
-              localStorage.setItem("Role", res.Data.RoleTypeCode);
-              localStorage.setItem("RoleIdentity", res.Data.SysRoleTypeCode);
-              localStorage.setItem("RoleType", res.Data.ProductName);
-              localStorage.setItem("ManageType", res.Data.Authority);
-              localStorage.setItem("AdminId", res.Data.AdminId);
-              localStorage.setItem("AdminName", res.Data.AdminName);
-              if (this.checked) {
-                localStorage.setItem(
-                  "account",
-                  this.b.encode(this.ruleForm.account)
-                );
-                localStorage.setItem(
-                  "checkPass",
-                  this.b.encode(this.ruleForm.checkPass)
-                );
-              } else {
-                localStorage.removeItem("account");
-                localStorage.removeItem("checkPass");
-              }
+    created() {
+        this.keyupSubmit(); //回车登录
+        this.getPhoneCode();//获取手机号区号
+    },
+    mounted(){
+        this.getRememberedInfo()
+    },
+    methods: {
+        keyupSubmit() {
+            //回车登录
+            document.onkeydown = (e) => {
+                let keyval = window.event.keyCode;
+                if (keyval === 13) {
+                    //this.handleSubmit2();
+                    !this.logining&&this.handleLogin()
+                }
+            };
+        },
+        handleSubmit2() {
+            //登录
+            let that = this;
+            this.$refs.ruleForm.validate((valid) => {
+                if (valid) {
+                    that.logining = true;
+                    var loginParams = {
+                        Username: that.ruleForm.account,
+                        Password: md5.hex_md5(that.ruleForm.checkPass),
+                        IsRemember: this.checked,
+                    };
+                    userLogin(loginParams).then(async (res) => {
+                        if (res.Ret === 200) {
+                            localStorage.setItem("auth", res.Data.Authorization);
+                            localStorage.setItem("userName", res.Data.RealName);
+                            localStorage.setItem("Role", res.Data.RoleTypeCode);
+                            localStorage.setItem("RoleIdentity", res.Data.SysRoleTypeCode);
+                            localStorage.setItem("RoleType", res.Data.ProductName);
+                            localStorage.setItem("ManageType", res.Data.Authority);
+                            localStorage.setItem("AdminId", res.Data.AdminId);
+                            localStorage.setItem("AdminName", res.Data.AdminName);
+                            if (this.checked) {
+                                localStorage.setItem("account", this.b.encode(this.ruleForm.account));
+                                localStorage.setItem("checkPass", this.b.encode(this.ruleForm.checkPass));
+                            }
+                            else {
+                                localStorage.removeItem("account");
+                                localStorage.removeItem("checkPass");
+                            }
+                            let path = "";
+                            switch (res.Data.RoleTypeCode) {
+                                case "rai_researcher":
+                                case "ficc_researcher":
+                                case "researcher":
+                                    path = "/reportlist";
+                                    break;
+                                case "compliance": //合规
+                                    path = "/contractapprovallist";
+                                    break;
+                                case "special_researcher": //特邀研究员
+                                    path = "/dataList";
+                                    break;
+                                case "special_ficc_seller":
+                                    path = "/meetingCalendar";
+                                    break;
+                                default:
+                                    path = await this.getOtherRolePath("myCalendar");
+                            }
+                            this.$router.push({ path });
+                        }
+                        that.logining = false;
+                    });
+                }
+            });
+        },
+        changePass(value) {
+            //密码输入格式切换
+            this.visible = !(value === "show");
+        },
+        getOtherRolePath(pathVal) {
+            return departInterence.getMenu().then((res) => {
+                let resolvePath = "";
+                if (res.Ret === 200) {
+                    let menuList = res.Data.List || [];
+                    if (!menuList.length) {
+                        this.$message.error('该账号没有任何菜单权限,请联系管理员');
+                        return;
+                    }
+                    // 是否已经拿到菜单信息
+                    sessionStorage.setItem("hasGetMenu", "true");
+                    sessionStorage.setItem("MenuList", JSON.stringify(menuList));
+                    /* 是否有数据报表权限 */
+                    this.$store.commit("SET_DATA_AUTH", menuList.some((item) => item.name === "数据报表"));
+                    for (let i = 0; i < menuList.length; i++) {
+                        const arr = menuList[i].children || [];
+                        if (arr.some(it => it.path == pathVal)) {
+                            resolvePath = "/" + pathVal;
+                            break;
+                        }
+                    }
+                    return resolvePath || "/" + menuList[0].children[0].path;
+                }
+                return "/" + pathVal;
+            });
+        },
+        getPhoneCode(){
+            departInterence.getPhoneAreaCode().then(res=>{
+                if(res.Ret!==200) return 
+                this.areaCode = res.Data||[]
+            })
+        },
+        handleClick(tab) {
+            //调用对应model的init方法
+            this.$refs[tab.name]&&this.$refs[tab.name].modelInit()
+            this.$refs[tab.name]&&this.$refs[tab.name].$refs.modelForm.clearValidate()
+            if(tab.name==='ordinaryModel'){
+                this.$nextTick(()=>{
+                    this.getRememberedInfo()
+                })
+            }
+        },
+        changeModel(model){
+            this.activeModel = model
+            if(model!=='forgetPassModel'){
+                this.$nextTick(()=>{
+                    this.getRememberedInfo()
+                })
+            }
+        },
+        handleLogin(){
+            //先进行判空的表单验证
+            this.$refs[this.activeModel].$refs.modelForm.validate((valid)=>{
+                if(valid){
+                    this.logining = true
+                    //根据activeName 调用不同的登陆接口
+                    //账号密码
+                        if(this.activeModel==='ordinaryModel'){
+                            this.ordinaryModelLogin()
+                        }
+                    //手机号登录
+                        if(this.activeModel==='mobileModel'){
+                            this.mobileModelLogin()
+                        }
+                    //邮箱登录
+                        if(this.activeModel==='emailModel'){
+                            this.emailModelLogin()
+                        }
+                }
+            })
+        },
+        submitCheck(){
+            this.$refs[this.checkActiveModel].$refs.modelForm.validate((valid)=>{
+                if(valid){
+                    this.checkLogining = true
+                    if(this.checkActiveModel==='checkMobileModel'){
+                        this.mobileModelLogin('checkMobileModel')
+                    }else{
+                        this.emailModelLogin('checkEmailModel')
+                    }
+                }
+            })
+        },
+        ordinaryModelLogin(){
+            const {account,checkPass,checked} = this.$refs.ordinaryModel.form
+            departInterence.userLogin({
+                LoginType:1,
+                Username:account,
+                Password:md5.hex_md5(checkPass)
+            }).then(res=>{
+                //this.logining = false
+                //账号异常 将accountCheck置为true
+                if(res.Ret===4011){
+                    this.accountCheck = true
+                    this.isCheckDialogShow = true
+                    this.$nextTick(()=>{
+                        this.$refs[this.checkActiveModel].getCodePic()
+                    })
+                }
+                //账号密码错误 将loginCheck置为true
+                if(res.Ret===4012){
+                    this.loginCheck = true
+                }
+                if(res.Ret!==200){
+                    this.logining = false
+                    return 
+                }
+                //登录成功,若设置了保存密码,在localStorage内存储一个时间戳
+                if(checked){
+                    this.setLoginDate(1)
+                    localStorage.setItem("account", this.b.encode(account));
+                    localStorage.setItem("checkPass", this.b.encode(checkPass));
+                }else {
+                    this.setLoginDate(0)
+                    localStorage.removeItem("account");
+                    localStorage.removeItem("checkPass");
+                }
+                this.setLoginInfo(res)
+                this.loginSys(res)
+            })
+        },
+        mobileModelLogin(model='mobileModel'){
+            const {mobile,checkCode} = this.$refs[model].form
+            departInterence.userLogin({
+                LoginType:2,
+                Mobile:mobile,
+                VerifyCode:checkCode
+            }).then(res=>{
+                if(res.Ret!==200){
+                    //刷新图形验证码
+                    this.$refs[model].getCodePic()
+                    this.$refs[model].form.picCode = ''
+                    model==='mobileModel'&&(this.logining = false)
+                    model!=='mobileModel'&&(this.checkLogining = false)
+                    return
+                }
+                this.setLoginInfo(res)
+                this.loginSys(res)
+            })
+        },
+        emailModelLogin(model='emailModel'){
+            const {email,checkCode} = this.$refs[model].form
+            departInterence.userLogin({
+                LoginType:3,
+                Email:email,
+                VerifyCode:checkCode
+            }).then(res=>{
+                if(res.Ret!==200){
+                    //刷新图形验证码
+                    this.$refs[model].getCodePic()
+                    this.$refs[model].form.picCode = ''
+                    model==='emailModel'&&(this.logining = false)
+                    model!=='emailModel'&&(this.checkLogining = false)
+                    return
+                }
+                this.setLoginInfo(res)
+                this.loginSys(res)
+            })
+        },
+        clearnHint(){
+            this.loginCheck = false
+            this.accountCheck = false
+        },
+        setLoginDate(type){
+            if(type===0){
+                localStorage.removeItem('timeKey')
+            }else{
+                localStorage.setItem('timeKey',Date.now())
+            }
 
-              let path = "";
-              switch (res.Data.RoleTypeCode) {
+        },
+        //判断timeKey有没有过期,目前设定的是60天,也就是5184000秒
+        checkTimeKey(timeKey){
+            const nowKey = Date.now()
+            return Math.floor((nowKey-timeKey)/1000)<5184000
+        },
+        //存储登录的信息
+        setLoginInfo(res){
+            localStorage.setItem("auth", res.Data.Authorization);
+            localStorage.setItem("userName", res.Data.RealName);
+            localStorage.setItem("Role", res.Data.RoleTypeCode);
+            localStorage.setItem("RoleIdentity", res.Data.SysRoleTypeCode);
+            localStorage.setItem("RoleType", res.Data.ProductName);
+            localStorage.setItem("ManageType", res.Data.Authority);
+            localStorage.setItem("AdminId", res.Data.AdminId);
+            localStorage.setItem("AdminName", res.Data.AdminName);
+        },
+        //根据角色判断应该进入系统的哪个页面,进入系统
+        async loginSys(res){
+            let path = ''
+            switch (res.Data.RoleTypeCode) {
                 case "rai_researcher":
                 case "ficc_researcher":
                 case "researcher":
-                  path = "/reportlist";
-                  break;
+                    path = "/reportlist";
+                    break;
                 case "compliance": //合规
-                  path = "/contractapprovallist";
-                  break;
+                    path = "/contractapprovallist";
+                    break;
                 case "special_researcher": //特邀研究员
-                  path = "/dataList";
-                  break;
+                    path = "/dataList";
+                    break;
                 case "special_ficc_seller":
-                  path = "/meetingCalendar";
-                  break;
+                    path = "/meetingCalendar";
+                    break;
                 default:
-                  path = await this.getOtherRolePath("myCalendar");
-              }
-              this.$router.push({ path });
+                    path = await this.getOtherRolePath("myCalendar");
             }
-            that.logining = false;
-          });
-        }
-      });
-    },
-    changePass(value) {
-      //密码输入格式切换
-      this.visible = !(value === "show");
-    },
-    getOtherRolePath(pathVal) {
-      return departInterence.getMenu().then((res) => {
-        let resolvePath = "";
-        if (res.Ret === 200) {
-          let menuList = res.Data.List || [];
-          if(!menuList.length){
-						this.$message.error('该账号没有任何菜单权限,请联系管理员')
-						return
-					}
-
-          // 是否已经拿到菜单信息
-          sessionStorage.setItem("hasGetMenu", "true");
-          sessionStorage.setItem("MenuList", JSON.stringify(menuList));
-          /* 是否有数据报表权限 */
-          this.$store.commit(
-            "SET_DATA_AUTH",
-            menuList.some((item) => item.name === "数据报表")
-          );
-
-          for (let i = 0; i < menuList.length; i++) {
-            const arr=menuList[i].children||[]
-						
-						if(arr.some(it => it.path == pathVal)){
-              resolvePath = "/" + pathVal;
-              break;
+            path&&this.$router.push({ path });
+            this.loading = false
+            this.checkLogining = false
+        },
+        //获取用户记住的账号密码 如果有
+        getRememberedInfo(){
+            const timeKey = localStorage.getItem("timeKey")
+            if(timeKey&&this.checkTimeKey(Number(timeKey))){
+                let userAccount = localStorage.getItem("account") || null;
+                let userCheckPass = localStorage.getItem("checkPass") || null;
+                if (userAccount) {
+                    this.$refs.ordinaryModel.form = {
+                        account:this.b.decode(userAccount),
+                        checkPass:this.b.decode(userCheckPass),
+                        checked:true
+                    }
+                }
             }
-          }
-          return resolvePath || "/" + menuList[0].children[0].path;
         }
-        return "/" + pathVal;
-      });
     },
-  },
-  destroyed() {
-    document.onkeydown = null;
-  },
+    destroyed() {
+        document.onkeydown = null;
+    }
 };
 </script>
 
+<style lang="scss">
+#login{
+	.el-tabs__nav {
+		width: 100%;
+		display: flex;
+	}
+	.el-tabs__item{
+		font-size: 18px;
+		flex: 1;
+		text-align: center;
+	}
+	.check-dialog{
+		.el-dialog{
+			border-radius: 8px;
+			.el-dialog__header{
+				background-color: transparent;
+				.el-dialog__headerbtn>i{
+					color: #C0C4CC;
+				}
+			}
+			.el-input{
+				width:100%;
+			}
+			.el-dialog__footer{
+				text-align: center;
+			}
+		}
+	}
+}
+</style>
 <style lang="scss" scoped>
 #login {
 	width: 100%;
@@ -250,22 +546,22 @@ export default {
 
 		.login-icon {
 			position: absolute;
-      top: 40px;
+			top: 40px;
 			right: 40px;
 		}
 		.login-title {
 			color: #333;
-			font-size: 30px;
+			font-size: 38px;
 			display: block;
-      text-align: center;
-			margin-bottom: 30px;
+			text-align: center;
+			margin-bottom: 60px;
 		}
 
-		#login-container {
+		#login-container ,.login-box{
 			box-sizing: border-box;
 			border-radius: 10px;
 			position: absolute;
-			top: 31%;
+			top: 27%;
 			right: 12%;
 			z-index: 100;
 			input::-webkit-input-placeholder {
@@ -276,7 +572,7 @@ export default {
 			}
 			.submit_btn {
 				width: 100%;
-				height: 60px;
+				height: 50px;
 				background: #3654C1;
 				font-size: 20px;
 				border-radius: 5px;
@@ -329,15 +625,15 @@ export default {
 			.login-bg{ 
 				display: block;
 			}
-			#login-container {
-				width: 31%;
+			#login-container ,.login-box{
+				width: 33%;
 			}
 		}
 		@media screen and (max-width: 1200px){
 			.login-bg{ 
 				display: none; 
 			}
-			#login-container {
+			#login-container ,.login-box{
 				width: 70%;
 			}
 		}

+ 8 - 16
src/views/chartRelevance_manage/components/chartCard.vue

@@ -7,7 +7,7 @@
       <div style="flex-shrink: 0">
         <template v-if="isHaveEdbHandle">
           <el-dropdown 
-            v-if="isEdbAdd" 
+            v-show="isEdbAdd" 
             split-button 
             type="primary" 
             @click="updateEdbHandle(entryType)" 
@@ -18,22 +18,22 @@
               <el-dropdown-item :command="{entryType,scence:'saveOther'}">指标另存为</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
-          <el-button type="primary" v-else @click="saveEdb(entryType)">保存指标</el-button>
+          <el-button type="primary" v-show="!isEdbAdd" @click="saveEdb(entryType)">保存指标</el-button>
         </template>
 
         <el-dropdown 
-          v-if="isChartAdd" 
+          v-show="isChartAdd" 
           split-button 
           type="primary" 
           @click="updateChartHandle(entryType)" 
           @command="chartCommandHandle"
         >
           更新
-          <el-dropdown-menu slot="dropdown" v-if="isHaveSaveOtherHandle">
+          <el-dropdown-menu slot="dropdown" v-show="isHaveSaveOtherHandle">
             <el-dropdown-item :command="{entryType,scence:'saveOther'}">另存为</el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
-        <el-button type="primary" @click="saveChart(entryType)" v-else>保存</el-button>
+        <el-button type="primary" @click="saveChart(entryType)" v-show="!isChartAdd">保存</el-button>
 
       </div>
     </div>
@@ -206,16 +206,7 @@ export default {
 
     /* 设置图表封面图片 */
     setChartImage(entryType,id) {
-      let otherOptions = this.chartInfo.Source===3 ? {
-        chart: {
-          width:340,
-          height:230,
-        },
-        xAxis:[{
-          ...this.options.xAxis,
-          offset: -65,
-        }]//这里记得要写成你渲染的图的配置项一样的 单独就配置一个offset无效
-      } : {
+      let otherOptions = {
         chart: {
           width:340,
           height:230,
@@ -265,7 +256,8 @@ export default {
       } 
 
       if(res.Ret !== 200) return
-
+      
+      this.setChartImage(entryType,res.Data.ChartInfoId)
       this.$message.success('更新成功');
     },
 

+ 8 - 0
src/views/chartRelevance_manage/fittingEquationChartEditor.vue

@@ -361,6 +361,14 @@ export default {
 	},
 	destroyed() {
 		window.removeEventListener('resize', this.reloadRightWid);
+	},
+	beforeRouteEnter(to, from, next) {
+		if(to.query.code){
+			to.matched[1].name='编辑图表'
+		}else{
+			to.matched[1].name='添加图表'
+		}
+		next()
 	}
 };
 </script>

+ 2 - 2
src/views/chartRelevance_manage/fittingEquationList.vue

@@ -392,7 +392,7 @@ export default {
 
 		/* 添加一级目录 */
 		addLevelOneHandle() {
-			this.dialog_title = '添加';
+			this.dialog_title = '添加图表分类';
 			this.classifyForm = {
 				classify_name: '',
 			}
@@ -402,7 +402,7 @@ export default {
     /* 编辑节点 */
     editNode(node, { ChartClassifyName,ChartClassifyId }) {
 
-      this.dialog_title = '编辑';
+      this.dialog_title = '编辑图表分类';
       /* 编辑目录 */
       this.classifyForm = {
         classify_name: ChartClassifyName,

+ 2 - 2
src/views/chartRelevance_manage/list.vue

@@ -464,7 +464,7 @@ export default {
 
     /* 添加一级目录 */
     addLevelOneHandle() {
-      this.dialog_title = "添加";
+      this.dialog_title = "添加图表分类";
       this.classifyForm = {
         classify_name: "",
       };
@@ -473,7 +473,7 @@ export default {
 
     /* 编辑节点 */
     editNode(node, { ChartClassifyName, ChartClassifyId }) {
-      this.dialog_title = "编辑";
+      this.dialog_title = "编辑图表分类";
       /* 编辑目录 */
       this.classifyForm = {
         classify_name: ChartClassifyName,

+ 8 - 0
src/views/chartRelevance_manage/relevanceChartEditor.vue

@@ -398,6 +398,14 @@ export default {
       };
     },
   },
+  beforeRouteEnter(to, from, next) {
+    if(to.query.code){
+      to.matched[1].name='编辑图表'
+    }else{
+      to.matched[1].name='添加图表'
+    }
+    next()
+  },
   data() {
     return {
       chart_code: this.$route.query.code || '',

+ 8 - 0
src/views/chartRelevance_manage/statisticFeatureChartEditor.vue

@@ -586,6 +586,14 @@ export default {
   },
   destroyed() {
     window.removeEventListener('resize', this.reloadRightWid);
+  },
+  beforeRouteEnter(to, from, next) {
+    if(to.query.code){
+      to.matched[1].name='编辑图表'
+    }else{
+      to.matched[1].name='添加图表'
+    }
+    next()
   }
 };
 </script>

+ 2 - 2
src/views/chartRelevance_manage/statisticFeatureList.vue

@@ -371,7 +371,7 @@ export default {
 
 		/* 添加一级目录 */
 		addLevelOneHandle() {
-			this.dialog_title = '添加';
+			this.dialog_title = '添加图表分类';
 			this.classifyForm = {
 				classify_name: '',
 			}
@@ -381,7 +381,7 @@ export default {
     /* 编辑节点 */
     editNode(node, { ChartClassifyName,ChartClassifyId }) {
 
-      this.dialog_title = '编辑';
+      this.dialog_title = '编辑图表分类';
       /* 编辑目录 */
       this.classifyForm = {
         classify_name: ChartClassifyName,

+ 4 - 3
src/views/classify_manage/classifyEnlist.vue

@@ -176,7 +176,7 @@
       <reportVarietyEnSet ref="varietyIns" :checked="checkedVariety" v-if="showSetVariety" />
       </div>
       <div style="text-align:center;padding:10px 0 30px 0">
-        <el-button type="primary" plain @click="showSetVariety=false">取消</el-button>
+        <el-button type="primary" plain @click="showSetVariety=false;checkedVariety=[]">取消</el-button>
         <el-button type="primary" style="margin-left:20px" @click="handleSaveVariety">保存</el-button>
       </div>
     </el-dialog>
@@ -334,8 +334,9 @@ export default {
 
   methods: {
     handleShowSetVariety(item){
+      console.log(item.EnPermissions);
       this.activeItem=item
-      this.checkedVariety=item.EnPermissions||[]
+      this.checkedVariety=item.EnPermissions?JSON.parse(JSON.stringify(item.EnPermissions)):[]
       this.showSetVariety=true
     },
     handleSaveVariety(){
@@ -420,7 +421,7 @@ export default {
 
     editHandle({ClassifyName,Id,ParentId,Sort,ClassifyType}) {
       this.classifyForm = {
-        title: '编辑英文分类',
+        title: '编辑分类',
         show: true,
         classify_name: ClassifyName,
         parent_id: ParentId,

+ 2 - 2
src/views/classify_manage/classifylist.vue

@@ -63,10 +63,10 @@
 		  	</el-col>
 		</el-card>
 		<!-- 添加分类弹框 -->
-		<el-dialog :modal-append-to-body='false' :title="isadd?'新增分类':'编辑分类'" :visible.sync="aeDialog" :close-on-click-modal="false" :center="true" v-dialogDrag custom-class="dialogclassLog" width="700px">
+		<el-dialog :modal-append-to-body='false' :title="isadd?'添加分类':'编辑分类'" :visible.sync="aeDialog" :close-on-click-modal="false" :center="true" v-dialogDrag custom-class="dialogclassLog" width="700px">
 			<div slot="title" style="display:flex;alignItems:center;">
 				<img :src="isadd?$icons.add:$icons.edit" style="color:#fff;width:16px;height:16px;marginRight:5px;">
-				<span style="fontSize:16px;">{{isadd?'新增分类':'编辑分类'}}</span>
+				<span style="fontSize:16px;">{{isadd?'添加分类':'编辑分类'}}</span>
 			</div>
 			<el-form :model="aeForm" :rules="aerules" ref="aeForm" label-position="right" label-width="140px" class="demo-aeForm" id="login-container" @submit.native.prevent>
 				<el-form-item prop="classify_name" label="分类名称">

+ 23 - 10
src/views/dataEntry_manage/chartSetting.vue

@@ -896,7 +896,14 @@ export default {
           let node = document.getElementById(`node${this.select_node}`);
           let parent = document.getElementsByClassName('tree-cont')[0];
 
-          if(node.offsetTop > parent.offsetHeight) {
+          //parent可视区间:[scrollTop,scrollTop+offsetHeight]
+          //node位置:node.offsetTop
+          const overTop = node.offsetTop+node.clientHeight+15<parent.scrollTop
+          const overBottom = node.offsetTop+node.clientHeight+15>parent.scrollTop+parent.offsetHeight
+          if(overTop){
+              parent.scrollTop = node.offsetTop-30
+          }
+          if(overBottom){
             parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
           }
         },400)
@@ -2028,15 +2035,21 @@ export default {
       this.selected_chartid = id;
 
       //滚动到高亮节点位置
-			setTimeout(() => {
-        this.$refs.treeRef.setCurrentKey(this.select_node);
-        let node = document.getElementById(`node${this.select_node}`);
-        let parent = document.getElementsByClassName('tree-cont')[0];
-
-        if(node.offsetTop > parent.offsetHeight) {
-          parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
-        }
-      },400)
+        setTimeout(() => {
+            this.$refs.treeRef.setCurrentKey(this.select_node);
+            let node = document.getElementById(`node${this.select_node}`);
+            let parent = document.getElementsByClassName('tree-cont')[0];
+            //parent可视区间:[scrollTop,scrollTop+offsetHeight]
+            //node位置:node.offsetTop
+            const overTop = node.offsetTop+node.clientHeight+15<parent.scrollTop
+            const overBottom = node.offsetTop+node.clientHeight+15>parent.scrollTop+parent.offsetHeight
+            if(overTop){
+                parent.scrollTop = node.offsetTop-30
+            }
+            if(overBottom){
+                parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
+            }
+        },400)
     },
     
     /* 根据图表id 查找对象 */

+ 25 - 12
src/views/dataEntry_manage/codecount/index.vue

@@ -82,7 +82,20 @@
 							label-width="100px"
 						>
 							<el-form-item label="数据来源">
-								<el-select 
+
+								<el-cascader
+								v-model="fromType"
+								:options="allFromArr"
+								:props="{
+									label: 'SourceName',
+									value: 'EdbSourceId',
+									children: 'Child',
+									emitPath: false
+								}"
+								clearable
+								style="width:220px"
+								placeholder="请选择来源"/>
+								<!-- <el-select 
 								v-model="fromType" 
 								placeholder="请选择来源"
 								style="width:220px">
@@ -92,7 +105,7 @@
 										:label="item.name"
 										:value="item.key">
 									</el-option>
-								</el-select>
+								</el-select> -->
 							</el-form-item>
 							<el-form-item label="指标名称/ID">
 								<el-select
@@ -152,7 +165,7 @@
 import { dataBaseInterface } from '@/api/api.js';
 import { unitArr } from '@/utils/defaultOptions';
 import storage from '@/utils/storage.js';
-import { allFromArr } from '../databaseComponents/util';
+// import { allFromArr } from '../databaseComponents/util';
 import codeMirror from './compoments/codeMirror';
 import dataTable from './compoments/dataTable';
 import { mapState } from 'vuex';
@@ -170,7 +183,7 @@ export default {
 			formData: {},
 			fromType:"",
 			unitArr,
-			allFromArr,//所有指标来源
+			allFromArr:[],//所有指标来源
 			frequencyArr:['日度','周度','旬度','月度','季度','年度'],
 			menuOptions:[],//目录数组
 
@@ -405,16 +418,16 @@ export default {
 			this.searchApi(this.current_search,++this.search_page);
 		},
 		getTargetSource(){
-			this.allFromArr = []
-			dataBaseInterface.getDataSource().then(res=>{
+			dataBaseInterface.getCodecountEdbSources().then(res=>{
 				if(res.Ret!==200) return
 				if(res.Data){
-					this.allFromArr = res.Data.map(i=>{
-						return {
-							name:i.SourceName,
-							key:i.EdbSourceId
-						}
-					})
+					this.allFromArr = res.Data.map(_ => ({
+						..._,
+						Child: _.Child.map(_item => ({
+							..._item,
+							Child:null
+						}))
+					}))
 				}
 			})
 		}

+ 1 - 1
src/views/dataEntry_manage/databaseComponents/addTargetDiaBase.vue

@@ -4,7 +4,7 @@
 			@close="cancelHandle" custom-class="dialog" top="11vh" center width="1200px" v-dialogDrag>
 			<div slot="title" style="display:flex;alignItems:center;">
 				<img :src="$icons.add" style="color:#fff;width:16px;height:16px;marginRight:5px;">
-				<span style="fontSize:16px;">新增指标</span>
+				<span style="fontSize:16px;">添加指标</span>
 			</div>
 			<div class="dialog-top">
 				<div>

+ 780 - 0
src/views/dataEntry_manage/databaseComponents/chartTrendRender.vue

@@ -0,0 +1,780 @@
+<template>
+	<div class="chart-trend-render">
+		<div class="header">
+			<template v-if="chart_type===1">
+				<el-button
+					type="primary"
+					v-for="item in yearSelector"
+					:key="item.value"
+					size="mini"
+					:plain="item.value !== year_select"
+					class="year-btn"
+					@click.native="changeYear(item)"
+					>{{ item.name }}</el-button
+				>
+				<el-button type="primary" plain size="mini" class="btn-sty" @click="openDateDia">{{
+					dateTip
+				}}</el-button>
+				<el-button type="primary" plain size="mini" class="btn-sty" @click="showOnChart('toggle')" v-if="!isOnlyShowBaseChart">
+					<!-- <i class="el-icon-view"></i> -->
+					{{ isShowOnyearData ? '隐藏同比图' : '展示同比图'}}
+				</el-button>
+			</template>
+			<!-- 季节图时间选择 -->
+			<template v-else-if="chart_type===2">
+				<date-picker
+						v-model="season_year"
+						type="month"
+						value-type="format"
+						range
+						placeholder="年份日期选择"
+						@change="getDataByPath"
+				/>
+			</template>
+			<el-button type="primary" plain size="mini" class="btn-sty" style="margin-left:auto;"
+				@click="chartTypeChange" v-if="!isOnlyShowBaseChart">
+				<i class="el-icon-sort" style="transform: rotate(90deg);"></i>
+				切换{{chart_type==1?'季节性图':'曲线图'}}
+			</el-button>
+		</div>
+		<div class="min-wrapper">
+			<div class="chartWrapper" id="chartWrapper" v-if="showChart">
+				<Chart :options="options" ref="chartRef" @clickYAxisTitle="clickYAxisTitle"/>
+				<div class="range-cont left" v-if="leftIndex != -1">
+					<el-input
+						style="width: 80px; display: block"
+						size="mini"
+						type="number"
+						placeholder="上限"
+						v-model="chartInfo.MaxValue"
+						@change="() => { chart_type===1?setOptions():setSeasonOptions() }"
+					/>
+					<el-input
+						class="min-data-input"
+						size="mini"
+						type="number"
+						placeholder="下限"
+						v-model="chartInfo.MinValue"
+						@change="() => { chart_type===1?setOptions():setSeasonOptions() }"
+					/>
+				</div>
+				<div class="range-cont right" v-if="isShowOnyearData">
+					<el-input
+						style="width: 80px; display: block"
+						size="mini"
+						type="number"
+						placeholder="上限"
+						v-model="limitData.rightMax"
+						@change="changeLimit"
+					/>
+					<el-input
+						class="min-data-input"
+						size="mini"
+						type="number"
+						placeholder="下限"
+						v-model="limitData.rightMin"
+						@change="changeLimit"
+					/>
+				</div>
+				<!-- 公历农历切换 只用于季节性图 -->
+				<div style="text-align:center;">
+					<el-radio-group
+							v-model="calendar_type"
+							class="calendar-cont"
+							v-if="chart_type===2"
+							@change="getDataByPath"
+					>
+							<el-radio-button label="公历" />
+							<el-radio-button label="农历" />
+					</el-radio-group>
+				</div>
+			</div>
+		</div>
+		<div class="table-data">
+
+		</div>
+		<!-- 自定义时间段选择弹窗 -->
+		<DateChooseDia
+			:isDateDia="isDateDia"
+			:dateForm="dateForm"
+			@cancel="isDateDia = false"
+			@dateBack="dataChangeBack"
+		/>
+	</div>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import * as supplyApi from '@/api/modules/supplyApi.js';
+import { yearSelector,defaultOpts,seasonOptions } from '@/utils/defaultOptions'
+import Chart from '../components/chart'
+import DateChooseDia from '../components/DateChooseDia';
+import Highcharts from 'highcharts'
+export default {
+	components: { Chart,DateChooseDia },
+	props: {
+		edbid: {
+			type: Number,
+		},
+		// 语言 ch/en
+		chartLang:{
+			type: String,
+			default:()=> 'ch'
+		}
+	},
+	computed: {
+
+		// 同比,环比,环差,超季节性、 残差展示基础图
+		isOnlyShowBaseChart() {
+			return [6,12,13,35,37].includes(this.chartInfo.Source)
+		}
+	},
+	watch: {
+		edbid:{
+			handler(newVal){
+				console.log('??')
+				if(newVal){
+					this.chart_type = 1
+					this.isShowOnyearData = false
+					this.getDataByPath()
+				}
+			},
+			immediate:true
+		}
+	},
+	data () {
+		return {
+			year_select: 10, //年份选择项 默认全部
+			yearSelector: [
+				{
+					name: '全部',
+					value: 10,
+				},
+				...yearSelector,
+			],
+			select_date: [], // 自定义时间段项
+
+			options: {},
+			showChart: false,
+			chart_type: 1,// 1曲线 2季节
+			isShowOnyearData: false, //是否展示同比
+			chartInfo: {},
+			dataList: [],
+			leftIndex: 0,
+
+			season_year:[],//季节图日期选择
+			calendar_type:'公历',
+
+			/* 日期弹窗 */
+			isDateDia: false, // 时间段弹窗
+			dateForm: {},
+			dateTip: '请选择时间段',
+			limitData: {
+				letMin: 0,
+				leftMax: 0,
+				rightMin: 0,
+				rightMax: 0,
+			},
+			oldOptions: {
+				MinValue: 0,
+				MaxValue: 0
+			},
+		};
+	},
+	methods: {
+		
+		getDataByPath() {
+			const apiMap = {
+				'/database': this.getEdbData,
+				'/analyseVariety': this.getPlantEdbData
+			}
+
+			apiMap[this.$route.path]()
+		},
+
+		/* 获取指标所有数据 */
+		async getEdbData() {
+			let params = {
+				EdbInfoId: this.edbid,
+				DateType: this.year_select,
+				StartDate: this.select_date[0] || '',
+				EndDate: this.select_date[1] || ''
+			}
+
+			const res = this.chart_type === 1 
+				? await dataBaseInterface.ebd_data(params)
+				: await dataBaseInterface.ebdSeasonData({
+						EdbInfoId: this.edbid,
+						Calendar: this.calendar_type,
+						StartDate: this.season_year[0] || '',
+						EndDate: this.season_year[1] || '',
+					})
+				
+				if(res.Ret !== 200) return
+					const { DataList,EdbInfo } = res.Data;
+					// DataList 表格数据列表
+					this.chartInfo = (this.oldOptions.MinValue || this.oldOptions.MaxValue) ? {
+						...EdbInfo,
+						...this.oldOptions
+					} : EdbInfo;
+					this.tableData = DataList || [];
+
+					this.chart_type === 1 ? this.setOptions() : this.setSeasonOptions();
+					this.showChart = true;
+					this.$nextTick(()=>{
+						if(!EdbInfo.ChartImage){
+							//设置图表缩略图
+							this.saveEdbImg(EdbInfo)
+						}
+					})
+		},
+		//保存指标缩略图
+		async saveEdbImg(EdbInfo){
+			let svg = this.$refs.chartRef.chart.getSVG({
+				chart: {
+					width: 340,
+					height: 230,
+				},
+			});
+			let form = new FormData();
+			form.append("Img", svg);
+			let { Data } = await dataBaseInterface.uploadImgSvg(form);
+			await dataBaseInterface.saveEdbChartImg({
+				EdbInfoId: EdbInfo.EdbInfoId,
+				ImageUrl: Data.ResourceUrl,
+			});
+		},
+
+		/* 获取装置指标数据 */
+		async getPlantEdbData() {
+			let params = {
+				VarietyEdbId: this.edbid,
+				DateType: this.year_select,
+				StartDate: this.select_date[0] || '',
+				EndDate: this.select_date[1] || ''
+			}
+
+			const res = this.chart_type === 1 
+				? await supplyApi.getEdbDetailData(params)
+				: await supplyApi.getEdbSeasonData({
+						VarietyEdbId: this.edbid,
+						Calendar: this.calendar_type,
+						StartDate: this.season_year[0] || '',
+						EndDate: this.season_year[1] || '',
+					})
+				
+				if(res.Ret !== 200) return
+					const { DataList,EdbInfo } = res.Data;
+					// DataList 表格数据列表
+					this.chartInfo = (this.oldOptions.MinValue || this.oldOptions.MinValue) ? {
+						...EdbInfo,
+						...this.oldOptions
+					} : EdbInfo;
+					this.tableData = DataList || [];
+
+					this.chart_type === 1 ? this.setOptions() : this.setSeasonOptions();
+					this.showChart = true;
+		},
+
+		 /* 年份改变 重新刷新图表接口  保存当前的图表配置和上下限 只改变图表 */
+    changeYear(item) {
+      this.year_select = item.value;
+      this.select_date = [];
+      this.dateTip = '请选择时间段';
+
+			const { MinValue,MaxValue } = this.chartInfo;
+			this.oldOptions = {
+				MinValue: Number(MinValue),
+				MaxValue: Number(MaxValue)
+			}
+      this.getDataByPath()
+    },
+
+		/* 打开时间段弹窗 */
+    openDateDia() {
+      // 自定义时间段回显
+      this.dateForm = {
+        date_type: this.year_select,
+        start_date:
+          this.year_select === 5 || this.year_select === 6
+            ? this.select_date[0]
+            : '',
+        end_date: this.year_select === 5 ? this.select_date[1] : '',
+      };
+      this.isDateDia = true;
+    },
+
+    /* 保存完自定义日期 刷新数据 保存当前的图表配置和上下限 只改变图表*/
+    dataChangeBack(data) {
+      this.year_select = data.dateType;
+      this.isDateDia = false;
+      this.select_date = [data.start_date, data.end_date];
+
+      this.dateTip =
+        data.dateType === 5
+          ? `${data.start_date}~${data.end_date}`
+          : `${data.start_date}~至今`;
+
+			const { MinValue,MaxValue } = this.chartInfo;
+			this.oldOptions = {
+				MinValue,
+				MaxValue
+			}
+      this.getDataByPath();
+    },
+
+		chartTypeChange() {
+			this.chart_type = this.chart_type===1 ? 2 : 1;
+			this.init('no_reset')
+			this.getDataByPath();
+		},
+
+		// 展示同比图
+		async showOnChart(scene='') {
+			if(scene==='toggle') {
+				this.isShowOnyearData = this.isShowOnyearData ? false : true;
+				if(!this.isShowOnyearData){
+					const { MinValue,MaxValue } = this.chartInfo;
+					this.oldOptions = {
+						MinValue: Number(MinValue),
+						MaxValue: Number(MaxValue)
+					}
+					this.getDataByPath();
+				}  
+			}
+			if(!this.isShowOnyearData) return;
+
+			let params = {
+				DateType: this.year_select,
+				StartDate: this.select_date[0] || '',
+				EndDate: this.select_date[1] || ''
+			}
+			const res = this.$route.path === '/analyseVariety' 
+				? await supplyApi.getEdbOnyearData({VarietyEdbId:this.edbid,...params})
+				: await dataBaseInterface.edbOnyearData({EdbInfoId: this.edbid,...params});
+
+			if(res.Ret !== 200) return
+
+			const { EdbInfo,DataList } = res.Data;
+
+			if(!this.limitData.rightMin && !this.limitData.rightMax) {
+				this.limitData.rightMin = Number(EdbInfo.MinValue);
+				this.limitData.rightMax = Number(EdbInfo.MaxValue);
+			}
+
+			this.options.yAxis.push({
+				title: {
+					text: '',
+					align: 'high',
+					rotation: 0,
+					y: -15,
+					offset: 0
+				},
+				labels: {
+					formatter: function (ctx) {
+						return ctx.value;
+					},
+					align: 'center',
+				},
+				min: Number(this.limitData.rightMin),
+				max: Number(this.limitData.rightMax),
+				...seasonOptions.yAxis,
+				opposite: true,
+			})
+
+			this.options.series.push({
+				data: DataList.map(item=>([item.DataTimestamp, item.Value])),
+				type: 'spline',
+				yAxis: 1,
+				name: this.chartLang=='ch'?`${EdbInfo.EdbName}同比`:EdbInfo.EdbNameEn?`${EdbInfo.EdbNameEn}同比`:'无英文名称',
+				lineWidth: 1
+			})
+			console.log(this.options.series)
+		},
+
+		changeLimit() {
+			const { rightMax,rightMin } = this.limitData;
+			this.options.yAxis[1].max = Number(rightMax);
+			this.options.yAxis[1].min = Number(rightMin);
+
+		},
+
+		/* 图表配置 曲线*/
+		setOptions() {
+			const chartData = _.cloneDeep(this.tableData);
+
+      //拼接标题 数据列
+      let data = [],
+        ydata = [];
+
+			//y轴
+
+			// 单位 中文时 为无不显示   英文时 为空提示点击输入
+			// 中文不存在或等于无时 英文显示为空  中文存在且英文不存在时 显示'英文单位'
+			let yTitleText = this.chartLang=='ch'?
+			(this.chartInfo.Unit && this.chartInfo.Unit!='无') ? this.chartInfo.Unit:'':
+			!this.chartInfo.UnitEn && this.chartInfo.Unit && this.chartInfo.Unit!='无' ? '英文单位':this.chartInfo.UnitEn
+			// title样式  英文为空时,提示文字样式  英文可以点击设置
+			let yTitleStyle = {}
+			if(this.chartLang=='en'){
+				yTitleStyle.cursor='pointer'
+				if(yTitleText=='英文单位'){
+					yTitleStyle.color="#999"
+				}
+			}
+			let yItem = {
+				title: {
+					text: yTitleText,
+					align: 'high',
+					rotation: 0,
+					y: -15,
+					offset: 0,
+					style:yTitleStyle
+				},
+				labels: {
+					formatter: function (ctx) {
+						return ctx.value;
+					},
+					align: 'center',
+				},
+				min: Number(this.chartInfo.MinValue),
+				max: Number(this.chartInfo.MaxValue),
+				...seasonOptions.yAxis,
+			};
+			// 图例名称和图例文字样式
+			let dataName = this.chartLang=='ch'?this.chartInfo.EdbName:this.chartInfo.EdbNameEn?this.chartInfo.EdbNameEn:'无英文名称'
+			let color = this.chartLang=='en'&&(!this.chartInfo.EdbNameEn)?'#999':'#333'
+			let legend={
+				...defaultOpts.legend,
+				itemStyle: {
+					color
+				},
+			}
+			//数据列
+			let obj = {
+				data: [],
+				type: 'spline',
+				yAxis: 0,
+				name: dataName,
+				lineWidth: 3
+			};
+			chartData.forEach((item, index) => {
+				obj.data.push([item.DataTimestamp, item.Value]);
+			});
+			
+			data.push(obj);
+			ydata.push(yItem);
+
+      // 范围为1年内 x轴显示为月/日 否则默认年/月
+      let xAxis = {};
+      const bool_time = this.xTimeDiffer();
+      xAxis = bool_time
+        ? {
+            ...defaultOpts.xAxis,
+            labels: {
+              formatter: function (ctx) {
+                return Highcharts.dateFormat('%m/%d', ctx.value);
+              },
+            },
+          }
+        : {
+            ...defaultOpts.xAxis,
+						labels: {
+              formatter: function (ctx) {
+                return Highcharts.dateFormat('%y/%m', ctx.value);
+              },
+            },
+          };
+      this.options = {
+        series: data,
+        yAxis: ydata,
+        xAxis,
+				legend
+      };
+
+			this.showOnChart();
+		},
+
+		/* 季节图 */
+		setSeasonOptions() {
+			console.log(this.tableData)
+      const chartData = _.cloneDeep(this.tableData);
+      let seasonYdata = [],
+        seasonData = [];
+
+        /* 公历数据处理 处理数据列 y轴 */
+        if (this.calendar_type === '公历')
+        for (let j of chartData) {
+          
+          let serie_item = {
+            data: [],
+            type: 'spline',
+            yAxis: 0,
+            name: j.Year,
+          };
+          const data_array = _.cloneDeep(j.DataList);
+          data_array &&
+            data_array.forEach((item) => {
+              serie_item.data.push([item.DataTimestamp, item.Value]);
+            });
+          const index = chartData.findIndex(
+            (item) => item.Year === j.Year
+          );
+          const s_yItem = {
+            labels: {
+              formatter: function () {
+                let val = this.value;
+                return index !== 0 ? '' : val;
+              },
+              align: 'center',
+            },
+            title: {
+              text:  this.chartLang=='ch'?this.chartInfo.Unit:
+							!this.chartInfo.UnitEn && this.chartInfo.Unit && this.chartInfo.Unit!='无' ? '英文单位':this.chartInfo.UnitEn,
+              align: 'high',
+              rotation: 0,
+              y: -15,
+              offset: -(12 * this.chartInfo.Unit.length),
+            },
+            max: Number(this.chartInfo.MaxValue),
+            min: Number(this.chartInfo.MinValue),
+            ...seasonOptions.yAxis,
+          };
+          seasonData.push(serie_item);
+          seasonYdata.push(s_yItem);
+        }
+
+      /* 农历数据处理  */
+      let filterArr =
+        this.calendar_type === '农历'
+          ? chartData.List.filter((item, index) => index > 0)
+          : [];
+      if (this.calendar_type === '农历')
+        for (let j of filterArr) {
+
+          let serie_item = {
+            data: [],
+            type: 'spline',
+            yAxis: 0,
+            name: j.Year
+          };
+          const data_array = _.cloneDeep(j.Items);
+          data_array &&
+            data_array.forEach((item) => {
+              serie_item.data.push([item.DataTimestamp, item.Value]);
+            });
+          const index = filterArr.findIndex((item) => item.Year === j.Year);
+          const s_yItem = {
+            labels: {
+              formatter: function () {
+                let val = this.value;
+                return index !== 0 ? '' : val;
+              },
+              align: 'center',
+            },
+            title: {
+              text:  this.chartLang=='ch'?this.chartInfo.Unit:
+							!this.chartInfo.UnitEn && this.chartInfo.Unit && this.chartInfo.Unit!='无' ? '英文单位':this.chartInfo.UnitEn,
+              align: 'high',
+              rotation: 0,
+              y: -15,
+              offset: -(12 * this.chartInfo.Unit.length),
+            },
+            max: Number(this.chartInfo.MaxValue),
+            min: Number(this.chartInfo.MinValue),
+            ...seasonOptions.yAxis,
+          };
+          seasonData.push(serie_item);
+          seasonYdata.push(s_yItem);
+        }
+
+      /* x轴显示月日  提示框显示月日*/
+      defaultOpts.xAxis.labels = {
+        formatter: function () {
+          return Highcharts.dateFormat('%m/%d', this.value);
+        },
+      };
+      
+      const tooltip = {
+        ...defaultOpts.tooltip,
+        dateTimeLabelFormats: {
+          // 时间格式化字符
+          day: '%m/%d',
+          week: '%m/%d',
+          month: '%m/%d',
+          year: '%m/%d',
+        },
+        xDateFormat: '%m/%d',
+      }
+      let rangeSelector =
+        this.calendar_type === '农历'
+          ? {
+              enabled: true,
+              selected: 0,
+              inputStyle: {
+                display: 'none',
+              },
+              labelStyle: {
+                display: 'none',
+              },
+              buttonTheme: {
+                style: {
+                  display: 'none',
+                },
+              },
+              buttons: [
+                {
+                  type: 'month',
+                  count: 12,
+                  text: '12月',
+                },
+                {
+                  type: 'month',
+                  count: 15,
+                  text: '15月',
+                },
+                {
+                  type: 'all',
+                  text: '全部',
+                  type: 'all',
+                },
+              ],
+            }
+          : {
+              enabled: false,
+            };
+
+      this.options = {
+        colors:
+          this.calendar_type === '公历'
+            ? seasonOptions.colors.slice(-chartData.length)
+            : seasonOptions.colors.slice(-filterArr.length),
+        series: seasonData,
+        yAxis: seasonYdata,
+        rangeSelector,
+        tooltip
+      };
+			console.log(this.options)
+		},
+
+	  /* 查询范围为1年内 x轴显示为月/日 否则默认年/月 */
+    xTimeDiffer() {
+      const end_date =
+        this.year_select === 5
+          ? this.select_date[1]
+          : this.year_select === 6
+          ? new Date()
+          : '';
+      //年限差
+      const year_differ = this.$moment(end_date).diff(
+        this.$moment(this.select_date[0]),
+        'years',
+        true
+      );
+      // console.log(year_differ)
+      if ([5, 6].includes(this.year_select) && year_differ <= 1) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+
+		init(type='') {
+			if(type!=='no_reset') this.chart_type = 1;
+			this.isShowOnyearData = false;
+			this.year_select = 10;
+			this.select_date = [];
+			this.options = {};
+			this.dateTip = '请选择时间段';
+			this.oldOptions = {};
+			this.calendar_type = '公历';
+			this.season_year = [];
+			this.limitData = {
+				letMin: 0,
+				leftMax: 0,
+				rightMin: 0,
+				rightMax: 0,
+			}
+		},
+		// 编辑英文信息弹窗
+		editEnName(){
+			this.$emit('editEnName','chart')
+		},
+		// 竖轴标题点击事件
+		clickYAxisTitle(){
+			console.log(this.chartLang);
+			if(this.chartLang == 'en') this.editEnName()
+		}
+	},
+	created() {},
+	mounted() {},
+}
+</script>
+<style lang='scss'>
+.chart-trend-render {
+	width:100%;
+	box-sizing: border-box;
+	@media screen and (min-width: 1711px) {
+		.min-data-input { margin-top: 300px; }
+	}
+	@media screen and (max-width:1710px) {
+		.min-data-input { margin-top: 210px; }
+	}
+	.header {
+		display: flex;
+		position: relative;
+		.year-btn,.btn-sty {
+			min-width: 98px;
+			font-size: 14px;
+			margin-right: 5px;
+			margin-bottom: 5px;
+		}
+		.btn-sty {
+			background-color: #fff;
+			color: #0052D9;
+		}
+		.change-chart-btn{
+				float: right;
+				color: #409eff;
+				font-size: 16px;
+				cursor: pointer;
+				&::before{
+						content:'';
+						display: inline-block;
+						width: 18px;
+						height: 18px;
+						background-image: url('~@/assets/img/chart_m/change.png');
+						background-size: cover;
+						position: relative;
+						top: 4px;
+						right: 4px;
+				}
+		}
+	}
+	.min-wrapper {
+		.el-input__inner {
+			padding: 0 0 0 5px;
+		}
+		/* margin: 20px 0 0 0; */
+		min-height: 320px;
+		.chartWrapper {
+			position: relative;
+			padding: 0 105px 0 100px;
+			.range-cont {
+				position: absolute;
+				top: 8%;
+				.min-data-input {
+					width: 80px;
+					display: block;
+				}
+				&.left {
+					left: 0px;
+				}
+				&.right {
+					right: 0;
+				}
+			}
+		}
+	}
+}
+</style>

+ 1 - 1
src/views/dataEntry_manage/databaseComponents/createChart.vue

@@ -217,7 +217,7 @@ export default {
 				if(res.Ret !== 200) return
 					const { DataList,EdbInfo } = res.Data;
 					// DataList 表格数据列表
-					this.chartInfo = (this.oldOptions.MinValue || this.oldOptions.MinValue) ? {
+					this.chartInfo = (this.oldOptions.MinValue || this.oldOptions.MaxValue) ? {
 						...EdbInfo,
 						...this.oldOptions
 					} : EdbInfo;

+ 150 - 0
src/views/dataEntry_manage/databaseComponents/edbDetailData.vue

@@ -0,0 +1,150 @@
+<template>
+	<div class="edb-detail-data-wrap">
+		<el-table
+			:data="tableData"
+			class="firstColumTable" border>
+			<el-table-column
+				v-for="item in tableColumsOne"
+				:key="item.label"
+				:width="item.widthsty"
+				:min-width="item.minwidthsty"
+				align="center">
+				<template slot="header" slot-scope="scope">
+					<div class="chartEn-mark" style="top: -10px;" v-show="scope.$index ==0 && tableData[0] && tableData[0].IsEnEdb" >En</div>
+					<span>{{item.label}}</span>
+				</template>	
+				<template slot-scope="scope">
+					<span v-show="currentLang=='ch'">{{ scope.row[item.key] }}</span> 
+					<span v-show="currentLang=='en'">{{scope.row[item.enKey||item.key] || scope.row[item.key]}}</span>
+				</template>
+			</el-table-column>
+		</el-table>
+		<el-table
+			:data="tableData"
+			style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);"
+			border>
+			<el-table-column
+				v-for="item in tableColumsTwo"
+				:key="item.label"
+				:label="item.label"
+				:width="item.widthsty"
+				:min-width="item.minwidthsty"
+				align="center"
+			>
+				<template #header>
+					<span>{{ item.label }}</span>
+				</template>
+				<template slot-scope="scope">
+					<span>{{ scope.row[item.key] }}</span>
+				</template>
+			</el-table-column>
+			<div slot="empty" style="padding: 50px 0 320px;">
+					<tableNoData :text="defaultWarn"/>
+			</div>
+		</el-table>
+		<ul 
+			class="value-ul" 
+			ref="valueUl" 
+			@scroll="scrollHandle" 
+			v-show="dataList.length">
+			<li
+				class="value-item"
+				v-for="item in dataList"
+				:key="item.EdbDataId"
+			>
+				<span class="value-label">
+					<span style="position: relative;">
+						<i class="new-tag" v-if="tableData[0].LatestDate===item.DataTime"></i>
+						{{item.DataTime}}
+					</span>
+				</span>
+				<span :class="['value-label',{'predict-act': tableData[0].DataInsertConfig.Date===item.DataTime}]" style="min-width:200px;text-align:center;">
+					<span :class="['value-style',{'predict-act': tableData[0].DataInsertConfig.Date===item.DataTime}]">{{item.Value}}</span>
+				</span>
+			</li>
+			<li class="nodata value-item" v-if="!dataList.length">暂无数据</li>
+		</ul>
+	</div>
+</template>
+
+<script>
+export default {
+	props:{
+		currentLang:{
+			type:String,
+			default:'ch'
+		},
+		tableData:{
+			type:Array,
+			default:()=>{return []}
+		},
+		tableColumsOne:{
+			type:Array,
+			default:()=>{return []}
+		},
+		tableColumsTwo:{
+			type:Array,
+			default:()=>{return []}
+		},
+		defaultWarn:{
+			type:String,
+			default:'暂无数据'
+		},
+		dataList:{
+			type:Array,
+			default:()=>{return []}
+		},
+		haveMore:{
+			type:Boolean,
+			default:false
+		}
+	},
+	data() {
+		return {
+
+		};
+	},
+	methods: {
+		/* 数值滚动加载 */
+		scrollHandle: _.throttle(function() {
+			let scrollTop = this.$refs.valueUl.scrollTop;
+			let clientHeight = this.$refs.valueUl.clientHeight;
+			let scrollHeight = this.$refs.valueUl.scrollHeight;
+			if(scrollTop===0) return
+			if(scrollTop + clientHeight >= scrollHeight-10 && this.haveMore){
+				this.$emit('getNextData')
+			}
+		},200),
+	},
+};
+</script>
+
+<style lang="scss">
+.edb-detail-data-wrap{
+    .el-table--enable-row-transition .el-table__body td{
+        background: #fff !important;
+    }
+    .el-table td, .el-table th.is-leaf {
+        background: #F2F6FA !important;
+    }
+
+}
+</style>
+<style scoped lang="scss">
+.edb-detail-data-wrap{
+	display: flex;
+	flex-direction: column;
+	height: 100%;
+	.firstColumTable{
+		box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);
+	}
+	.el-table{
+		flex: none;
+	}
+	.value-ul{
+		/* flex: 1;
+		overflow-y: auto; */
+        overflow-y: auto;
+	}
+}
+</style>

+ 780 - 0
src/views/dataEntry_manage/databaseComponents/smoothEdbDialog.vue

@@ -0,0 +1,780 @@
+<template>
+    <!-- 指数修匀计算弹窗 -->
+    <el-dialog
+        :visible.sync="isOpenSmooth"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="cancelHandle"
+        center
+        width="1200px"
+        top="3vh"
+        v-dialogDrag
+        class="smooth-edb-dialog"
+    >
+        <div slot="title" style="display: flex; align-items: center">
+            <img
+                :src="$icons.computed"
+                style="color: #fff; width: 16px; height: 16px; margin-right: 5px"
+            />
+            <span style="font-size: 16px">指数修匀</span>
+        </div>
+        <div class="smooth-edb-dialog-wrap">
+            <!-- 常规计算 -->
+            <div class="normal-wrap" v-if="computedSource===1">
+                <div class="min-top">
+                    <label >选择指标:</label>
+                    <el-select
+                        v-model="select_target"
+                        v-loadMore="searchLoad"
+                        :filterable="!select_target"
+                        clearable
+                        placeholder="请输入指标名称"
+                        style="width: 85%"
+                        remote
+                        :remote-method="getTarget"
+                        @click.native="inputFocusHandle"
+                        @change="chooseTarget"
+                        @blur="search_have_more = false"
+                        :disabled="operationForm.view"
+                    >
+                        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                        <el-option
+                            v-for="item in searchOptions"
+                            :key="item.EdbInfoId"
+                            :label="$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+                            :value="item.EdbInfoId"
+                        >
+                        </el-option>
+                    </el-select>
+                    <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="handleSelectBtnClick" v-if="select_target"/>
+                    
+                </div>
+                <div class="middle">
+                    <label>已选指标:</label>
+                    <el-table
+                        :data="tableData"
+                        style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);margin-top:10px;"
+                        border>
+                        <el-table-column
+                            v-for="item in tableColums"
+                            :key="item.label"
+                            :label="item.label"
+                            :width="item.widthsty"
+                            :min-width="item.minwidthsty"
+                            align="center"
+                        >
+                            <template slot-scope="scope">
+                                <span>{{ scope.row[item.key] }}</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column
+                            width="110"
+                            align="center"
+                            label="操作"
+                            v-if="!operationForm.view"
+                        >
+                            <template slot-scope="scope">
+                                <span class="deletesty" @click="delTarget">删除</span>
+                            </template>
+                        </el-table-column>
+                        <div slot="empty" style="padding:20px 0 30px;">
+                            <tableNoData text="暂无指标" size="mini"/>
+                        </div>
+                    </el-table>
+                    <ul 
+                        class="data-ul" 
+                        ref="dataUl" 
+                        @scroll="scrollHandle"
+                        v-if="dataList.length">
+                        <li
+                            class="value-item"
+                            v-for="(item, index) in dataList"
+                            :key="item.EdbDataId"
+                        >
+                            <span class="value-label">
+                                <i class="new-tag" v-if="index === 0"></i>
+                                {{item.DataTime}}
+                            </span>
+                            <span class="value-label" style="min-width:200px;text-align:center;">{{item.Value}}</span>
+                        </li>
+                    </ul>
+                    <div class="form-cont">
+                        <el-form
+                            ref="form"
+                            label-position="right"
+                            inline
+                            label-width="80px"
+                            :model="formData"
+                            :rules="formRules"
+                            :disabled="operationForm.view"
+                        >
+                            <el-form-item label="指标名称" prop="targetName">
+                                <el-input
+                                    v-model="formData.targetName"
+                                    style="width: 340px"
+                                    placeholder="请输入指标名称"
+                                />
+                            </el-form-item>
+                            <el-form-item label="单位" prop="unit">
+                                <selectUnit 
+                                    v-model="formData.unit" 
+                                    style="width: 340px" 
+                                />
+                            </el-form-item>
+                            <el-form-item label="指标目录" prop="menu">
+                                <el-cascader v-if="isOpenSmooth"
+                                    v-model="formData.menu"
+                                    :options="catalogArr"
+                                    :props="levelProps"
+                                    clearable
+                                    placeholder="请选择指标目录"
+                                />
+                            </el-form-item>
+                            <el-form-item label="频度" prop="frequency">
+                                <el-select
+                                    v-model="formData.frequency"
+                                    placeholder="请选择频度"
+                                    style="width: 340px"
+                                    clearable
+                                >
+                                    <el-option
+                                        v-for="item in frequencyArr"
+                                        :key="item"
+                                        :label="item"
+                                        :value="item"
+                                    >
+                                    </el-option>
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item label="alpha值" prop="alphaValue">
+                                <el-input
+                                    v-model.trim="formData.alphaValue"
+                                    style="width: 340px"
+                                    placeholder="请输入alpha值"
+                                />
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </div>
+            </div>
+            <!-- 批量计算 -->
+            <div class="batch-wrap" v-else>
+                <ul class="target-ul">
+                    <li class="target-li" v-for="(list, index) in targetList" :key="index">
+                        <span class="li-tag">{{ list.tag }}</span>
+                        <el-select v-model="list.target" v-loadMore="searchLoad" :filterable="!list.target" clearable
+                            placeholder="请输入指标名称" style="width: 400px" @change="(val)=>{chooseTargetList(val,index)}"
+                            @clear="clearHandle(index)" remote :remote-method="getTarget"
+                            @click.native="inputFocusHandle">
+                            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                            <el-option v-for="item in searchOptions" :key="item.EdbInfoId"
+                                :label="$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+                                :value="item.EdbInfoId">
+                            </el-option>
+                        </el-select>
+                        <i class="el-icon-tickets" style="color:#409EFF;font-size:18px"
+                            @click="$emit('lookHistory',list.target)" v-if="list.target" />
+                        <i class="el-icon-error del-tag" v-if="index > 1" @click="delTargetList(index)" />
+                        <span class="target-date" v-if="list.start_date">{{
+                            `${list.start_date}至${list.end_date}`
+                        }}</span>
+                    </li>
+                </ul>
+                <span class="add-icon" @click="addTargetHandle">
+                    <i class="el-icon-circle-plus-outline" style="color: #5882ef; font-size: 16px" />
+                    添加更多指标
+                </span>
+                <ul class="form-ul">
+                    <li class="form-li" v-for="(list, index) in targetList" :key="index">
+                        <span class="li-tag">{{ list.tag }}</span>
+                        <el-form :ref="`list_form_${index}`"
+                            label-position="right"
+                            inline
+                            label-width="0px"
+                            :model="targetList[index]"
+                            :rules="formRules"
+                        >
+                            <el-form-item prop="targetName">
+                                <el-input
+                                    v-model="targetList[index].targetName"
+                                    style="width: 240px"
+                                    placeholder="请输入指标名称"
+                                />
+                            </el-form-item>
+                            <el-form-item prop="menu">
+                                <el-cascader v-if="isOpenSmooth"
+                                    v-model="targetList[index].menu"
+                                    :options="catalogArr"
+                                    :props="levelProps"
+                                    style="width: 200px" 
+                                    clearable
+                                    placeholder="请选择指标目录"
+                                />
+                            </el-form-item>
+                            <el-form-item prop="unit">
+                                <selectUnit 
+                                    v-model="targetList[index].unit" 
+                                    style="width: 160px" 
+                                />
+                            </el-form-item>
+                            <el-form-item prop="alphaValue">
+                                <el-input
+                                    v-model.trim="targetList[index].alphaValue"
+                                    style="width: 180px"
+                                    placeholder="请输入alpha值"
+                                />
+                            </el-form-item>
+                            <el-form-item prop="frequency">
+                                <el-select
+                                    v-model="targetList[index].frequency"
+                                    placeholder="请选择频度"
+                                    style="width: 180px"
+                                    clearable
+                                >
+                                    <el-option
+                                        v-for="item in frequencyArr"
+                                        :key="item"
+                                        :label="item"
+                                        :value="item"
+                                    >
+                                    </el-option>
+                                </el-select>
+                            </el-form-item>
+                            
+                        </el-form>
+                    </li>
+                </ul>
+            </div>
+            <div class="dia-bot" v-if="!operationForm.view">
+                <el-button
+                    type="primary"
+                    style="margin-right: 20px"
+                    @click="saveBtnClick"
+                    :loading="loading"
+                    >指数修匀计算</el-button
+                >
+                <el-button type="primary" plain @click="cancelHandle(operationForm.edb_id?'':'cancel')">取消</el-button>
+            </div>
+            <el-popover
+                placement="top-start"
+                width="500"
+                trigger="click">
+                <p style="padding:30px;line-height:25px;" v-html="$parent.tips.get('alpha')"/>
+                <span slot="reference" class="tip-label">公式说明</span>
+            </el-popover>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import { formRules } from './util';
+const tag_arr = [];
+for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
+export default {
+    props:{
+        isOpenSmooth:{
+            type:Boolean,
+            default:false
+        },
+        computedSource:{ //常规 or 批量
+            type:Number,
+            default:1
+        },
+        operationForm:{
+            type:Object,
+            default:()=>{return{
+                edb_id:'',
+                oldedb_id:''
+            }}
+        },
+        isPredict:{ //是不是预测指标
+            type:Boolean,
+            default:false,
+        }
+    },
+    data() {
+        return {
+            /* 常规 */
+            formData:{
+                targetName:'',
+                unit:'',
+                menu:'',
+                frequency:'',
+                alphaValue:''
+            },
+            formRules,
+            frequencyArr: ['日度', '周度','旬度', '月度', '季度', '年度'],
+            catalogArr:[],
+            levelProps: {
+                label: 'ClassifyName',
+                value: 'ClassifyId',
+                children: 'Children',
+                emitPath: false,
+            },
+
+            select_target:'',
+            search_page:1,
+            search_have_more:false,
+            searchOptions:[],
+            current_search:'',
+
+            tableData:[],
+            page_no:1,
+            haveMore:false,
+            tableColums:[
+                    {
+                    label: '指标ID',
+                    key: 'EdbCode',
+                },
+                {
+                    label: '指标名称',
+                    key: 'EdbName',
+                },
+                {
+                    label: '频度',
+                    key: 'Frequency',
+                },
+                {
+                    label: '单位',
+                    key: 'Unit',
+                },
+                {
+                    label: '起始时间',
+                    key: 'StartDate',
+                    minwidthsty: '100px'
+                },
+                {
+                    label: '更新时间',
+                    key: 'ModifyTime',
+                    minwidthsty: '110px'
+                },
+                {
+                    label: '来源',
+                    key: 'SourceName',
+                },
+            ],
+            dataList:[],
+
+            /* 批量 */
+            targetList:[/* {
+                tag:'A',
+                target:123456 //edbid 
+                ...formData
+            } */],
+            formDataList:[],
+
+            loading:false,
+        };
+    },
+    watch:{
+        isOpenSmooth(newVal){
+            if(newVal){
+                this.getMenu()
+                if(this.operationForm.edb_id){
+                    this.select_target = this.operationForm.oldedb_id
+                    this.getDataList()
+                    this.setDefaultOption(this.operationForm,'edit')
+                    //回显时的默认options
+                    this.searchOptions = [
+                        {
+                            EdbInfoId: this.operationForm.oldedb_id,
+                            EdbName: this.operationForm.oldEdb_name,
+                        }
+                    ]
+                }
+                if(this.computedSource===2){
+                    this.addTargetHandle()
+                    this.addTargetHandle()
+                }
+            }
+        }
+    },
+    methods: {
+        init(){
+            this.$refs.form&&(this.$refs.form.resetFields());
+            Object.assign(this.$data, this.$options.data());
+        },
+        searchLoad() {
+            if(!this.search_have_more) return;
+            this.searchApi(this.current_search,++this.search_page)
+        },
+        async searchApi(query,page=1){
+            const params = {
+                KeyWord:query,
+                CurrentIndex: page,
+            }
+            const res = this.isPredict
+                ? await preDictEdbInterface.edbSearch(params)
+                : await dataBaseInterface.targetSearchByPage(params)
+            if(res.Ret !== 200) return
+            const { List,Paging } = res.Data;
+            this.search_have_more = page < Paging.Pages;
+            let arr = page === 1 ? List : this.searchOptions.concat(List);
+            this.searchOptions = arr;
+        },
+        /* 指标列表 */
+        getTarget(query) {
+            this.search_page = 1;
+            this.current_search = query;
+            this.searchApi(this.current_search);
+        },
+        /* 聚焦获取当前检索 */
+        inputFocusHandle(e) {
+            this.search_page = 1;
+            this.current_search = e.target.value;
+            this.searchApi(this.current_search);
+        },
+        /* 获取目录结构 */
+        async getMenu() {
+            const res = this.isPredict
+                ? await preDictEdbInterface.classifyListV2()
+                : await dataBaseInterface.menuListV3()
+            if(res.Ret!==200) return 
+            this.catalogArr = res.Data.AllNodes || [];
+        },
+        /* 选择指标 */
+        chooseTarget(val) {
+            if(val) {
+                let obj = this.searchOptions.find(item => item.EdbInfoId === val);
+                //同步指标信息
+                this.setDefaultOption(obj);
+                this.page_no = 1;
+                this.dataList.length ? this.$refs.dataUl.scrollTop = 0 : null;
+                this.getDataList()
+            }else {
+                this.tableData = [];
+                this.dataList = [];
+            }
+        },
+        chooseTargetList(val,index){
+            if(val){
+                const obj = this.searchOptions.find(item => item.EdbInfoId === val);
+                this.targetList[index].targetName = `${obj.EdbName}指数修匀`
+                this.targetList[index].unit = obj.Unit
+                this.targetList[index].frequency = obj.Frequency
+                this.targetList[index].menu = obj.ClassifyId||''
+                this.targetList[index].alphaValue =obj.Formula||''
+            }
+        },
+        setDefaultOption(obj,type){
+            this.formData = {
+                targetName:`${obj.EdbName}${type==='edit'?'':'指数修匀'}`,
+                unit:obj.Unit,
+                frequency:obj.Frequency,
+                menu:obj.ClassifyId||'',
+                alphaValue:obj.Formula||''
+            }
+        },
+        async getDataList(){
+            const params = {
+                PageSize: 10,
+                CurrentIndex: this.page_no,
+                EdbInfoId: this.select_target,
+            }
+            const res = this.isPredict
+                ? await preDictEdbInterface.edbDataInfo(params)
+                : await dataBaseInterface.targetList(params)
+            if(res.Ret!==200) return 
+            if(res.Data){
+                res.Data.Item.ModifyTime = res.Data.Item.ModifyTime.substr(0,10);
+                this.tableData = [res.Data.Item] || [];
+                this.haveMore =  this.page_no < res.Data.Paging.Pages ? true : false;
+                this.dataList = this.page_no === 1 ? (res.Data.Item.DataList || []) : this.dataList.concat(res.Data.Item.DataList);
+            }else{
+                this.tableData = [];
+                this.dataList = [];
+            }
+        },
+        handleSelectBtnClick(){
+            //计算指标打开弹窗,基础指标打开新页面
+            if(this.tableData[0].EdbType===2){
+                this.$emit('lookHistory',this.select_target)
+            }else{
+                const {ClassifyId,UniqueCode,EdbInfoId} = this.tableData[0]
+                let {href} = this.$router.resolve({path:`/database`,query:{code:UniqueCode,id:EdbInfoId,classifyId:ClassifyId}});
+                window.open(href,'_blank');
+            }
+        },
+        scrollHandle(e){
+            const dom = e.target
+            let scrollTop = dom.scrollTop; //滑入屏幕上方的高度
+            let windowHeitht = dom.clientHeight; //页面的高度
+            let scrollHeight = dom.scrollHeight; //整个div的高度
+            let total = scrollTop + windowHeitht
+            if(total >= scrollHeight && this.haveMore){
+                this.page_no ++;
+                this.getDataList();
+            }
+        },
+        /* 删除已选指标 */
+		delTarget() {
+			this.tableData = [];
+			this.dataList = [];
+			this.select_target = '';
+			this.page_no = 1;
+		},
+        delTargetList(index){
+            this.targetList.splice(index, 1);
+        },
+        clearHandle(index){
+            const item = {...{tag:tag_arr[index],target:''},..._.cloneDeep(this.formData)}
+            this.targetList.splice(index,1,item)
+        },
+        
+        addTargetHandle(){
+            if(this.targetList.length >= 26){
+                this.$message.warning('添加指标个数已达上限')
+                return 
+            }
+            let tag = 'A'
+            let index = -1
+            if(this.targetList.length>=1){
+                tag = this.targetList[this.targetList.length-1].tag;
+                index = tag_arr.findIndex(item => item === tag);
+            }
+            const item = {...{tag:tag_arr[index+1],target:''},..._.cloneDeep(this.formData)}
+            this.targetList.push(item)
+        },
+        saveBtnClick(){
+            this.computedSource===1?this.saveHandle():this.saveListHandle()
+        },
+        //常规编辑/保存指标
+        async saveHandle(){
+            if(!this.select_target){
+                this.$message.warning('指标不能为空')
+                return
+            }
+            await this.$refs.form.validate();
+            this.loading = true;
+
+            const {targetName,unit,menu,frequency,alphaValue} = this.formData
+            let params = {
+                Source:this.$route.path==='/database'?72:73,
+                EdbName:targetName,
+                Unit:unit,
+                ClassifyId:menu,
+                Frequency:frequency,
+                Formula:alphaValue,
+                FromEdbInfoId:this.select_target
+            }
+
+            let res = null
+            if(this.isPredict){
+                let edit_params = { ...params,EdbInfoId: this.operationForm.edb_id }
+                res = await preDictEdbInterface.operateEdbSave(this.operationForm.edb_id ? edit_params : params)
+            }else{
+                res = this.operationForm.edb_id 
+                ? await dataBaseInterface.calculateTargetEdit({ ...params,EdbInfoId: this.operationForm.edb_id })
+                : await dataBaseInterface.calculateTargetSave(params)
+            }
+            if(res.Ret!==200) return 
+            this.$message.success(res.Msg)
+            this.operationForm.edb_id 
+                ? this.$emit('addCallBack','edit') 
+                : this.$emit('addCallBack','add',{ code:res.Data.UniqueCode,id:res.Data.EdbInfoId,classifyId:params.ClassifyId });
+            this.init();
+            this.loading = false;
+
+        },
+        //批量添加指标
+        async saveListHandle(){
+            //只添加选择了指标的
+            const targetCheck = this.targetList.filter(item=>item.target)
+            /* if(targetCheck.length!==this.targetList.length){
+                this.$message.warning('请选择指标')
+                return
+            } */
+            //只验证选择了指标的form-rules
+            for(let i = 0;i<targetCheck.length;i++){
+                const index = tag_arr.findIndex(item=>item===targetCheck[i].tag)
+                await this.$refs[`list_form_${index}`][0].validate();
+            }
+
+            this.loading = true
+            const params = targetCheck.map(item=>{
+                return {
+                    CalculateId: item.tag,
+                    CalculateInfo: {
+                        ClassifyId: item.menu,
+                        EdbName: item.targetName,
+                        Formula: item.alphaValue,
+                        Frequency:item.frequency,
+                        FromEdbInfoId: item.target,
+                        Source:this.$route.path==='/database'?72:73,
+                        Unit: item.unit
+                    }
+                }
+            })
+
+            const res = this.$route.path==='/database'
+                ? await dataBaseInterface.batchCalculateTargetAdd(params)
+                : await preDictEdbInterface.batchCalculateTargetAdd(params)
+            if(res.Ret !== 200) return
+            const { Fail,Success } = res.Data;
+            if(Fail.length) {
+                let message = '';
+                Fail.forEach(item => {
+                    message+=`${item.CalculateId}:${item.Msg}</br>`
+                })
+
+                this.$message({
+                    dangerouslyUseHTMLString: true,
+                    message,
+                    type: 'error'
+                })
+                this.dealFailHandle(Fail)
+            }else {
+                this.$message.success('添加成功');
+                this.init();
+                this.$emit('addCallBack','add',{ code:Success[0].UniqueCode,id:Success[0].EdbInfoId,classifyId:Success[0].ClassifyId});
+                this.loading = false;
+            }
+        },
+        dealFailHandle(arr){
+            //从targetList中剔除成功的指标,重新赋予剩下的指标tag
+            const failTagArr = arr.map(_ =>_.CalculateId);
+            this.targetList = this.targetList.filter(_ => failTagArr.includes(_.tag));
+            this.targetList.forEach((item,index)=>{
+                item.tag = tag_arr[index]
+            })
+            this.loading = false;
+        },
+        cancelHandle(type) {
+            this.init();
+            this.$emit('cancel');
+            type==='cancel' && this.$emit('openPrev');
+        },
+    },
+};
+</script>
+
+<style lang="scss">
+.smooth-edb-dialog{
+    .el-dialog__body{
+        padding: 25px 25px 30px !important;
+        padding-bottom: 5px !important;
+    }
+}
+.smooth-edb-dialog-wrap{
+    .el-cascader .el-input {
+        width: 340px;
+    }
+    .min-top {
+        padding: 20px 30px;
+        border: 1px solid #ECECEC;
+        box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
+        border-radius:4px;
+    }
+    .middle {
+        margin-top: 20px;
+        .data-ul {
+            margin-top: 5px;
+            border-bottom: 1px solid #dcdfe6;
+            max-height: 140px;
+            overflow-y: auto;
+            .value-item {
+                padding: 14px 0;
+                border: 1px solid #dcdfe6;
+                border-bottom: none;
+                display: flex;
+                justify-content: space-around;
+                .value-label {
+                    position: relative;
+                    color: #666;
+                }
+                .new-tag {
+                    width: 6px;
+                    height: 6px;
+                    display: inline-block;
+                    position: absolute;
+                    left: -12px;
+                    top: 50%;
+                    transform: translateY(-50%);
+                    border-radius: 50%;
+                    background: #f00;
+                }
+            }
+        }
+        .form-cont {
+            padding-top: 30px;
+            margin-top: 30px;
+            border-top: 1px dashed #AAB4CC;
+            input::-webkit-outer-spin-button,
+            input::-webkit-inner-spin-button {
+                    -webkit-appearance: none;
+            }
+            input[type="number"]{
+                -moz-appearance: textfield;
+            }
+        }
+    }
+    .dia-bot {
+        padding: 20px 0 30px;
+        display: flex;
+        justify-content: center;
+    }
+    .tip-label {
+        position: absolute;
+        bottom: 30px;
+        right: 30px;
+        color: #409EFF;
+        cursor: pointer;
+    }
+    .batch-wrap{
+        padding:0 40px;
+        .target-ul {
+            display: flex;
+            flex-wrap: wrap;
+            justify-content: space-between;
+            .target-li {
+                position: relative;
+                margin-bottom: 30px;
+                .li-tag {
+                    font-size: 16px;
+                    margin-right: 8px;
+                }
+                .del-tag {
+                    position: absolute;
+                    right: -30px;
+                    top: 12px;
+                    font-size: 16px;
+                    cursor: pointer;
+                }
+                .target-date {
+                    color: #5882ef;
+                    position: absolute;
+                    bottom: -25px;
+                    left: 24px;
+                }
+            }
+        }
+        .add-icon {
+            font-size: 16px;
+            color: #5882ef;
+            cursor: pointer;
+        }
+        .form-ul {
+            padding-top: 20px;
+            margin-top: 20px;
+            border-top: 1px dashed #AAB4CC;
+            .form-li {
+                display: flex;
+                align-items: center;
+                margin-bottom: 15px;
+                .el-cascader>.el-input{
+                    width:100%;
+                }
+                .el-form-item{
+                    margin-bottom: 0;
+                }
+                .li-tag{
+                    margin-right: 20px;
+                }
+            }
+        }
+    }
+    
+}
+</style>

+ 23 - 1
src/views/dataEntry_manage/databaseComponents/util.js

@@ -20,6 +20,16 @@ export const formRules= {
 	],
 	calendar_type: [
 		{ required: true, message: '日历不能为空',trigger: 'blur' }
+	],
+	alphaValue:[
+		{ validator:(rule,value,callback)=>{
+			if(Number(value)<=0||Number(value)>=1){
+				callback(new Error("请输入>0,<1的数值"))
+			}else{
+				callback()
+			}
+		},trigger:['change','blur']},
+		{ required:true,message:'alpha值不能为空',trigger:'blur'},
 	]
 }
 
@@ -88,6 +98,10 @@ export const computedTypes = [
 	{
 		name: '累计值',
 		type: 'accumulate'
+	},
+	{
+		name:'指数修匀',
+		type:'alpha'
 	}
 ]
 
@@ -124,6 +138,10 @@ export const computedBatchTypes = [
 	{
 		name: '累计值',
 		type: 'accumulate'
+	},
+	{
+		name:'指数修匀',
+		type:'alpha'
 	}
 ]
 
@@ -396,5 +414,9 @@ export const formulaTip = new Map([
 	日度数据年初至今:日期同原日度数据。将每年1月1日(含)到日度数据所在日期(含)之间的日度值,进行加总。<br>
 	周度数据年初至今:日期同原周度数据。将周度值转成日度频率,空值用插值法插值,然后算法同日度年度至今,再除以7<br>
 	月度/季度数据年初至今:日期同原月度/季度数据,将每年1月1日(含)到月度数据所在日期(含)之间的月度/季度值,进行加总<br>
-	以此类推`]
+	以此类推`],
+	['alpha',`指数修匀计算公式:<br>
+	1、设定指数修匀值序列的初始值=原来时间序列的初始值 <br>
+	2、选择平滑系数alpha值:在0-1之间,开区间 <br>
+	3、本期指数修匀值=alpha*本期实际值+(1-alpha)*上期指数修匀值`]
 ])

+ 462 - 159
src/views/dataEntry_manage/databaseList.vue

@@ -13,7 +13,7 @@
 				<el-button v-permission="permissionBtn.edbDataPermission.edbData_dataAdjust"
 					type="primary" @click="$router.push({path: '/adjustdata'})">数据调整</el-button>
 				<el-button v-permission="permissionBtn.edbDataPermission.edbData_batchUpdate"
-					type="primary" plain @click="updateHandler">一键新</el-button>
+					type="primary" plain @click="updateHandler">一键新</el-button>
 			</div>
 			<div class="top-right">
 
@@ -119,23 +119,22 @@
 									@click.stop="addNode(node,data)"
 									v-if="data.Button.AddButton"
 								/>
-								<!--如果是分类,判断data.Button.OpButton不变;如果是指标,再加上checkPermissionBtn判断-->
+								<!--如果是分类,判断data.Button.OpButton不变;如果是指标,不显示(ETA1.0.3)-->
 								<img
 									src="~@/assets/img/set_m/edit.png"
 									alt=""
 									style="width: 15px; height: 14px; margin-right: 8px"
 									@click.stop="editNode(node,data)"
-									v-if="data.EdbCode
-										?(data.Button.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_edit))
-										:(data.Button.OpButton)"
+									v-if="!data.EdbCode&&(data.Button.OpButton)"
 								/>
+								<!--如果是分类,判断data.Button.DeleteButton不变;如果是指标,不显示(ETA1.0.3)-->
 								<img
 									slot="reference"
 									src="~@/assets/img/set_m/del.png"
 									alt=""
 									style="width: 14px; height: 14px;"
 									@click.stop="removeNode(node,data)"
-									v-if="data.Button.DeleteButton"
+									v-if="!data.EdbCode&&(data.Button.DeleteButton)"
 								/>
 								<i class="el-icon-view" v-if="data.EdbType===2&&![58,59,67,68].includes(data.Source)" @click.stop="viewNode(node,data)"></i>
 								<img 
@@ -171,65 +170,45 @@
 			<div class="main-right right" id="right" style="background:transparent;border:none;box-shadow:none" v-if="showAssociateChart">
 				<dataAssociateChart :edbInfoId="selected_edbid"></dataAssociateChart>
 			</div>
-			<div class="main-right right" id="right" style="background:transparent;border:none;box-shadow:none" v-if="showAssociateComputeData">
+			<div class="main-right right" id="right" style="background:transparent;border:none;box-shadow:none;padding-top: 30px;box-sizing: border-box;" v-if="showAssociateComputeData">
 				<dataAssociateComputeData :edbInfoId="selected_edbid"></dataAssociateComputeData>
 			</div>
-			<div class="main-right right" id="right" v-show="!showAssociateChart&&!showAssociateComputeData">
-				<el-table
-				:data="tableData"
-				style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);"
-				class="firstColumTable"
-				border>
-					<el-table-column
-						v-for="item in tableColumsOne"
-						:key="item.label"
-						:width="item.widthsty"
-						:min-width="item.minwidthsty"
-						align="center"
-					>
-						<template slot="header" slot-scope="scope">
-							<div class="chartEn-mark" style="top: -10px;" v-show="scope.$index ==0 && tableData[0] && tableData[0].IsEnEdb" >En</div>
-							<span>{{item.label}}</span>
-						</template>	
-						<template slot-scope="scope">
-							<!-- 中文 -->
-							<span v-show="currentLang=='ch'">{{ scope.row[item.key] }}</span> 
-							<span v-show="currentLang=='en'">{{scope.row[item.enKey||item.key] || scope.row[item.key]}}</span>
-						</template>
-					</el-table-column>
-				</el-table>
-				<el-table
-				:data="tableData"
-				style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);"
-				border>
-					<el-table-column
-						v-for="item in tableColumsTwo"
-						:key="item.label"
-						:label="item.label"
-						:width="item.widthsty"
-						:min-width="item.minwidthsty"
-						align="center"
-					>
-						<template #header>
-							<span>{{ item.label }}</span>
-						</template>
-						<template slot-scope="scope">
-							<span>{{ scope.row[item.key] }}</span>
-						</template>
-					</el-table-column>
-					<el-table-column
-						width="260"
-						align="center"
-						label="操作"
-					>
-						<template slot-scope="scope">
-							<el-button v-permission="permissionBtn.edbDataPermission.edbData_update"
-								size="mini" type="text" @click="refreshTargetHandle" >更新</el-button>
-							<el-button 
-								v-permission="permissionBtn.edbDataPermission.edbData_edit"
-								size="mini" 
-								type="text" 
-								:disabled="!scope.row.Button.OpButton"
+			<!-- 指标图表列表 -->
+			<div class="main-right right list" id="right" v-show="isShowList">
+				<p>共{{Total||0}}个指标</p>
+				<div class="list-wrap" ref="listRef" @scroll="loadMoreHandle" v-if="Total">
+					<div class="list-item" v-for="item in chartList" :key="item.EdbInfoId">
+						<div class="header">
+							<span v-show="currentLang=='ch'">{{ item.EdbName }}</span> 
+							<span v-show="currentLang=='en'">{{ item.EdbNameEn || item.EdbName }}</span>
+						</div>
+						<div class="image" @click="detailShowHandle(item)">
+							<img :src="item.ChartImage" alt=""/>
+						</div>
+						<div class="info">
+							创建时间:{{item.CreateTime.substring(0,10)}}
+						</div>
+					</div>
+					<p style="height: 40px;line-height:40px;width: 100%;"></p>
+				</div>
+				<div v-if="!Total" class="nodata">
+					<tableNoData text="暂无指标"/>
+				</div>
+			</div>
+			<!-- 指标详情 -->
+			<div class="main-right right detail" id="right" v-show="isShowDetail">
+				<div class="header">
+					<el-tabs v-model="activeTab" @tab-click="rePainChart">
+						<el-tab-pane label="走势图" name="Chart">
+						</el-tab-pane>
+						<el-tab-pane label="数据详情" name="Data">
+						</el-tab-pane>
+					</el-tabs>
+					<div class="edb-tool">
+						<el-button v-if="isEdbBtnShow('update')"
+							type="text" @click="refreshTargetHandle" >刷新</el-button>
+						<el-button v-if="isEdbBtnShow('edit')"
+								type="text" :disabled="!(EdbData.Button.OpButton)"
 								@click="editNode({
 									level: 4,
 									parent: {
@@ -241,47 +220,73 @@
 											}
 										},
 									}
-								},scope.row)"
-								>编辑</el-button>
-							<el-button size="mini" type="text" @click.stop="reCalculateHandler" v-if="scope.row.EdbType===2" :loading="calculateLoading">重新计算</el-button>
-							<el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_toImgs)"
-								size="mini" type="text" @click.stop="createChartHandle(scope.row.EdbInfoId)">一键成图</el-button>
-							<el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_copyData)"
-								size="mini" type="text" @click="copyCode">复制数据</el-button>
-							<!-- <lookEdbHistory :showType="2" :edbId="selected_edbid" v-if="scope.row.EdbType===2"/> -->
-							<el-button size="mini" type="text"
-							v-if="scope.row.EdbType===2&&permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_edbSource)" @click="isLookHistory=true;lookEdbId=selected_edbid">指标溯源</el-button>
-							
-							<el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_enNameSetting)"
-								size="mini" type="text" @click="openEnNameDia">设置英文名称</el-button>
-							<el-button size="mini" type="text" @click.stop="updateNewestDataHandle" 
-							v-if="scope.row.Button.InsertNewDataButton&&permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_newestValue)" >{{scope.row.DataInsertConfig.Date?'编辑最新值':'添加最新值'}}</el-button>
-							<el-button size="mini" type="text" @click.stop="refreshBaseHandler" 
-								v-if="scope.row.EdbType===1&&permissionBtn.checkPermissionBtn(permissionBtn.edbDataPermission.edbData_refreshAll)" :loading="refreshLoading">全部刷新</el-button>
-						</template>
-					</el-table-column>
-					<div slot="empty" style="padding: 50px 0 320px;">
-						 <tableNoData :text="defaultWarn"/>
+								},EdbData)"
+							>编辑</el-button>
+						<!-- 指保存指标的上下限,在走势图才显示 -->
+						<el-button v-if="activeTab==='Chart'"
+							type="text" @click.stop="saveEdbLimit">保存</el-button>
+						<el-button v-if="isEdbBtnShow('setEn')"
+							type="text" @click="openEnNameDia">设置英文名称</el-button>
+						<el-button v-if="EdbData.Button.InsertNewDataButton&&isEdbBtnShow('newValue')"
+							type="text" @click.stop="updateNewestDataHandle" >{{(EdbData.DataInsertConfig.Date)?'编辑最新值':'添加最新值'}}</el-button>
+						<el-button v-if="EdbData.EdbType===2"
+							type="text" @click.stop="reCalculateHandler" :loading="calculateLoading">重新计算</el-button>
+						<el-button v-if="EdbData.EdbType===2&&isEdbBtnShow('toSource')"
+							type="text" @click="isLookHistory=true;lookEdbId=selected_edbid">指标溯源</el-button>
+						<el-button v-if="EdbData.EdbType===1&&isEdbBtnShow('refreshAll')"
+							type="text" @click.stop="refreshBaseHandler" :loading="refreshLoading">全部刷新</el-button>
+						<el-button v-if="isEdbBtnShow('copyData')"
+							type="text" @click="copyCode">复制数据</el-button>
+						<el-button v-if="EdbData.Button.DeleteButton"
+							type="text" @click="removeNode(_,EdbData)" style="color:#C54322;">删除</el-button>
 					</div>
-				</el-table>
-				<ul 
-				class="value-ul" 
-				ref="valueUl" 
-				@scroll="scrollHandle" 
-				v-show="showTable&&dataList.length">
-					<li
-						class="value-item"
-						v-for="item in dataList"
-						:key="item.EdbDataId"
-					>
-						<span class="value-label">
-							<i class="new-tag" v-if="tableData[0].LatestDate===item.DataTime"></i>
-							{{item.DataTime}}
-						</span>
-						<span :class="['value-label',{'predict-act': tableData[0].DataInsertConfig.Date===item.DataTime}]" style="min-width:200px;text-align:center;">{{item.Value}}</span>
-					</li>
-					<li class="nodata value-item" v-if="!dataList.length">暂无数据</li>
-				</ul>
+				</div>
+				<div class="container" id="detail-container">
+					<div class="chart" v-show="activeTab==='Chart'">
+						<chart-trend-render
+							:edbid="selected_edbid"
+							:chartLang="currentLang"
+							ref="createChart"
+							@editEnName="openEnNameDia"/>
+						<div class="info">
+							<span>数据来源:{{EdbData.SourceName}}</span>
+							<span>添加人:{{EdbData.SysUserRealName}}</span>
+						</div>
+						<ul class="value-ul"
+							v-show="showTable&&dataList.length">
+							<li class="value-item" style="background-color: #EBEFF6;">
+								<span style="width:240px">日期(频度:{{EdbData.Frequency}})</span>
+								<span style="flex:1;">值</span>
+							</li>
+							<li class="value-item"
+								v-for="item in dataList.slice(0,3)"
+								:key="item.EdbDataId">
+								<span class="value-label date" style="width:240px">
+									<span style="position: relative;">
+										<i class="new-tag" v-if="EdbData.LatestDate===item.DataTime"></i>
+										{{item.DataTime}}
+									</span>
+								</span>
+								<span :class="['value-label',{'predict-act': EdbData.DataInsertConfig.Date===item.DataTime}]" style="flex:1;">
+									<span :class="['value-style',{'predict-act': EdbData.DataInsertConfig.Date===item.DataTime}]">{{item.Value}}</span>
+								</span>
+							</li>
+							<li class="nodata value-item" v-if="!dataList.length">暂无数据</li>
+						</ul>
+					</div>
+					<div class="list" v-show="activeTab==='Data'">
+						<edb-detail-data 
+							ref="edb_detail_data"
+							:current-lang="currentLang"
+							:table-data="tableData"
+							:table-colums-one="tableColumsOne"
+							:table-colums-two="tableColumsTwo"
+							:data-list="dataList"
+							:haveMore="haveMore"
+							@getNextData="()=>{page_no++;getDataList();}"
+						/>
+					</div>
+				</div>
 			</div>
 		</div>
 		<!-- 输入英文指标弹窗 -->
@@ -369,14 +374,14 @@
 			@changeSource="changeComputedType"
 		/>
 		<!-- 一键成图弹窗 -->
-		<create-chart
+		<!-- <create-chart
 			:isCreateChart="isCreateChart"
 			:edbid="selected_edbid"
 			:chartLang="currentLang"
 			ref="createChart"
 			@close="isCreateChart = false"
 			@editEnName="openEnNameDia"
-		/>
+		/> -->
 
 		<!-- 一键更新弹窗 -->
 		<update-dialog
@@ -443,7 +448,16 @@
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
     />
-
+		<!-- 指数修匀弹窗 -->
+		<SmoothEdbDialog 
+			:is-open-smooth="computed_type==='alpha'"
+			:computed-source="computed_source"
+			:operationForm="operationForm"
+			@cancel="computed_type=0"
+			@openPrev="isOpenComputed=true"
+			@addCallBack="addComputedCallBack"
+			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+		/>
 	</div>
 </template>
 
@@ -469,10 +483,13 @@ import batchComputedDialog from './databaseComponents/batchComptedDialog.vue';
 import diffusionIndexDialog from './databaseComponents/diffusionIndexDia.vue';
 import updateNewestDataDia from './databaseComponents/updateNewestDia.vue';
 import EdbLabelList from '@/components/edbLabelList.vue';
+import chartTrendRender from './databaseComponents/chartTrendRender.vue';
+import edbDetailData from './databaseComponents/edbDetailData.vue';
+import SmoothEdbDialog from './databaseComponents/smoothEdbDialog.vue';
 export default {
 	name: '',
-	components: { 
-		openDialog, 
+	components: {
+		openDialog,
 		addTargetDiaBase,
 		completeTargetDia,
 		computedDialog,
@@ -489,7 +506,10 @@ export default {
 		batchComputedDialog,
 		diffusionIndexDialog,
 		updateNewestDataDia,
-		EdbLabelList
+		EdbLabelList,
+		chartTrendRender,
+		edbDetailData,
+		SmoothEdbDialog
 	},
 	directives: {
     drag(el, bindings) {
@@ -580,7 +600,7 @@ export default {
 				{
 					label: '指标目录',
 					key: 'Menu',
-					minwidthsty: '117px',
+					minwidthsty: '150px',
 				},
 				{
 					label: '起始时间',
@@ -590,12 +610,12 @@ export default {
 				{
 					label: '更新时间',
 					key: 'ModifyTime',
-					minwidthsty: '118px',
+					minwidthsty: '120px',
 				},
 				{
 					label: '添加人',
 					key: 'SysUserRealName',
-					widthsty: '100px',
+					widthsty: '160px',
 				}
 			],
 			haveMore: true,
@@ -666,7 +686,17 @@ export default {
 			lookEdbId: 0,
 			labelList:[],//标签列表
 
-			CanOpClassify: false
+			CanOpClassify: false,
+
+			select_classifyId:0,//指标分类id
+			PageSize:20,
+			CurrentIndex:1,
+			Total:0,
+			IsListEnd:false,//是不是到底了
+			chartList:[],
+
+			activeTab:'',
+			activeName:'second'
 		};
 	},
 	watch: {
@@ -675,7 +705,10 @@ export default {
 				this.tableData = [];
 				this.dataList = [];
 				this.defaultWarn = '请在左侧选择指标';
+				this.activeTab=''
 			}else {
+				console.log('new val')
+				this.activeTab='Chart'
 				this.initGetData();
 			}
 		},
@@ -685,26 +718,21 @@ export default {
 				let [search_obj] = this.searchOptions.filter(
 					(item) => item.EdbInfoId === newval
 				);
-				
 				this.page_no = 1;
-				this.$refs.valueUl.scrollTop = 0;
-				// 查找图表的父级code
-				//this.defaultShowNodes = this.findParentNodeHandle(this.treeData,search_obj.ClassifyId);
+				if(this.$refs.edb_detail_data){
+					this.$refs.edb_detail_data.$refs.valueUl.scrollTop=0
+				}
 				this.select_node = search_obj.UniqueCode;
 				this.selected_edbid = newval;
-
-				//滚动到高亮节点位置
-				/* setTimeout(() => {
-					this.$refs.menuTree.setCurrentKey(this.select_node);
-					let node = document.getElementById(`node${this.select_node}`);
-					let parent = document.getElementsByClassName('tree-cont')[0];
-
-					if(node.offsetTop > parent.offsetHeight) {
-						parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
-					}
-				},400) */
 			}
 		},
+		select_classifyId(newval){
+			if(this.$refs.listRef) this.$refs.listRef.scrollTop = 0;
+			if(newval){
+				this.CurrentIndex = 1
+				this.getEdbChartList()
+			}
+		}
 	},
 	computed: {
 			/* 计算弹窗控制 */
@@ -727,8 +755,35 @@ export default {
 			let id = parseInt(localStorage.getItem('AdminId'));
 			return id;
 		},
+		//指标详情,也就是tableData[0]
+		EdbData(){
+			return this.tableData[0]?this.tableData[0]:{Button:{},DataInsertConfig:{},DataList:[]}
+		},
+		//是否显示指标列表
+		isShowList(){
+			return !this.showAssociateChart&&!this.showAssociateComputeData&&!this.selected_edbid
+		},
+		//是否显示指标详情
+		isShowDetail(){
+			return !this.showAssociateChart&&!this.showAssociateComputeData&&this.selected_edbid
+		}
 	},
 	methods: {
+		//控制指标详情操作按钮
+		isEdbBtnShow(type){
+			const {edbDataPermission,checkPermissionBtn}=this.permissionBtn
+			const BtnMap = {
+				'update':edbDataPermission.edbData_update,
+				'edit':edbDataPermission.edbData_edit,
+				'toImg':edbDataPermission.edbData_toImgs,
+				'copyData':edbDataPermission.edbData_copyData,
+				'toSource':edbDataPermission.edbData_edbSource,
+				'setEn':edbDataPermission.edbData_enNameSetting,
+				'newValue':edbDataPermission.edbData_newestValue,
+				'refreshAll':edbDataPermission.edbData_refreshAll,
+			}
+			return checkPermissionBtn(BtnMap[type])
+		},
 		/* 获取树分类数据 */
 		getTreeData(params) {
 			
@@ -787,7 +842,8 @@ export default {
 						//将指标添加进标签列表中
 						const {EdbNameEn,EdbName,EdbInfoId,UniqueCode,ClassifyId}=res.Data.Item
 						this.addLabel({code:UniqueCode,id:EdbInfoId,classifyId:ClassifyId,EdbName,EdbNameEn})
-						this.defaultShowNodes=this.findParentNodeHandle(this.treeData,ClassifyId)
+						let deep_arr = _.cloneDeep(this.treeData);
+						this.defaultShowNodes=this.findParentNodeHandle(deep_arr,ClassifyId).reverse()||[]
 						//设置tree高亮
 						this.$refs.menuTree.setCurrentKey(UniqueCode);
 
@@ -797,9 +853,14 @@ export default {
 						this.defaultWarn = type=== 'search' ? '未搜索到该指标' : '请在左侧选择指标'
 
 						this.$refs.menuTree.setCurrentKey(null)
+						// 清除当前的label
+						this.deleteLabel({code:this.select_node,id:this.selected_edbid,classifyId:''})
+						
 					}
 					if(type==='refresh') {
-						this.$refs.valueUl.scrollTop = 0;
+						if(this.$refs.edb_detail_data){
+							this.$refs.edb_detail_data.$refs.valueUl.scrollTop=0
+						}
 					}
 					this.$nextTick(()=>{
 						const _node = this.$refs.menuTree.getNode(this.select_node)
@@ -808,8 +869,15 @@ export default {
 						//滚动到高亮位置
 						setTimeout(() => {
 							let node = document.getElementById(`node${this.select_node}`)||{}
-							let parent = document.getElementsByClassName('tree-cont')[0];
-							if(node.offsetTop > parent.offsetHeight) {
+							let parent = document.getElementsByClassName('target_tree')[0];
+							//parent可视区间:[scrollTop,scrollTop+offsetHeight]
+							//node位置:node.offsetTop
+							const overTop = node.offsetTop+node.clientHeight+30<parent.scrollTop
+							const overBottom = node.offsetTop+node.clientHeight+30>parent.scrollTop+parent.offsetHeight
+							if(overTop){
+								parent.scrollTop = node.offsetTop-60
+							}
+							if(overBottom){
 								parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
 							}
 						},400)
@@ -818,6 +886,33 @@ export default {
 				}
 			})
 		}),
+		//获取指标图表列表
+		getEdbChartList(){
+			dataBaseInterface.getEdbChartList({
+				PageSize:this.PageSize,
+				CurrentIndex:this.CurrentIndex,
+				ClassifyId:this.select_classifyId,
+			}).then(res=>{
+				if(res.Ret!==200) return
+				if(res.Data){
+					this.chartList = this.CurrentIndex===1?res.Data.List:[...this.chartList,...res.Data.List]
+					this.Total = res.Data.Paging.Totals||0
+					this.IsListEnd = res.Data.Paging.IsEnd
+				}
+
+
+			})
+		},
+		//指标图表列表-加载更多
+		loadMoreHandle: _.throttle(function() {
+			let scrollTop = this.$refs.listRef.scrollTop;
+			let clientHeight = this.$refs.listRef.clientHeight;
+			let scrollHeight = this.$refs.listRef.scrollHeight;
+			if(scrollTop + clientHeight >= scrollHeight-10 && !this.IsListEnd){
+				this.CurrentIndex++;
+				this.getEdbChartList();
+			}
+			},300),
 		/* 搜索 */
 		searchHandle(query) {
 			this.search_page = 1;
@@ -975,17 +1070,14 @@ export default {
 		},
 		/* 节点变化时 */
 		nodeChange(data,node) {
-			this.dynamicNode = node;
 			this.search_txt = '';
-			this.showAssociateChart=false
-			this.showAssociateComputeData=false
-			// this.page_no = 1;
-			// this.$refs.valueUl.scrollTop = 0;
+			this.select_classifyId = !data.EdbInfoId?data.ClassifyId:0;
 			this.select_node = data.UniqueCode;
 			this.selected_edbid = data.EdbInfoId;
 			this.resetNodeStyle(node);
-			
-			
+			this.dynamicNode = node;
+			this.showAssociateChart=false
+			this.showAssociateComputeData=false
 		},
 		resetNodeStyle: _.debounce(function(node) {
 			const tree = $('.target_tree')[0];
@@ -1096,6 +1188,7 @@ export default {
 					if(res.Ret === 200) {
 						this.setComputedDialogForm(data.Source,node,data,res.Data);
 						this.computed_type = [23,24].includes(data.Source) ? 'joint' : data.Source;
+						this.computed_type = [72,73].includes(data.Source)? 'alpha': data.Source;
 					}
 				})
 
@@ -1159,7 +1252,7 @@ export default {
 			if(this.selected_edbid) {
 				this.loading = this.$loading({
 					lock: true,
-					target:'.main-right',
+					target:'.detail',
 					text: '刷新数据中...',
 					spinner: 'el-icon-loading',
 					background: 'rgba(255, 255, 255, 0.8)'
@@ -1427,9 +1520,11 @@ export default {
 			this.selected_edbid = id;
 
 			//this.defaultShowNodes=this.findParentNodeForClassifyId(classifyId,code)
+			const containerDom = document.getElementById('detail-container')
+			containerDom&&(containerDom.scrollTop = 0)
 			
 			 //滚动到高亮节点位置
-			this.$nextTick(()=>{
+			/* this.$nextTick(()=>{
 				setTimeout(() => {
 					let node = document.getElementById(`node${this.select_node}`)||{}
 					let parent = document.getElementsByClassName('tree-cont')[0];
@@ -1438,7 +1533,7 @@ export default {
 						parent.scrollTop =  node.offsetTop - parent.offsetHeight/2
 					}
 				},400)
-			})
+			}) */
 		},
 		// 查找树节点所有父节点
 		findParentNodeHandle(arr, id) {
@@ -1525,8 +1620,8 @@ export default {
 
 		initGetData() {
 			this.page_no = 1;
-			if(this.$refs.valueUl){
-				this.$refs.valueUl.scrollTop = 0;
+			if(this.$refs.edb_detail_data){
+				this.$refs.edb_detail_data.$refs.valueUl.scrollTop=0
 			}
 			this.getDataList();
 		},
@@ -1575,6 +1670,7 @@ export default {
 				if(res.Ret !== 200) return
 				this.setComputedDialogForm(Source,node,data,res.Data,true);
 				this.computed_type = [23,24].includes(Source) ? 'joint' : Source;
+				this.computed_type = [72,73].includes(data.Source)? 'alpha': data.Source;
 			})
 		},
 
@@ -1647,16 +1743,35 @@ export default {
 							moveVal: type === 22 ? dataInfo.CalculateFormula : '',
 							calendar_type: type === 35 ? dataInfo.Calendar : '',
 					}
+
+				if([72,73].includes(type)){
+					const {EdbName,EdbInfoId,Frequency,Unit,ClassifyId,CalculateFormula} = dataInfo
+					this.operationForm = {
+						edb_id: EdbInfoId,
+						oldedb_id: old_edb[0].FromEdbInfoId,
+						oldEdb_name: old_edb[0].FromEdbName,
+						EdbName,Frequency,Unit,ClassifyId,Formula:CalculateFormula,
+						view
+					}
+				}
 			}
 		},
 
 		/* 基础指标刷新 */
 		refreshBaseHandler() {
 			this.refreshLoading = true;
+			this.loading = this.$loading({
+					lock: true,
+					target:'.detail',
+					text: '刷新数据中...',
+					spinner: 'el-icon-loading',
+					background: 'rgba(255, 255, 255, 0.8)'
+				});
 			dataBaseInterface.refreshBaseTarget({
 				EdbInfoId: Number(this.selected_edbid)
 			}).then(res => {
 				this.refreshLoading = false;
+				this.loading&&this.loading.close()
 				if(res.Ret !== 200) return;
 				this.$message.success(res.Msg);
 				this.initDataStatus();
@@ -1673,7 +1788,9 @@ export default {
 		/* 重新刷新 重新计算后重置刷数据 */
 		initDataStatus() {
 			this.page_no = 1;
-			this.$refs.valueUl.scrollTop = 0;
+			if(this.$refs.edb_detail_data){
+				this.$refs.edb_detail_data.$refs.valueUl.scrollTop=0
+			}
 			this.getDataList();
 		},
 		/* 用于复制指标 */
@@ -1771,7 +1888,7 @@ export default {
 		changeTreeNode(){
 			this.$refs.menuTree.setCurrentKey(this.select_node);
 			this.$nextTick(()=>{
-				const _node = this.$refs.menuTree.getNode(this.select_node)
+				const _node = this.$refs.menuTree.getCurrentNode()
 				this.dynamicNode = _node;
 				this.dynamicNode&&this.resetNodeStyle(this.dynamicNode)
 			})
@@ -1806,8 +1923,41 @@ export default {
 			if(node.level>maxLevel){
 				resolve([])
 			}
-		}
 		},
+		//保存指标上下限
+		saveEdbLimit(){
+			if(!this.$refs.createChart) return
+			//获取指标的上下限
+			const {MaxValue=0,MinValue=0} = this.$refs.createChart.chartInfo
+			dataBaseInterface.saveEdbChartLimit({
+				EdbInfoId:this.EdbData.EdbInfoId,
+				MaxValue:Number(MaxValue),
+				MinValue:Number(MinValue)
+			}).then(res=>{
+				if(res.Ret!==200) return 
+				this.$message.success('保存成功')
+
+				this.$refs.createChart.saveEdbImg(this.EdbData)
+			})
+		},
+		//重绘指标图表
+		rePainChart(){
+			if(this.activeTab!=='Chart') return
+			this.$nextTick(()=>{
+				this.$refs.createChart.getDataByPath()
+			})
+		},
+		/* 展开对应菜单 显示详情 */
+		detailShowHandle({ UniqueCode, EdbInfoId,ClassifyId}) {
+			let params = {
+				code: UniqueCode,
+				id: EdbInfoId,
+				classifyId:ClassifyId
+			};
+			this.selectCurrentNode(params);
+			this.select_classifyId = 0;
+		},
+	},
 	//离开页面时保存标签
 	beforeRouteLeave(to,from,next){
 		sessionStorage.setItem('database',JSON.stringify(this.labelList))
@@ -1815,7 +1965,7 @@ export default {
 	},
 	mounted() {
 		this.getlabelList()
-
+		this.getEdbChartList()
 		this.$route.query.code 
 		? this.getTreeData({code: this.$route.query.code,id: this.$route.query.id,classifyId:this.$route.query.classifyId})
 		: this.getTreeData();
@@ -1891,7 +2041,7 @@ export default {
 			width: 5px !important;
 		}
 		.main-left {
-			width: 500px;
+			width: 400px;
 			min-width: 300px;
 			background: #fff;
 			margin-right: 20px;
@@ -1903,12 +2053,14 @@ export default {
 			position: relative;
 			box-sizing: border-box;
 			.tree-cont {
-				padding: 30px;
-				height: calc(100vh - 290px);
-				overflow: auto;
+				padding: 30px 0 30px 30px;
+				/* height: calc(100vh - 290px);
+				overflow: auto; */
 			}
 			.target_tree {
 				color: #333;
+				height: calc(100vh - 350px);
+				overflow: auto;
 				.label-input .el-input__inner {
 					height: 25px;
 					line-height: 25px;
@@ -1971,7 +2123,7 @@ export default {
 				}
 			}
 			.noDepart {
-				margin: 60px 0;
+				margin: 30px 0;
 				display: flex;
 				align-items: center;
 				justify-content: center;
@@ -1995,28 +2147,51 @@ export default {
 		.main-right {
 			flex: 1;
 			/* width:70%; */
-			height: calc(100vh - 288px);
+			height: calc(100vh - 225px);
 			background: #fff;
 			border: 1px solid #ececec;
 			border-radius: 4px;
 			box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
-			padding: 30px;
 			overflow: hidden;
 			.value-ul {
 				margin-top: 10px;
-				border-bottom: 1px solid #dcdfe6;
-				max-height: calc(100vh - 560px);
-				overflow-y: auto;
+				border-bottom: 1px solid #EBEFF6;
+				//max-height: calc(100vh - 495px);
+				//overflow-y: auto;
 				.value-item {
 					/* width: 100%; */
-					padding: 14px 0;
+					padding: 10px 0;
 					border: 1px solid #dcdfe6;
 					border-bottom: none;
 					display: flex;
 					justify-content: space-around;
+					>span{
+						padding:0 16px;
+						box-sizing: border-box;
+					}
 					.value-label {
 						position: relative;
 						color: #666;
+						.value-style{
+							/* background-color: #ECF2FE;
+							color: #0052D9; */
+							padding:5px;
+							border-radius: 4px;
+							&.predict-act {
+								color: orange;
+							}
+						}
+						&.date{
+							&::after{
+								content: '';
+								position:absolute;
+								right:0;
+								top:-14px;
+								height:calc(100% + 28px);
+								width:1px;
+								background-color: #dcdfe6;
+							}
+						}
 					}
 					.predict-act {
 						color: orange;
@@ -2039,6 +2214,134 @@ export default {
 					color: #999;
 				}
 			}
+			&.list{
+				background-color: transparent;
+				box-shadow: none;
+				border:none;
+				padding:0 30px;
+				display: flex;
+				flex-direction: column;
+				.list-wrap{
+					flex: 1;
+					margin-top: 20px;
+					display: flex;
+					gap: 20px;
+					flex-wrap: wrap;
+					overflow-x: hidden;
+					overflow-y: auto;
+					.dragShdow {
+						box-shadow: 0 1px 8px rgba(64, 158, 255, 0.8);
+						opacity: 0.5;
+					}
+					.list-item{
+						width:23%;
+						height:375px;
+						background-color: #fff;
+						display: flex;
+						flex-direction: column;
+						box-sizing: border-box;
+						/* padding: 0 10px; */
+						border-radius: 4px;
+						border:1px solid #DCDFE6;
+						box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+						.header,.info{
+							padding:20px;
+							box-sizing: border-box;
+							text-align: left;
+						}
+						.header{
+							//border-bottom: 1px solid #DCDFE6;
+							white-space: nowrap;
+							overflow: hidden;
+							text-overflow: ellipsis;
+							font-size: 16px;
+							font-weight: 600;
+							box-shadow: 0 3px 6px rgba(37, 37, 239, 0.1);
+						}
+						.image{
+							padding:20px 20px 0 20px;
+							flex: 1;
+							cursor: pointer;
+							img{
+								width:100%;
+								height: 230px;
+								object-fit: fill !important;
+							}
+						}
+					}
+				}
+			}
+			&.detail{
+				display: flex;
+				flex-direction: column;
+				>.header{
+					display: flex;
+					position: relative;
+					height: 60px;
+					.el-tabs{
+						width:200px;
+						.el-tabs__header{
+							margin-bottom: 0;
+						}
+						.el-tabs__nav{
+							display: flex;
+							width: 100%;
+							.el-tabs__item{
+								flex: 1;
+								text-align: center;
+								font-size: 16px;
+								height: 60px;
+								line-height: 60px;
+							}
+						}
+					}
+					.edb-tool{
+						flex: 1;
+						text-align: right;
+						display: flex;
+						gap: 16px;
+						justify-content: flex-end;
+						padding-right: 15px;
+						position: relative;
+						&::after{
+							position: absolute;
+							content:'';
+							width:100%;
+							left: 0;
+							bottom: 0;
+							height:2px;
+							background-color: #E4E7ED;
+						}
+					}
+				}
+				.container{
+					flex: 1;
+					overflow-y: auto;
+					padding:15px;
+					.chart{
+						.info{
+							display: flex;
+							justify-content: space-between;
+						}
+						.table{
+							margin-top: 16px;
+							border:1px solid #E7E7E7 ;
+							.table-header{
+								display: flex;
+								padding:6px;
+								span{
+									flex: 1;
+									border-bottom: 1px solid #E7E7E7;
+								}
+							}
+						}
+					}
+					.list{
+						height: 100%;
+					}
+				}
+			}
+
 		}
 	}
 	.dialog-computed {

+ 8 - 0
src/views/dataEntry_manage/onlineExcelCopy.vue

@@ -185,6 +185,14 @@ created() {
       luckysheet.create(this.options)
     })
   },
+  beforeRouteEnter(to, from, next){
+    if(to.query.isEdit=='true'){
+      to.matched[1].name='编辑excel数据'
+    }else{
+      to.matched[1].name='复制excel数据'
+    }
+    next()
+  },
   beforeRouteLeave(to, from, next) {
     luckysheet.destroy()
     next();

+ 1 - 1
src/views/dataEntry_manage/targetList.vue

@@ -522,7 +522,7 @@ export default {
 				up_time = '';
 				up_day = '';
 			}
-				this.editTitle="修改指标名称";
+				this.editTitle="编辑指标";
 				this.editFormData = {
 					type:item.ClassifyName,
 					frequency:item.Frequency,

+ 8 - 0
src/views/datasheet_manage/customSheetEdit.vue

@@ -82,6 +82,14 @@ import CustomTable from './components/CustomTable.vue'
 import html2canvas from 'html2canvas';
 export default {
   components: { selectTarget,CustomTable },
+  beforeRouteEnter(to, from, next) {
+    if(to.query.id){
+      to.matched[1].name=`编辑表格`
+    }else{
+      to.matched[1].name='添加表格'
+    }
+    next()
+  },
   data() {
     return {
       sheetId: this.$route.query.id || '',

+ 8 - 0
src/views/datasheet_manage/mixedSheetEdit.vue

@@ -61,6 +61,14 @@ import MixedTable from './components/MixedTable.vue'
 import html2canvas from 'html2canvas';
 export default {
   components: { selectTarget,MixedTable },
+  beforeRouteEnter(to, from, next) {
+    if(to.query.id){
+      to.matched[1].name=`编辑表格`
+    }else{
+      to.matched[1].name='添加表格'
+    }
+    next()
+  },
   data() {
     return {
       sheetId: this.$route.query.id || '',

+ 16 - 0
src/views/futures_manage/chartEditor.vue

@@ -580,6 +580,22 @@ export default {
 	},
 	destroyed() {
 		window.removeEventListener('resize', this.reloadRightWid);
+	},
+	beforeRouteEnter(to, from, next) {
+		if(to.query.code){
+			if(to.query.scence=='price'){
+				to.matched[1].name='编辑价格曲线'
+			}else{
+				to.matched[1].name='编辑利润曲线'
+			}
+		}else{
+			if(to.query.scence=='price'){
+				to.matched[1].name='添加价格曲线'
+			}else{
+				to.matched[1].name='添加利润曲线'
+			}
+		}
+		next()
 	}
 };
 </script>

+ 2 - 1
src/views/futures_manage/commodityChartBase.vue

@@ -747,7 +747,8 @@ export default {
 			this.$router.push({
         path: '/addCommodityChart',
         query: {
-          code: this.chartInfo.UniqueCode
+          code: this.chartInfo.UniqueCode,
+		  scence:this.chartInfo.Source==2?'price':'profit'
         }
       })
 		},

+ 139 - 0
src/views/login_manage/EmailModel.vue

@@ -0,0 +1,139 @@
+<template>
+    <div class="email-model-wrap model-wrap">
+        <el-form 
+            ref="modelForm" 
+            label-position="right" 
+            label-width="0px"
+            :model="form"
+            :rules="rules">
+            <el-form-item prop="email">
+                <el-input
+                    type="text"
+                    v-model="form.email"
+                    auto-complete="off"
+                    placeholder="请输入邮箱"
+                >
+                </el-input>
+                <span class="inline-message el-form-item__error" 
+                    v-show="(emailCheck||accountForbidden)&&form.email.length">
+                    {{hintMessage}}
+                </span>
+            </el-form-item>
+            <el-form-item prop="picCode">
+                <el-input
+                    class="input-with-slot"
+                    type="text"
+                    v-model="form.picCode"
+                    auto-complete="off"
+                    placeholder="请输入图形验证码"
+                >
+                    <div class="pic-box" slot="append" @click="getCodePic">
+                        <img :src="picSrc" alt="图形验证码"/>
+                    </div>
+                </el-input>
+            </el-form-item>
+            <el-form-item prop="checkCode" class="code-input">
+                <el-input
+                    type="text"
+                    v-model="form.checkCode"
+                    auto-complete="off"
+                    placeholder="请输入验证码"
+                ></el-input>
+                <el-button type="text" class="code-btn" @click="checkForm" :disabled="codeCountDown<60&&codeCountDown>0">{{codeStr}}</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+
+<script>
+import modelMixins from './modelMixins';
+import {patternEmail} from '@/utils/commonOptions'
+import {departInterence} from "@/api/api.js";
+export default {
+    mixins:[modelMixins],
+    props:{
+        emailCheck:{
+            type:Boolean,
+            default:false
+        },
+        accountForbidden:{
+            type:Boolean,
+            default:false
+        },
+        Source:{//请求验证码来源:1登陆
+            type:Number,
+            default:1
+        }
+    },
+    data() {
+        return {
+            hasPicCode:true,
+            picSrc:'',
+            picId:'',
+            timer:0,
+            codeStr:'获取验证码',
+            codeCountDown:60,
+            form:{
+                email:'',
+                picCode:'',
+                checkCode:''
+            },
+            rules:{
+                email:[
+                    {required:true,message:'请输入邮箱',trigger:'blur'},
+                    {validator:(rule,value,callback)=>{
+                        if(!patternEmail.test(value)){
+                            callback(new Error("请输入正确的邮箱格式"))
+                        }else{
+                            callback()
+                        }
+                    },trigger:'blur'}
+                ],
+                picCode:[{required:true,message:'请输入图形验证码',trigger:'blur'}],
+                checkCode:[{required:true,message:'请输入短信验证码',trigger:'blur'}]
+            },
+            hintMessage:''
+        };
+    },
+    methods: {
+        checkForm(){
+            //首先检查是否是重新获取验证码
+            if(this.codeStr==='重新获取'){
+                //引导用户重新输入图形验证码
+                this.getCodePic()
+                this.form.picCode = ''
+            }
+            //检查邮箱和图形验证码是否正确
+            const {email,picCode} = this.form
+            if(!picCode.length){
+                this.$message.warning('请输入图形验证码')
+                return
+            }
+            if(!patternEmail.test(email)){
+                this.$message.warning('请输入正确的邮箱')
+                return
+            }
+            //通过请求发送验证码
+            departInterence.getCodeVerify({
+                VerifyType:2,
+                CaptchaId:this.picId,
+                CaptchaCode:picCode,
+                Email:email,
+                Source:this.Source
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success('验证码已发送')
+                //60秒倒计时
+                this.countDown()
+                this.timer = setInterval(()=>{
+                    this.countDown()
+                },1000)
+            })
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+@import "./css/formStyle.scss";
+</style>

+ 339 - 0
src/views/login_manage/ForgetPassModel.vue

@@ -0,0 +1,339 @@
+<template>
+    <div class="forget-pass-model">
+        <div class="header-nav" @click="changeModel">
+            <span><i class="el-icon-back"></i></span>
+            <span>忘记密码</span>
+        </div>
+        <div class="step-container model-wrap" v-show="currentStep===0">
+            <el-form 
+                ref="modelForm" 
+                label-position="right" 
+                label-width="0px"
+                :model="form"
+                :rules="rules">
+                <el-form-item prop="account">
+                    <el-input
+                        type="text"
+                        v-model="form.account"
+                        auto-complete="off"
+                        placeholder="请输入账号">
+                    </el-input>
+                </el-form-item>
+                <el-form-item prop="picCode">
+                    <el-input
+                        class="input-with-slot"
+                        type="text"
+                        v-model="form.picCode"
+                        auto-complete="off"
+                        placeholder="请输入图形验证码"
+                    >
+                        <div class="pic-box" slot="append" @click="getCodePic">
+                            <img :src="picSrc" alt="图形验证码"/>
+                        </div>
+                    </el-input>
+                </el-form-item>
+            </el-form>
+            <el-button class="submit_btn" @click="getUserInfo">下一步</el-button>
+        </div>
+        <div class="step-container" v-show="currentStep>0">
+            <div class="container-header">
+                <p>您正在找回账号{{form.account}}的密码</p>
+                <ModelSteps :active-step="currentStep"/>
+            </div>
+            <div class="container-inner model-wrap" v-show="currentStep===1">
+                <VerificationBox
+                    verifies-type="mobile"
+                    :info-text="userMobile||'暂未绑定'"
+                    :hideBtn="!userMobile"
+                    @goNext="getCode"
+                />
+                <VerificationBox
+                    verifies-type="email"
+                    :info-text="userEmail||'暂未绑定'"
+                    :hideBtn="!userEmail"
+                    @goNext="getCode"
+                />
+            </div>
+            <div class="container-inner" v-show="currentStep===2">
+                <CaptchaInput 
+                    ref="captInput"
+                />
+                <div class="btn-wrap">
+                    <el-button type="primary" plain @click="changeModel">上一步</el-button>
+                    <el-button type="primary" @click="checkInput">下一步</el-button>
+                </div>
+                
+            </div>
+            <div class="container-inner model-wrap" v-show="currentStep===3">
+                <el-form 
+                    ref="passForm" 
+                    label-position="right" 
+                    label-width="0px"
+                    :model="passForm"
+                    :rules="passRules">
+                    <el-form-item prop="pass1">
+                        <el-input
+                            type="password" show-password
+                            v-model.trim="passForm.pass1"
+                            auto-complete="off"
+                            @copy.native.capture.prevent="()=>{return false}"
+                            @cut.native.capture.prevent="()=>{return false}"
+                            @paste.native.capture.prevent="()=>{return false}"
+                            placeholder="请输入新密码">
+                        </el-input>
+                    </el-form-item>
+                    <el-form-item prop="pass2">
+                        <el-input
+                            type="password" show-password
+                            v-model.trim="passForm.pass2"
+                            auto-complete="off"
+                            @copy.native.capture.prevent="()=>{return false}"
+                            @cut.native.capture.prevent="()=>{return false}"
+                            @paste.native.capture.prevent="()=>{return false}"
+                            placeholder="请确认新密码">
+                        </el-input>
+                    </el-form-item>
+                </el-form>
+                <el-button class="submit_btn" @click="handleResetPass">{{checkPassStr}}</el-button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import CaptchaInput from './components/CaptchaInput.vue';
+import ModelSteps from './components/ModelSteps.vue';
+import VerificationBox from './components/VerificationBox.vue';
+import modelMixins from './modelMixins';
+import{checkPassWord} from '@/utils/commonOptions';
+import http from '@/api/http.js';
+import {departInterence } from "@/api/api.js";
+export default {
+    mixins:[modelMixins],
+    props:{
+        autoAccount:{//自动填写的账号,如果有,作为form.accout的初始值
+            type:String,
+            default:''
+        }
+    },
+    components: { VerificationBox, ModelSteps, CaptchaInput },
+    data() {
+        const validatePass = (rule,value,callback)=>{
+            if(value===''){
+                callback(new Error('请输入新密码'))
+            }
+            if(this.passForm.pass2!==''){
+                this.$refs.passForm.validateField('pass2')
+            }
+            if(!checkPassWord(value)){
+                callback(new Error('密码要求8位及以上,包含数字、大写字母、小写字母、特殊字符中的三个类型'))
+            }else{
+                callback()
+            }
+        }
+        const validateCheck = (rule,value,callback)=>{
+            if(value===''){
+                callback(new Error('请输入确认密码'))
+            }else if(value!==this.passForm.pass1){
+                callback(new Error('两次输入的密码不一致,请检查'))
+            }else{
+                callback()
+            }
+        }
+        return {
+            currentStep:0,
+            /* form */
+            form:{//步骤0的表单
+                account:this.autoAccount,
+                picCode:''
+            },
+            picSrc:'',
+            picId:'',
+            passForm:{//设置新密码的表单
+                pass1:'',
+                pass2:''
+            },
+            /* form rule */
+            rules:{},
+            passRules:{
+                pass1:[{validator: validatePass,trigger: 'blur'}],
+                pass2:[{validator: validateCheck,trigger: 'blur'}]
+            },
+            /*user info */
+            userMobile:'',//用户的手机号
+            TelAreaCode:'',//用户手机号的区号
+            userEmail:'',//用户的邮箱
+            /* check way */
+            checkWay:'',//选择的验证方式
+            authCode:'',//手机/邮箱验证码,从CaptchaInput组件中取
+            mobileCountDown:0,//手机获取验证码倒计时
+            emailCountDown:0,//邮箱验证码倒计时
+            checkPassStr:'确定',//重置密码按钮
+            countDownNum:5,
+            resetPassTimer:0,
+        };
+    },
+    created(){
+        this.getCodePic()
+    },
+    methods: {
+        //获取用户账号信息
+        getUserInfo(){
+            //检查form是否填写完整
+            const {account,picCode} = this.form
+            if(!account){
+                this.$message.warning('请输入账号')
+                return
+            }
+            if(!picCode){
+                this.$message.warning('请输入图形验证码')
+                return
+            }
+            //请求接口获取账号数据,赋值userMobile,userEmail
+            departInterence.accountCheck({
+                CaptchaId:this.picId,
+                CaptchaCode:picCode,
+                UserName:account
+            }).then(res=>{
+                if(res.Ret!==200){
+                    //刷新图形验证码
+                    this.getCodePic()
+                    this.form.picCode=''
+                    return
+                }
+                if(res.Data){
+                    this.userMobile = res.Data.Mobile||''
+                    this.userEmail = res.Data.Email||''
+                    this.TelAreaCode = res.Data.TelAreaCode||''
+                    this.goSteps()
+                }
+                
+            })
+        },
+        //获取对应验证方式的验证码
+        getCode(way){
+            this.checkWay = way
+            departInterence.getCodeVerify({
+                VerifyType:way==='mobile'?1:2,
+                CaptchaId:this.picId,
+                CaptchaCode:this.form.picCode,
+                Mobile:way==='mobile'?this.userMobile:'',
+                TelAreaCode:way==='mobile'?this.TelAreaCode:'',
+                Email:way==='email'?this.userEmail:'',
+                Source:3
+            }).then(res=>{
+                if(res.Ret!==200) return
+                /* //60秒倒计时
+                this.countDown()
+                this.timer = setInterval(()=>{
+                    this.countDown()
+                },1000)
+                this.goSteps() */
+                this.goSteps()
+            })
+        },
+        //检查输入的验证码
+        checkInput(){
+            const code = this.$refs.captInput.captchas.map((x) => x.num).join("");
+            if(code.length!==6){
+                this.$message.warning('请输入完整的验证码')
+                return
+            }
+            departInterence.checkCodeVerify({
+                FindType:this.checkWay==='mobile'?1:2,
+                VerifyCode:code,
+                UserName:this.form.account,
+                Mobile:this.checkWay==='mobile'?this.userMobile:'',
+                Email:this.checkWay==='email'?this.userEmail:''
+            }).then(res=>{
+                if(res.Ret!==200) return
+                this.goSteps()
+            })
+
+        },
+        goSteps(){
+            this.currentStep++
+        },
+        changeModel(){
+            if(this.currentStep>0){
+                this.currentStep--
+                if(this.currentStep===0){
+                    this.getCodePic()
+                    this.form.picCode = ''
+                }
+            }else{
+                this.$emit('changeModel')
+            }
+            
+        },
+        handleResetPass(){
+            if(this.checkPassStr.includes('去登陆')){
+                this.$emit('changeModel')
+                return
+            }
+            this.$refs.passForm.validate((valid)=>{
+                if(valid){
+                    //重置密码
+                    departInterence.resetPass({
+                        UserName:this.form.account,
+                        Password:new http.Base64().encode(this.passForm.pass1),
+                        RePassword:new http.Base64().encode(this.passForm.pass2)
+                    }).then(res=>{
+                        if(res.Ret!==200) return
+                        this.$message.success('重置密码成功,请登陆')
+                        this.resetPassCountDown()
+                        this.resetPassTimer = setInterval(()=>{
+                            this.resetPassCountDown()
+                        },1000)
+                    })
+                }
+            })
+        },
+        resetPassCountDown(){
+            this.countDownNum--
+            this.checkPassStr = `去登陆(${this.countDownNum}s)`
+            if(this.countDownNum<=0){
+                clearInterval(this.resetPassTimer)
+                this.$emit('changeModel')
+                return
+            }
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+@import "./css/formStyle.scss";
+</style>
+<style scoped lang="scss">
+.forget-pass-model{
+    .header-nav{
+        font-size: 38px;
+        margin-bottom: 60px;
+        cursor: pointer;
+    }
+    .step-container{
+        .container-header{
+            margin-bottom: 60px;
+            p{
+               font-size: 18px;
+               padding-bottom: 20px;
+               border-bottom: 1px solid #DCDFE6; 
+               margin-bottom: 60px;
+            }
+            .el-steps{
+                margin-top: 60px;
+            }
+        }
+        .container-inner{
+            .btn-wrap{
+                margin-top: 100px;
+                text-align: center;
+                .el-button{
+                    width:200px;
+                }
+            }
+        }
+    }
+}
+</style>

+ 156 - 0
src/views/login_manage/MobileModel.vue

@@ -0,0 +1,156 @@
+<template>
+    <div class="mobile-model-wrap model-wrap">
+        <el-form 
+            ref="modelForm" 
+            label-position="right" 
+            label-width="0px"
+            :model="form"
+            :rules="rules">
+            <el-form-item prop="mobile">
+                <el-input
+                    class="input-with-slot"
+                    type="text"
+                    v-model="form.mobile"
+                    auto-complete="off"
+                    placeholder="请输入手机号"
+                >
+                    <el-select v-model="areaCodeSelect" slot="prepend" placeholder="请选择">
+                        <el-option v-for="item in areaCode" :key="item.Value"
+                            :label="item.Name" :value="item.Value" />
+                    </el-select>
+                </el-input>
+                <span class="inline-message el-form-item__error" 
+                    v-show="(mobileCheck||accountForbidden)&&form.mobile.length">
+                    {{hintMessage}}
+                </span>
+            </el-form-item>
+            <el-form-item prop="picCode">
+                <el-input
+                    class="input-with-slot"
+                    type="text"
+                    v-model="form.picCode"
+                    auto-complete="off"
+                    placeholder="请输入图形验证码"
+                >
+                    <div class="pic-box" slot="append" @click="getCodePic">
+                        <img :src="picSrc" alt="图形验证码"/>
+                    </div>
+                </el-input>
+            </el-form-item>
+            <el-form-item prop="checkCode" class="code-input">
+                <el-input
+                    type="text"
+                    v-model="form.checkCode"
+                    auto-complete="off"
+                    placeholder="请输入验证码">
+                </el-input>
+                <el-button type="text" class="code-btn" @click="checkForm" :disabled="codeCountDown<60&&codeCountDown>0">{{codeStr}}</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+
+<script>
+import modelMixins from './modelMixins';
+import {isMobileNo} from '@/utils/commonOptions'
+import {departInterence } from "@/api/api.js";
+export default {
+    mixins:[modelMixins],
+    props:{
+        mobileCheck:{
+            type:Boolean,
+            default:false
+        },
+        accountForbidden:{
+            type:Boolean,
+            default:false
+        },
+        areaCode:{
+            type:Array,
+            default:()=>{return []}
+        },
+        Source:{//请求验证码来源:1登陆
+            type:Number,
+            default:1
+        }
+    },
+    data() {
+        return {
+            hasPicCode:true,//是否需要图形验证码
+            areaCodeSelect:'86',
+            picSrc:'',//图形验证码地址
+            picId:'',//图形验证码id
+            timer:0,
+            codeStr:'获取验证码',
+            codeCountDown:60,
+            form:{
+                mobile:'',
+                picCode:'',
+                checkCode:''
+            },
+            rules:{
+                mobile:[
+                    {required: true,message: "请输入手机号",trigger: "blur"},
+                    {validator:(rule,value,callback)=>{
+                        if(this.areaCodeSelect==='86'&&!isMobileNo(value)){
+                            callback(new Error('请输入正确的手机号格式'));
+                        }else if(this.areaCodeSelect!=='86'&&isNaN(value.trim())){
+                            callback(new Error('请输入正确的手机号格式'));
+                        }else{
+                            callback()
+                        }
+                    },trigger:'blur'}
+                ],
+                picCode:[{required:true,message:'请输入图形验证码',trigger:'blur'}],
+                checkCode:[{required:true,message:'请输入短信验证码',trigger:'blur'}]
+            }
+        };
+    },
+    methods: {
+        checkForm(){
+            //首先检查是否是重新获取验证码
+            if(this.codeStr==='重新获取'){
+                //引导用户重新输入图形验证码
+                this.getCodePic()
+                this.form.picCode = ''
+            }
+            //检查手机号和图形验证码是否正确
+            const {picCode,mobile} = this.form
+            if(!picCode.length){
+                this.$message.warning('请输入图形验证码')
+                return
+            }
+            if(this.areaCodeSelect==='86'&&!isMobileNo(mobile)){
+                this.$message.warning('请输入正确的手机号')
+                return
+            }
+            /* this.countDown()
+                this.timer = setInterval(()=>{
+                    this.countDown()
+                },1000) */
+            //通过请求发送验证码
+            departInterence.getCodeVerify({
+                VerifyType:1,
+                CaptchaId:this.picId,
+                CaptchaCode:picCode,
+                Mobile:mobile,
+                TelAreaCode:this.areaCodeSelect,
+                Source:this.Source
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success('验证码已发送')
+                //60秒倒计时
+                this.countDown()
+                this.timer = setInterval(()=>{
+                    this.countDown()
+                },1000)
+            })
+
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+@import "./css/formStyle.scss";
+</style>

+ 117 - 0
src/views/login_manage/OrdinaryModel.vue

@@ -0,0 +1,117 @@
+<template>
+    <div class="ordinary-model-wrap model-wrap">
+        <el-form 
+            ref="modelForm" 
+            label-position="right" 
+            label-width="0px"
+            :model="form"
+            :rules="rules">
+            <el-form-item prop="account">
+                <el-input
+                    type="text"
+                    v-model="form.account"
+                    auto-complete="off"
+                    placeholder="请输入用户名"
+                />
+                <span class="inline-message el-form-item__error" 
+                    v-show="(loginCheck||accountCheck)&&form.account.length">
+                    {{hintMessage}}
+                </span>
+            </el-form-item>
+            <el-form-item prop="checkPass">
+                <el-input
+                    type="password" show-password
+                    v-model="form.checkPass"
+                    auto-complete="off"
+                    placeholder="请输入密码"
+                    @copy.native.capture.prevent="()=>{return false}"
+                    @cut.native.capture.prevent="()=>{return false}"
+                    @paste.native.capture.prevent="()=>{return false}"
+                />
+                <span class="inline-message el-form-item__error" 
+                    v-show="(loginCheck||accountCheck)&&form.checkPass.length">
+                    {{hintMessage}}</span>
+            </el-form-item>
+            <el-form-item class="remember-cont" prop="checked">
+                <el-checkbox v-model="form.checked" class="remember">
+                    记住账号密码
+                    <el-tooltip effect="dark" content="有效期60天" placement="top">
+                        <span class="hint-text">
+                            <i class="el-icon-question"></i>
+                        </span>
+                    </el-tooltip>
+                </el-checkbox>
+                <el-button type="text" style="font-size: 16px;" @click="changeModel">忘记密码</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+
+<script>
+import modelMixins from './modelMixins';
+export default {
+    mixins:[modelMixins],
+    props:{
+        loginCheck:{
+            type:Boolean,
+            default:false
+        },
+        accountCheck:{
+            type:Boolean,
+            default:false
+        }
+    },
+    data() {
+        const validateClearn = (rule,value,callBack)=>{
+            if(this.loginCheck||this.accountCheck){
+                this.$emit('clearnHint')
+            }
+            callBack()
+        }
+        return {
+            form:{
+                account:'',
+                checkPass:'',
+                checked:false
+            },
+            rules:{
+                account:[
+                    {required: true,message: "请输入账号",trigger: "blur"},
+                    {validator:validateClearn,trigger:['change']}
+                ],
+                checkPass:[
+                    {required: true,message: "请输入密码",trigger: "blur"},
+                    {validator:validateClearn,trigger:['change']}
+                ]
+            },
+            hintMessage:''
+        };
+    },
+    watch:{
+        loginCheck(newVal){
+            //显示/隐藏inline-message
+            if(newVal){
+                this.hintMessage="账号或密码错误"
+            }else{
+                this.hintMessage=''
+            }
+        },
+        accountCheck(newVal){
+            if(newVal){
+                this.hintMessage="账号异常,请通过验证登录"
+            }else{
+                this.hintMessage=''
+            }
+        }
+    },
+    methods: {
+        changeModel(){
+            this.$emit('changeModel')
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+@import "./css/formStyle.scss";
+</style>

+ 108 - 0
src/views/login_manage/components/CaptchaInput.vue

@@ -0,0 +1,108 @@
+<template>
+    <!-- 格子验证码输入组件 -->
+    <div class="row-center captcha_input_wrap">
+        <input
+            v-for="(item, index) in captchas"
+            :key="index"
+            v-model="item.num"
+            :id="'captcha' + index"
+            @input="inputFinash(index)"
+            @focus="adjust(index)"
+            @keydown="(e)=>{inputDirection(index,e)}"
+            class="captcha_input_box row-center"
+            :class="[index <= activeInput ? 'active' : '']"
+            type="tel"
+            maxlength="1"
+        />
+  </div>
+</template>
+  
+  <script>
+export default {
+  data() {
+    return {
+      // 当前输入框
+      activeInput: 0,
+      captchas: [
+        { num: "" },
+        { num: "" },
+        { num: "" },
+        { num: "" },
+        { num: "" },
+        { num: "" },
+      ],
+    };
+  },
+  //   页面加载后聚焦第一个
+  mounted() {
+    let dom = document.getElementById("captcha" + this.activeInput);
+    dom.focus();
+  },
+ 
+  methods: {
+    // 自动校准输入顺序
+    adjust(index) {
+      let dom = document.getElementById("captcha" + this.activeInput);
+      if (index !== this.activeInput && dom) {
+        dom.focus();
+      }
+    },
+    // 控制前后方向
+    inputDirection(index,e) {
+      let val = this.captchas[index].num;
+      // 回退键处理
+      if (e.key==='Backspace' && val === "") {
+        // 重新校准
+        let dom = document.getElementById("captcha" + (index - 1));
+        this.activeInput = index - 1;
+        if (dom) dom.focus();
+      }
+      if (e.key!=='Backspace' && val !== "") {
+        let dom = document.getElementById("captcha" + (index + 1));
+        this.activeInput = index + 1;
+        if (dom) dom.focus();
+      }
+    },
+    // 输入框相互联动
+    inputFinash(index) {
+      let val = this.captchas[index].num;
+      this.activeInput = val ? index + 1 : index - 1;
+      let dom = document.getElementById("captcha" + this.activeInput);
+      if (dom) dom.focus();
+      if (index == this.captchas.length - 1) {
+        let code = this.captchas.map((x) => x.num).join("");
+        if (code.length == 6) {
+          this.$emit("finish", code);
+        }
+      }
+    },
+  },
+};
+</script>
+  
+<style scoped lang='scss'>
+.row-center {
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    gap:40px;
+}
+.captcha_input_wrap {
+    width: 100%;
+}
+.captcha_input_box {
+    width: 40px;
+    height: 40px;
+    background: rgba(255, 255, 255, 1);
+    border-radius: 6px;
+    border: 1px solid #dddddd;
+    font-size: 16px;
+    text-align: center;
+    color: #1e243a;
+    outline: none;
+}
+.active {
+    border: 1px solid #3654C1 !important;
+}
+</style>

+ 99 - 0
src/views/login_manage/components/ModelSteps.vue

@@ -0,0 +1,99 @@
+<template>
+    <ul class="model-step-wrap">
+        <li v-for="(step,index) in stepList" :key="step.text"
+            class="step-item"
+            :class="{'active':index+1===activeStep,'success':index+1<activeStep}"
+        >   
+            <div class="step-line"></div>
+            <div class="step-num" v-if="index+1>=activeStep">{{index+1}}</div>
+            <div class="step-num" v-else><i class="el-icon-check"></i></div>
+            <div class="step-text">{{step.text}}</div>
+            
+        </li>
+    </ul>
+</template>
+
+<script>
+export default {
+    props:{
+        stepList:{
+            type:Array,
+            default:()=>{
+                return [
+                    {text:'选择验证方式'},
+                    {text:'进行安全验证'},
+                    {text:'设置密码'}
+                ]
+            }
+        },
+        activeStep:{
+            type:Number,
+            default:1
+        }
+    },
+    data() {
+        return {
+
+        };
+    },
+    methods: {
+
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.model-step-wrap{
+    display: flex;
+    justify-content: center;
+    width: 100%;
+    .step-item{
+        display: flex;
+        align-items: center;
+        gap: 12px;
+        color: #DCDCDC;
+        font-size: 20px;
+        &:first-child{
+            .step-line{
+                display: none;
+            }
+        }
+        &:last-child{
+            .step-text{
+                margin-right: 0;
+            }
+        }
+        &.active,&.success{
+            color:#3654C1;
+            .step-num{
+                border-color: #3654C1;
+                color: #3654C1;
+            }
+            .step-line{
+                background-color: #3654C1;
+            }
+        }
+        &.success{
+            color: #000;
+        }
+        .step-num{
+            width:24px;
+            height:24px;
+            font-size: 16px;
+            border:1px solid #DCDCDC;
+            border-radius: 50%;
+            text-align: center;
+            line-height: 25px;
+        }
+        .step-line{
+           flex: 1;
+           height:2px;
+           background-color:#DCDCDC ;
+           min-width: 40px;
+        }
+        .step-text{
+            margin-right: 16px;
+        }
+    }
+}
+</style>

+ 79 - 0
src/views/login_manage/components/VerificationBox.vue

@@ -0,0 +1,79 @@
+<template>
+    <div class="verification-box-wrap">
+        <div class="icon">
+            <img :src="verifiesType==='mobile'?mobile_src:email_src" />
+        </div>
+        <div class="text">{{infoText}}</div>
+        <el-button  type="primary" @click="goNext" v-if="!hideBtn" :disabled="countDown">{{countDown?`重发(${countDown}秒)`:btnText}}</el-button>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        verifiesType:{//安全验证 mobile or email
+            type:String,
+            default:'mobile'
+        },
+        infoText:{//手机号或邮箱
+            type:String,
+            default:'123456'
+        },
+        hideBtn:{
+            type:Boolean,
+            default:false
+        },
+        countDown:{
+            type:Number,
+            default:0
+        },
+        btnText:{
+            type:String,
+            default:'开始验证'
+        }
+    },
+    data() {
+        return {
+            mobile_src:require('@/assets/img/home/phone_icon.png'),
+            email_src:require('@/assets/img/home/email_icon.png'),
+        };
+    },
+    methods: {
+        goNext(){
+            this.$emit('goNext',this.verifiesType)
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.verification-box-wrap{
+    display: flex;
+    align-items: center;
+    margin-bottom: 60px;
+    cursor: pointer;
+    .icon{
+        width:40px;
+        height:40px;
+        box-sizing: border-box;
+        padding:8px;
+        border-radius: 50%;
+        box-shadow: 0px 2px 12px 0px #0000001A;
+        text-align: center;
+        img{
+            width: 24px;
+            height: 24px;
+        }
+    }
+    .text{
+        margin-left: 20px;
+        font-size: 18px;
+    }
+    .el-button{
+        /* background-color: #3654C1;
+        color: #fff; */
+        margin-left: auto;
+    }
+}
+
+</style>

+ 111 - 0
src/views/login_manage/css/formStyle.scss

@@ -0,0 +1,111 @@
+.model-wrap{
+    margin-top: 25px;
+    .remember-cont{
+        margin-top: -10px;
+        margin-bottom: 60px !important;
+        width: 100%;
+        .hint-text{
+            color: #606266 !important;
+            font-size: 16px;
+        }
+        .el-form-item__content{
+            display: flex;
+            width: 100%;
+            justify-content: space-between;
+            .remember{
+                flex: 1;
+                .el-checkbox__label{
+                    font-size: 16px;
+                }
+            }
+        }
+    }
+    .el-form-item{
+        margin-bottom: 40px;
+        .el-input__inner{
+            height: 50px;
+            border-radius: 8px;
+            font-size: 16px;
+        }
+    }
+    .el-form-item.is-error{
+        .inline-message{
+            display: none;
+        }
+    }
+    .input-with-slot{
+        display: flex;
+        &.el-input-group--prepend{
+            .el-input__inner{
+                border-top-left-radius: 0;
+                border-bottom-left-radius: 0;
+            }
+        }
+        &.el-input-group--append{
+            .el-input__inner{
+                border-top-right-radius: 0;
+                border-bottom-right-radius: 0;
+            }
+        }
+        .el-input__inner{
+            flex: 1;
+            height: 50px !important;
+        }
+        .el-input-group__prepend,.el-input-group__append{
+            padding:0 !important;
+            background-color: #fff;
+            width:110px;
+            height: 50px;
+            box-sizing: border-box;
+            overflow: hidden;
+            .el-input__inner{
+                padding:0;
+            }
+            .el-select{
+                margin:0;
+                width:110px;
+                .el-input__inner{
+                    width:100%;
+                    text-align: center;
+                }
+            }
+        }    
+        .pic-box{
+            cursor: pointer;
+            width:110px;
+            height:50px;
+            overflow: hidden;
+            padding:5px;
+            box-sizing: border-box;
+            background-color: #D7F1F6;
+            img{
+                width: 100%;
+                height: 100%;
+            }
+        }
+        .code{
+            display: inline-block;
+            width:100%;
+            text-align: center;
+            line-height: 40px;
+            cursor: pointer;
+        }
+    }
+    .submit_btn {
+        width: 100%;
+        height: 50px;
+        background: #3654C1;
+        font-size: 20px;
+        border-radius: 5px;
+        color: #fff;
+    }
+    .code-input{
+        position:relative;
+        .code-btn{
+            position:absolute;
+            top:5px;
+            right: 20px;
+            font-size: 16px;
+        }
+    }
+}

+ 34 - 0
src/views/login_manage/modelMixins.js

@@ -0,0 +1,34 @@
+import {departInterence } from "@/api/api.js";
+export default {
+    methods:{
+        modelInit(){
+            //重置表单
+            this.form = this.$options.data().form
+            //如果有图形验证码,重新请求
+            this.hasPicCode && this.getCodePic()
+        },
+        //获取图片验证码
+        getCodePic(){
+            //存base64和id
+            departInterence.getCodePic().then(res=>{
+                if(res.Ret!==200) return 
+                if(res.Data){
+                    this.picSrc = res.Data.Base64Blob,
+                    this.picId = res.Data.Id
+                }
+                
+            })
+        },
+        countDown(){
+            /* if(!this.timer) return */
+            console.log('click down')
+            this.codeCountDown--
+            this.codeStr=`重新获取(${this.codeCountDown})秒`
+            if(this.codeCountDown<=0){
+                clearInterval(this.timer)
+                this.codeStr = '重新获取'
+                return
+            }
+        }
+    }
+}

+ 23 - 9
src/views/ppt_manage/mixins/pptMixins.js

@@ -10,7 +10,7 @@ import futuresInterface from '@/api/modules/futuresBaseApi';
 import { fittingEquationInterface,statisticFeatureInterface } from '@/api/modules/chartRelevanceApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi.js';
 import { defaultOpts } from '@/utils/defaultOptions';
-import {formatPPTDate,checkPPTpageElemant,getStrSize} from '../newVersion/utils/untils.js';
+import {formatPPTDate,checkPPTpageElemant,getStrSize,isShowPPTTitle} from '../newVersion/utils/untils.js';
 import FormatOne from '../newVersion/components/formatPage/FormatOne.vue';
 import FormatTwo from '../newVersion/components/formatPage/FormatTwo.vue';
 import FormatThree from '../newVersion/components/formatPage/FormatThree.vue';
@@ -39,8 +39,12 @@ export default {
       pageLoading:null,//演示时,切换page需要加载图表数据
       publishLoading:null,//发布时loading
       pptCoverList:[],//配置ppt封面
-      pptBgImage:'',
-      pptBackImage:'',
+      pptBgImage:'',//ppt背景图
+      pptBackImage:'',//ppt封底
+      pptCoverCompenyName:'',//封面公司名称
+      pptCoverDepartName:'',//封面部门名称
+      pptCoverTextColor:'',//控制上面两个字段展示的颜色
+
 
       setEnName:false,
       // 传入的formItem所需内容
@@ -56,21 +60,27 @@ export default {
     }
   },
   methods: {
-    //获取ppt配置
+    //获取基本配置-ppt配置
     async getpptConfig(){
         const res = await etaBaseConfigInterence.getBaseConfig()
         if(res.Ret!==200) return 
-        const {CnPptCoverImgs,CnPptBackgroundImg,CnPptBottomImg,
-               EnPptCoverImgs,EnPptBackgroundImg,EnPptBottomImg,
+        const {CnPptCoverImgs,CnPptBackgroundImg,CnPptBottomImg,PptCompanyName,PptTeamName,PptFontColor,
+               EnPptCoverImgs,EnPptBackgroundImg,EnPptBottomImg,PptCompanyNameEn,PptTeamNameEn,PptFontColorEn
               } = res.Data
         if(this.currentLang==='en'){
             this.pptCoverList = EnPptCoverImgs.split(',')
             this.pptBgImage = EnPptBackgroundImg
             this.pptBackImage = EnPptBottomImg
+            this.pptCoverCompenyName = PptCompanyNameEn
+            this.pptCoverDepartName = PptTeamNameEn
+            this.pptCoverTextColor = PptFontColorEn
         }else{
             this.pptCoverList = CnPptCoverImgs.split(',')
             this.pptBgImage = CnPptBackgroundImg
             this.pptBackImage = CnPptBottomImg
+            this.pptCoverCompenyName = PptCompanyName
+            this.pptCoverDepartName = PptTeamName
+            this.pptCoverTextColor = PptFontColor
         }
     },
     //获取ppt详情
@@ -402,10 +412,14 @@ export default {
         MyChartType: 2 季节性图,7 柱形图,  10 截面散点图,
         Source:2
         MyChartType: 8 商品价格曲线图
+        Source:5
+        MyChartType: 8 利润曲线
+        Source:6 拟合方程曲线
+        Source:7 统计特征
         以上图表需要显示标题
       */
      const {Source,MyChartType} = options
-     const isShowTitle = Source===1&&[2,7,10].includes(MyChartType)||Source===2&&MyChartType===8
+     const isShowTitle = isShowPPTTitle(Source,MyChartType)
       this.$nextTick(() => {
         let is_linear = options.series 
           ? options.series.every(_ => _.type === 'scatter' ) || options.series.some(_ => _.chartType === 'linear'  )
@@ -418,7 +432,7 @@ export default {
         let {total,newStr} = getStrSize(options.MyChartTitle,count)
         const isPublish = this.$route.path==='/pptpublish'||this.$route.path==='/pptenpublish'
         if(isShowTitle){
-          titleHTML = `<div style="white-space: normal;">${options.MyChartTitle}</div>`
+          titleHTML = `<div style="white-space: normal;font-size:18px;">${options.MyChartTitle}</div>`
         }
         let SpecialOption = {
           chart: {
@@ -429,7 +443,7 @@ export default {
           title: isPublish?{
             text: isShowTitle?newStr:null,
             useHTML:false,
-            style:{},
+            style:{fontSize:'18px'},
             align:total>count?'left':'center',
           }:{
             text: titleHTML,

+ 9 - 9
src/views/ppt_manage/newVersion/components/Cover.vue

@@ -1,23 +1,23 @@
 <template>
-    <div class="flex-column cover" style="width:100%;" v-if="pageInfo">
+    <div class="flex-column cover" :style="`width:100%;color: ${$parent.pptCoverTextColor||'#fff'};`" v-if="pageInfo">
         <!-- <img :src="pageInfo.BackgroundImg" class="pptbg" /> -->
         <!-- <img :src="base64Url" class="pptbg" /> -->
         <img :src="pageInfo.BackgroundImg" class="pptbg"  style="width:100%"/>
         <div
-        style="width:62%; font-size:16px; text-align:center; line-height:1.6; color:#fff; position:absolute; right:20px; top:50%;zIndex:20;">
-        <p style="height:5px; border-top:1px solid #fff;marginBottom:21px;"></p>
+        style="width:62%; font-size:16px; text-align:center; line-height:1.6;  position:absolute; right:20px; top:50%;zIndex:20;">
+        <p :style="`height:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};marginBottom:21px;`"></p>
         <p style="font-size:28px;">{{ pageInfo.Title }}</p>
         <p style="display:flex; align-items:center; justify-content:center;margin:10px 0;">
-            <span style="display:inline-block; width:15px; margin-right:5px; border-top:1px solid #fff;"></span>
-            <span>弘则弥道(上海)投资咨询有限公司</span>
+            <span :style="`display:inline-block; width:15px; margin-right:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>
+            <span :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverCompenyName||'ETA'}}</span>
             <span
-            style="display:inline-block; width:14px; height:14px; background:#fff; border-radius:100%; margin:0 5px;"></span>
+            :style="`display:inline-block; width:14px; height:14px; background:${$parent.pptCoverTextColor||'#fff'}; border-radius:100%; margin:0 5px;`"></span>
             <span>{{ pageInfo.ReportType }}</span>
-            <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>
+            <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>
         </p>
-        <p>FICC研究部</p>
+        <p :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverDepartName||'投研部'}}</p>
         <p>{{pageInfo.PptDate}}</p>
-        <p style="width:80%; height:1px; border-bottom:1px solid #fff; margin:21px auto 0;"></p>
+        <p :style="`width:80%; height:1px; border-bottom:1px solid ${$parent.pptCoverTextColor||'#fff'}; margin:21px auto 0;`"></p>
         </div>
     </div>
 </template>

+ 7 - 7
src/views/ppt_manage/newVersion/components/CoverEn.vue

@@ -2,20 +2,20 @@
     <div class="flex-column cover" style="width:100%;" v-if="pageInfo">
         <img :src="pageInfo.BackgroundImg" class="pptbg"  style="width:100%"/>
         <div
-        style="width:62%; font-size:16px; text-align:center; line-height:1.6; color:#fff; position:absolute; right:20px; top:50%;zIndex:20;">
-        <p style="height:5px; border-top:1px solid #fff;marginBottom:21px;"></p>
+        :style="`width:62%; font-size:16px; text-align:center; line-height:1.6; color:${$parent.pptCoverTextColor||'#fff'}; position:absolute; right:20px; top:50%;zIndex:20;`">
+        <p :style="`height:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};marginBottom:21px;`"></p>
         <p style="font-size:28px;">{{ pageInfo.Title }}</p>
         <p style="display:flex; align-items:center; justify-content:center;margin:10px 0;">
-            <span>HORIZON INSIGHTS PTE. LTD.</span>
+            <span :style="{'color':$parent.pptCoverTextColor||'#fff'}">{{$parent.pptCoverCompenyName||'ETA'}}</span>
         </p>
         <p style="display:flex; align-items:center; justify-content:center;">
-          <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>  
+          <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>  
           <span>{{ pageInfo.ReportType }}</span>
-          <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>
+          <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>
         </p>
-        <p>FICC Research Department</p>
+        <p :style="{'color':$parent.pptCoverTextColor||'#fff'}">{{$parent.pptCoverDepartName||'Research Department'}}</p>
         <p>{{pageInfo.PptDate}}</p>
-        <p style="width:80%; height:1px; border-bottom:1px solid #fff; margin:21px auto 0;"></p>
+        <p :style="`width:80%; height:1px; border-bottom:1px solid ${$parent.pptCoverTextColor||'#fff'}; margin:21px auto 0;`"></p>
         </div>
     </div>
 </template>

+ 3 - 1
src/views/ppt_manage/newVersion/components/catalog/pptContent.vue

@@ -144,7 +144,8 @@ export default {
         await this.initPageElements(this.pageList[i],'show')
       } 
       this.isLoadBack = true
-      this.loadArr.push({name:'back'})
+      if(this.pptBackImage.length)
+        this.loadArr.push({name:'back'})
 
       //获取已加载图表的信息
       let chartInfoMap = {}
@@ -241,6 +242,7 @@ export default {
     },
     //计算title的字节数
     getStrCount(title){
+        if(!title) return
         return countStrSize(title)
     }
   },

+ 3 - 1
src/views/ppt_manage/newVersion/components/catalog/pptContentEn.vue

@@ -140,7 +140,8 @@ export default {
         await this.initPageElements(this.pageList[i],'show')
       }
       this.isLoadBack = true
-      this.loadArr.push({name:'back'})
+      if(this.pptBackImage.length)
+        this.loadArr.push({name:'back'})
       //获取已加载图表的信息
       let chartInfoMap = {}
       for(let i=1;i<this.loadArr.length-1;i++){
@@ -236,6 +237,7 @@ export default {
     },
     //计算title的字节数
     getStrCount(title){
+        if(!title) return
         return countStrSize(title)
     }
   },

+ 26 - 11
src/views/ppt_manage/newVersion/components/editor/ChooseCover.vue

@@ -6,35 +6,37 @@
                 <img src="~@/assets/img/ppt_m/close.png" alt="" class="close_ico" @click="closeDialog">
             </header>
             <div class="dialog-bg" :style="'backgroundImage:url('+bgList[bgListIndex]+');backgroundPosition:center;backgroundRepeat:no-repeat;backgroundSize:cover;'">
-                <div style="width:62%; font-size:16px; text-align:center; line-height:1.6; color:#fff; position:absolute; right:20px; top:50%;">
-                    <p style="height:5px; border-top:1px solid #fff;margin-bottom:21px;"></p>
+                <div :style="`width:62%; font-size:16px; text-align:center; line-height:1.6; color:${$parent.pptCoverTextColor}; position:absolute; right:20px; top:50%;`">
+                    <p :style="`height:5px; border-top:1px solid ${$parent.pptCoverTextColor};margin-bottom:21px;`"></p>
                     <el-input
+                      :data-textcolor="$parent.pptCoverTextColor"
                       type="textarea"
                       autosize
                       placeholder="请输入标题"
                       :maxlength="48"
                       v-model="pageData.Title" />
                     <p style="display:flex; align-items:center; justify-content:center;margin:10px 0;">
-                        <span style="display:inline-block; width:15px; margin-right:5px; border-top:1px solid #fff;"></span>
-                        <span>弘则弥道(上海)投资咨询有限公司</span>
-                        <span style="display:inline-block; width:14px; height:14px; background:#fff; border-radius:100%; margin:0 5px;"></span>
+                        <span style="display:inline-block; width:15px; margin-right:5px; border-top:1px solid $parent.pptCoverTextColor;"></span>
+                        <span :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverCompenyName||'ETA'}}</span>
+                        <span :style="`display:inline-block; width:14px; height:14px; background:${$parent.pptCoverTextColor}; border-radius:100%; margin:0 5px;`"></span>
                         <input 
                         type="text" 
-                        style="width:80px;background:transparent;color:#fff;border:none;text-align:center;display:inline-block" 
+                        :style="`width:80px;background:transparent;color:${$parent.pptCoverTextColor};border:none;text-align:center;display:inline-block`" 
                         v-model="pageData.ReportType"
                         placeholder="请输入类型">
-                        <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>
+                        <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor};`"></span>
                     </p>
-                    <p>FICC研究部</p>
+                    <p :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverDepartName||'投研部'}}</p>
                     <el-date-picker
                         v-model="pageData.PptDate"
+                        :data-textcolor="$parent.pptCoverTextColor"
                         type="month"
                         ref="date_pic"
                         format="yyyy年M月"
                         value-format="yyyy年M月"
                         placeholder="请选择日期">
                     </el-date-picker>
-                    <p style="width:80%; height:1px; border-bottom:1px solid #fff; margin:21px auto 0;"></p>
+                    <p :style="`width:80%; height:1px; border-bottom:1px solid ${$parent.pptCoverTextColor}; margin:21px auto 0;`"></p>
                 </div>
             </div>
             <div class="dialog-bot">
@@ -68,7 +70,7 @@ export default {
         };
     },
     mounted(){
-        $('.el-date-editor .el-input__inner').css({backgroundColor: 'transparent',border:'none',color:'#fff',textAlign:'center',fontSize:'16px'});
+        $('.el-date-editor .el-input__inner').css({backgroundColor: 'transparent',border:'none',color:this.$parent.pptCoverTextColor||'#fff',textAlign:'center',fontSize:'16px'});
 		$('.el-date-editor .el-icon-date' ).css({display:'none'});
         this.bgList = this.pptCoverList
         this.searchIndex = this.bgList.findIndex(i=>i===this.firstPage.BackgroundImg)
@@ -123,6 +125,7 @@ export default {
     .dialog-bg{
       .el-textarea{
         max-width: 95%;
+        --text-color:attr(data-textcolor);
         textarea{
           outline: none;
           border: none;
@@ -132,7 +135,10 @@ export default {
           text-align: center;
           resize: none;
           font-weight:bolder; 
-          color: #fff;
+          color:var(--text-color);
+          &::placeholder{
+            color:var(--text-color);
+          }
           scrollbar-width: none; 
           -ms-overflow-style: none;
           &::-webkit-scrollbar {
@@ -140,6 +146,15 @@ export default {
           }
         }
       }
+      .el-date-editor{
+        --text-color:attr(data-textcolor);
+          .el-input__inner::placeholder{
+            color:var(--text-color);
+          }
+          .el-input__suffix{
+            color:var(--text-color);
+          }
+      }
     }
   }
 }

+ 26 - 10
src/views/ppt_manage/newVersion/components/editor/ChooseCoverEn.vue

@@ -6,36 +6,38 @@
                 <img src="~@/assets/img/ppt_m/close.png" alt="" class="close_ico" @click="closeDialog">
             </header>
             <div class="dialog-bg" :style="'backgroundImage:url('+bgList[bgListIndex]+');backgroundPosition:center;backgroundRepeat:no-repeat;backgroundSize:cover;'">
-                <div style="width:62%; font-size:16px; text-align:center; line-height:1.6; color:#fff; position:absolute; right:20px; top:50%;">
-                    <p style="height:5px; border-top:1px solid #fff;margin-bottom:21px;"></p>
+                <div :style="`width:62%; font-size:16px; text-align:center; line-height:1.6; color:${$parent.pptCoverTextColor||'#fff'}; position:absolute; right:20px; top:50%;`">
+                    <p :style="`height:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};margin-bottom:21px;`"></p>
                     <el-input
+                      :data-textcolor="$parent.pptCoverTextColor"
                       type="textarea"
                       autosize
                       placeholder="请输入标题"
                       :maxlength="48"
                       v-model="pageData.Title" />
                     <p style="display:flex; align-items:center; justify-content:center;margin:10px 0;">
-                        <span>HORIZON INSIGHTS PTE. LTD.</span>
+                        <span :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverCompenyName||'ETA'}}</span>
                     </p>
                     <p style="display:flex; align-items:center; justify-content:center;">
-                      <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>
+                      <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>
                       <input 
                         type="text" 
-                        style="width:80px;background:transparent;color:#fff;border:none;text-align:center;display:inline-block" 
+                        :style="`width:80px;background:transparent;color:${$parent.pptCoverTextColor||'#fff'};border:none;text-align:center;display:inline-block`" 
                         v-model="pageData.ReportType"
                         placeholder="请输入类型"/>
-                        <span style="display:inline-block; width:15px; margin-left:5px; border-top:1px solid #fff;"></span>
+                        <span :style="`display:inline-block; width:15px; margin-left:5px; border-top:1px solid ${$parent.pptCoverTextColor||'#fff'};`"></span>
                     </p>
-                    <p>FICC Research Department</p>
+                    <p :style="{'color':$parent.pptCoverTextColor||''}">{{$parent.pptCoverDepartName||'Research Department'}}</p>
                     <el-date-picker
                         v-model="pageData.PptDate"
+                        :data-textcolor="$parent.pptCoverTextColor"
                         type="month"
                         ref="date_pic"
                         format="yyyy.MM"
                         value-format="yyyy.MM"
                         placeholder="请选择日期">
                     </el-date-picker>
-                    <p style="width:80%; height:1px; border-bottom:1px solid #fff; margin:21px auto 0;"></p>
+                    <p :style="`width:80%; height:1px; border-bottom:1px solid ${$parent.pptCoverTextColor||'#fff'}; margin:21px auto 0;`"></p>
                 </div>
             </div>
             <div class="dialog-bot">
@@ -69,7 +71,7 @@ export default {
         };
     },
     mounted(){
-        $('.el-date-editor .el-input__inner').css({backgroundColor: 'transparent',border:'none',color:'#fff',textAlign:'center',fontSize:'16px'});
+        $('.el-date-editor .el-input__inner').css({backgroundColor: 'transparent',border:'none',color:this.$parent.pptCoverTextColor||'#fff',textAlign:'center',fontSize:'16px'});
 		$('.el-date-editor .el-icon-date' ).css({display:'none'});
         this.bgList = this.pptCoverList
         this.searchIndex = this.bgList.findIndex(i=>i===this.firstPage.BackgroundImg)
@@ -126,6 +128,7 @@ export default {
     .dialog-bg{
       .el-textarea{
         max-width: 95%;
+        --text-color:attr(data-textcolor);
         textarea{
           outline: none;
           border: none;
@@ -135,14 +138,27 @@ export default {
           text-align: center;
           resize: none;
           font-weight:bolder; 
-          color: #fff;
+          /* color: #fff; */
           scrollbar-width: none; 
           -ms-overflow-style: none;
+          color:var(--text-color);
+          &::placeholder{
+            color:var(--text-color);
+          }
           &::-webkit-scrollbar {
             width: 0px;
           }
         }
       }
+      .el-date-editor{
+        --text-color:attr(data-textcolor);
+          .el-input__inner::placeholder{
+            color:var(--text-color);
+          }
+          .el-input__suffix{
+            color:var(--text-color);
+          }
+      }
     }
   }
 }

+ 120 - 0
src/views/ppt_manage/newVersion/components/editor/InsertSemantics.vue

@@ -0,0 +1,120 @@
+<template>
+    <div class="import-mychart-wrap">
+        <div>
+            <el-input
+				placeholder="关键词搜索"
+				v-model="keyword"
+				size="medium"
+				prefix-icon="el-icon-search"
+                @input="handleChange"
+			/>
+		</div>
+		<div class="list" v-infinite-scroll="load" v-if="list.length>0">
+            <div class="item" v-for="item in list" :key="item.SaCompareId" @click="handleClickItem(item)">
+                <p>{{ item.Title }}</p>
+                <img :src="item.PicUrl" alt="">
+            </div>
+		</div>
+        <div v-if="list.length==0" class="empty-box">
+            无数据
+        </div>
+    </div>
+</template>
+
+<script>
+import {semanticInterface} from '@/api/modules/semanticsApi.js';
+export default {
+    data() {
+        return {
+            keyword:'',
+            pageSize:20,
+			CurrentIndex: 1,
+			list:[],
+            loading:false,
+            finished:false,
+
+        }
+    },
+    mounted(){
+        this.handleGetList()
+    },  
+    methods: {
+		async handleGetList(){
+            this.loading=true
+            const res=await semanticInterface.compareSearch({
+				PageSize: this.pageSize,
+				CurrentIndex: this.CurrentIndex,
+				Keyword: this.keyword
+			})
+            this.loading=false
+            let arr=res.Data.List||[]
+            arr=arr.map(item => {
+               return {
+                   ...item,
+                   PicUrl:item.ResultImg
+               } 
+            });
+
+            this.list=[...this.list,...arr]
+            if(!res.Data){
+                this.finished=true
+            }
+            if(res.Data&&res.Data.Paging.IsEnd){
+                this.finished=true
+            }
+		},
+
+        load(){
+            if(this.finished) return
+            this.CurrentIndex++
+            this.handleGetList()
+        },
+        handleChange(){
+            console.log('aaa');
+            this.CurrentIndex=1
+            this.finished=false
+            this.list=[]
+            this.handleGetList()
+        },
+
+        handleClickItem(item){
+           this.$parent.chooseChart(item,'sandImage')
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap{
+    .list{
+        height: calc(100vh - 320px);
+        overflow-x: hidden;
+		overflow-y: auto;
+        .item{
+            width: 100%;
+            margin: 20px 0;
+            padding: 20px;
+            box-sizing: border-box;
+            border: 1px solid #eaeaea;
+            border-radius: 10px;
+            position: relative;
+            overflow: hidden;
+            p{
+                text-align: center;
+                font-size: 16px;
+                margin-bottom: 10px;
+                color: #5882EF;
+            }
+            img{
+                width: 100%;
+            }
+        }
+    }
+    .empty-box{
+        height: calc(100vh - 320px);
+        text-align: center;
+        color: #999;
+        padding-top: 100px;
+    }
+}
+</style>

+ 28 - 14
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -385,20 +385,34 @@ export default {
   watch:{
     searchTitle(newVal){
       let data = null
-      this.publicList.forEach((item)=>{
+      let search='private'
+      this.privateList.forEach((item)=>{
         item.children.forEach(i=>{
-          if(i.PptId===newVal){
-            data = i
-          }
+            if(i.PptId===newVal){
+                data = i
+                search='private'
+            }
         })
       })
-      this.default_tab = '3';
-      //选中该节点
-      this.$refs.publicTree.setCurrentKey('ppt'+newVal)
-      //展开该节点的父节点...
-      const node = this.$refs.publicTree.getCurrentNode()
-      this.publicExpandKeys.push(node.catalogId)
-      this.nodeChange(data,_,'public')
+      if(!data){
+        this.publicList.forEach((item)=>{
+            item.children.forEach(i=>{
+                if(i.PptId===newVal){
+                    data = i
+                    search='public'
+                }
+            })
+        })
+      }
+      if(data){
+        this.default_tab = search==='public'?'3':'1';
+        //选中该节点
+        this.$refs[`${search}Tree`].setCurrentKey('ppt'+newVal)
+        //展开该节点的父节点...
+        const node = this.$refs[`${search}Tree`].getCurrentNode()
+        this[`${search}ExpandKeys`].push(node.catalogId)
+        this.nodeChange(data,_,search)
+      }
       this.searchOptions=[]
     },
 /*     default_tab(newVal){
@@ -1055,7 +1069,7 @@ export default {
     //搜索ppt标题
     searchHandle(keyword){
       //searchPPT->searchPPTByKeyWorld
-      pptInterface.searchPPTByKeyWorld({
+      pptInterface.searchPPTByKeyWorldV2({
         Keyword:keyword
       }).then(res=>{
         if(res.Ret===200){
@@ -1259,7 +1273,7 @@ export default {
       height: 0;
     }
     .el-tabs__item.is-active {
-      border-bottom: 2px solid #409EFF;
+      border-bottom: 2px solid #0052D9;
     }
     .el-tabs__item { font-size: 16px; }
     .ppt-list-wrap{
@@ -1375,7 +1389,7 @@ export default {
       h3{
         span{
           margin-left: 20px;
-          color:#409EFF;
+          color:#0052D9;
           font-size: 12px;
           font-weight: normal;
         }

+ 7 - 2
src/views/ppt_manage/newVersion/pptEditor.vue

@@ -176,6 +176,9 @@
               <div v-show="tabsactive == 'MyETA批量'" class="chart-tool flex-column">
                 <insert-charts @handleImportMyChart="handleImportMyChart"/>
               </div>
+              <div v-show="tabsactive == '语义分析插入'" class="chart-tool flex-column">
+                <InsertSemantics />
+              </div>
             </div>
             <!-- 图层编辑 -->
             <div class="layer-edit-box" v-else>
@@ -287,6 +290,7 @@ import InsertPageDialog from './components/editor/InsertPageDialog.vue';
 import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
 import InsertCharts from './components/editor/InsertCharts.vue';
 import ContextMenu from './components/ContextMenu.vue';
+import InsertSemantics from './components/editor/InsertSemantics.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -295,7 +299,7 @@ export default {
           ],
   components: { 
         IndexItem, ChooseCover, AddFormat,ShapePreview,
-    LayerEditTool,DeletePageDialog,ChangeFormatDialog,InsertPageDialog,addMyClassifyDia,InsertCharts,ContextMenu
+    LayerEditTool,DeletePageDialog,ChangeFormatDialog,InsertPageDialog,addMyClassifyDia,InsertCharts,ContextMenu,InsertSemantics
   },
   data() {
     return {
@@ -339,7 +343,7 @@ export default {
         catalogId:0,//ppt目录id,添加ppt时需要
         ReportId:0,//ppt对应的双周报id,如果没转过,则为0
         isChartLoading:false,//是否正在加载图表/图片
-        panelTabs: [ '图表','MyETA批量','沙盘','表格' ],
+        panelTabs: [ '图表','MyETA批量','沙盘','表格','语义分析插入' ],
         sheetSearchList:[],
         sheetSearchObj: {
           Keyword:''
@@ -1227,6 +1231,7 @@ export default {
   },
   updated(){
     $('.ppt-item').css('height',$('.ppt-item').width()*0.7);
+    $('.ppt-item').css('background-image',`url(${this.pptBgImage})`);
     window.onresize = ()=>{
       $('.ppt-item').css('height',$('.ppt-item').width()*0.7);
     }

+ 32 - 18
src/views/ppt_manage/newVersion/pptEnCatalog.vue

@@ -373,22 +373,36 @@ export default {
   },
   watch:{
     searchTitle(newVal){
-      let data = null
-      this.publicList.forEach((item)=>{
-        item.children.forEach(i=>{
-          if(i.PptId===newVal){
-            data = i
-          }
+        let data = null
+        let search='private'
+        this.privateList.forEach((item)=>{
+            item.children.forEach(i=>{
+                if(i.PptId===newVal){
+                    data = i
+                    search='private'
+                }
+            })
         })
-      })
-      this.default_tab = '3';
-      //选中该节点
-      this.$refs.publicTree.setCurrentKey('ppt'+newVal)
-      //展开该节点的父节点...
-      const node = this.$refs.publicTree.getCurrentNode()
-      this.publicExpandKeys.push(node.catalogId)
-      this.nodeChange(data,_,'public')
-      this.searchOptions=[]
+        if(!data){
+            this.publicList.forEach((item)=>{
+                item.children.forEach(i=>{
+                    if(i.PptId===newVal){
+                        data = i
+                        search='public'
+                    }
+                })
+            })
+        }
+        if(data){
+            this.default_tab = search==='public'?'3':'1';
+            //选中该节点
+            this.$refs[`${search}Tree`].setCurrentKey('ppt'+newVal)
+            //展开该节点的父节点...
+            const node = this.$refs[`${search}Tree`].getCurrentNode()
+            this[`${search}ExpandKeys`].push(node.catalogId)
+            this.nodeChange(data,_,search)
+        }
+        this.searchOptions=[]
     },
   },
   methods: {
@@ -974,7 +988,7 @@ export default {
     },
     //搜索ppt标题
     searchHandle(keyword){
-      pptEnInterface.searchPPTByKeyWorld({
+      pptEnInterface.searchPPTByKeyWorldV2({
         Keyword:keyword
       }).then(res=>{
         if(res.Ret===200){
@@ -1154,7 +1168,7 @@ export default {
       height: 0;
     }
     .el-tabs__item.is-active {
-      border-bottom: 2px solid #409EFF;
+      border-bottom: 2px solid #0052D9;
     }
     .el-tabs__item { font-size: 16px; }
     .ppt-list-wrap{
@@ -1269,7 +1283,7 @@ export default {
       h3{
         span{
           margin-left: 20px;
-          color:#409EFF;
+          color:#0052D9;
           font-size: 12px;
           font-weight: normal;
         }

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

@@ -180,6 +180,9 @@
                   :showEnMark="true"
                   />
               </div>
+              <div v-show="tabsactive == '语义分析插入'" class="chart-tool flex-column">
+                <InsertSemantics />
+              </div>
             </div>
             <!-- 图层编辑 -->
             <div class="layer-edit-box" v-else>
@@ -299,6 +302,7 @@ import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyD
 import InsertCharts from './components/editor/InsertCharts.vue';
 import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue';
 import ContextMenu from './components/ContextMenu.vue';
+import InsertSemantics from './components/editor/InsertSemantics.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -317,7 +321,8 @@ export default {
     setEnNameDia,
     addMyClassifyDia,
     InsertCharts,
-    ContextMenu
+    ContextMenu,
+    InsertSemantics
   },
   data() {
     return {
@@ -361,7 +366,7 @@ export default {
         catalogId:0,//ppt目录id,添加ppt时需要
         ReportId:0,//ppt对应的双周报id,如果没转过,则为0
         isChartLoading:false,//是否正在加载图表/图片
-        panelTabs: [ '图表','MyETA批量','沙盘','表格' ],
+        panelTabs: [ '图表','MyETA批量','沙盘','表格','语义分析插入' ],
         sheetSearchList:[],
         sheetSearchObj: {
           Keyword:''
@@ -1202,6 +1207,7 @@ export default {
   },
   updated(){
     $('.ppt-item').css('height',$('.ppt-item').width()*0.7);
+    $('.ppt-item').css('background-image',`url(${this.pptBgImage})`);
     window.onresize = ()=>{
       $('.ppt-item').css('height',$('.ppt-item').width()*0.7);
     }

+ 3 - 3
src/views/ppt_manage/newVersion/pptEnPublish.vue

@@ -394,10 +394,10 @@ export default {
       const coverInfo = [
         {text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.Title,options:{fontSize:28*0.75,breakLine:true}},
-        {text:`\nHORIZON INSIGHTS PTE. LTD.`,
+        {text:`\n${this.pptCoverCompenyName||'ETA'}`,
          options:{fontSize:16*0.75,breakLine:true}},
         {text:`\n — ${this.coverInfo.page.ReportType} —`,options:{fontSize:16*0.75,breakLine:true}}, 
-        {text:'\nFICC Research Department',options:{fontSize:16*0.75,breakLine:true}},
+        {text:`\n${this.pptCoverDepartName||'Research Department'}`,options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.PptDate,options:{fontSize:16*0.75,breakLine:true}},
         {text:'\n—————————————————————————',options:{fontSize:16*0.75,breakLine:true}}
       ]
@@ -406,7 +406,7 @@ export default {
         y:'50%',
         w:'60%',
         h:'28%',
-        color:'ffffff',
+        color:(this.pptCoverTextColor||'#ffffff').slice(1),
         align:'center',
         fontFace:'SimHei'
       })

+ 3 - 3
src/views/ppt_manage/newVersion/pptPublish.vue

@@ -474,9 +474,9 @@ export default {
       const coverInfo = [
         {text:'—————————————————————————————————\n',options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.Title,options:{fontSize:28*0.75,breakLine:true}},
-        {text:`\n— 弘则弥道(上海)投资咨询有限公司 ● ${this.coverInfo.page.ReportType} —`,
+        {text:`\n— ${this.pptCoverCompenyName||'ETA'} ● ${this.coverInfo.page.ReportType} —`,
          options:{fontSize:16*0.75,breakLine:false}},
-        {text:'\nFICC研究部',options:{fontSize:16*0.75,breakLine:true}},
+        {text:`\n${this.pptCoverDepartName||'投研部'}`,options:{fontSize:16*0.75,breakLine:true}},
         {text:this.coverInfo.page.PptDate,options:{fontSize:16*0.75,breakLine:true}},
         {text:'\n—————————————————————————',options:{fontSize:16*0.75,breakLine:true}}
       ]
@@ -485,7 +485,7 @@ export default {
         y:'50%',
         w:'60%',
         h:'28%',
-        color:'ffffff',
+        color:(this.pptCoverTextColor||'#ffffff').slice(1),
         align:'center',
         fontFace:'SimHei'
       })

+ 18 - 0
src/views/ppt_manage/newVersion/utils/untils.js

@@ -641,3 +641,21 @@ export const getContextMenuPos = (layerId) =>{
     return {clientX:menuBoundingClientRect.x - layerBoundingClientRect.x,
             clientY:menuBoundingClientRect.y - layerBoundingClientRect.y,}
 }
+
+//根据Source 和 MyChartType判断图表是否显示标题
+/*
+    Source:1
+    MyChartType: 2 季节性图,7 柱形图,  10 截面散点图,
+    Source:2 商品价格曲线图
+    Source:5 利润曲线
+    Source:6 拟合方程曲线
+    Source:7 统计特征-标准差
+    Source:9 统计特性-频率
+    Source:8 统计特性-百分位
+    以上图表需要显示标题
+*/
+export const isShowPPTTitle = (Source,MyChartType)=>{
+    const sense_1 = Source===1&&[2,7,10].includes(MyChartType)
+    const sense_2 = [2,5,6,7,8,9].includes(Source)
+    return sense_1||sense_2
+}

+ 2 - 2
src/views/predictEdb_manage/addPredicEdb.vue

@@ -605,8 +605,8 @@ export default {
             oldEdbName: res.Data.CalculateList[0].FromEdbName,
             edbName: EdbName,
             frequency: Frequency,
-            newdata: LatestValue,
-            lasetDate: LatestDate,
+            newdata:  res.Data.CalculateList[0].EndValue,
+            lasetDate: res.Data.CalculateList[0].EndDate,
             dateType: DataDateType
           };
 

+ 16 - 10
src/views/predictEdb_manage/components/chartInfo.vue

@@ -7,14 +7,14 @@
 				type="primary"
 				v-for="item in yearSelector"
 				:key="item.value"
-				size="medium"
+				size="mini"
 				:plain="item.value !== year_select"
 				class="year-btn"
 				@click.native="changeYear(item)"
 				>{{ item.name }}</el-button
 			>
 			<el-button 
-                type="text" 
+                type="primary" size="mini"
                 class="btn-sty" 
                 @click="openDateDia"
             >{{dateTip}}</el-button>
@@ -30,8 +30,14 @@
                     @change="seasonYearChange"
                 />
             </template>
-            <span v-permission="permissionBtn.predictEdbPermission.edbPreData_switchSeason"
-                class="change-chart-btn" @click="chartTypeChange">切换{{chartInfo.ChartType==1?'季节性图':'曲线图'}}</span>
+            <!-- <span v-permission="permissionBtn.predictEdbPermission.edbPreData_switchSeason"
+                class="change-chart-btn" @click="chartTypeChange">切换{{chartInfo.ChartType==1?'季节性图':'曲线图'}}</span> -->
+            <el-button type="primary" size="mini" class="btn-sty" style="margin-left:auto;"
+                v-permission="permissionBtn.predictEdbPermission.edbPreData_switchSeason"
+                @click="chartTypeChange">
+                <i class="el-icon-sort" style="transform: rotate(90deg);"></i>
+                    切换{{chartInfo.ChartType==1?'季节性图':'曲线图'}}
+            </el-button>
         </div>
         <div class="chartWrapper">
             <Chart 
@@ -185,20 +191,20 @@ export default {
 
 <style lang="scss" scoped>
 .predicedb-chart-wrap{
-    padding: 30px;
+    /* padding: 30px; */
     .header {
+        display: flex;
         position: relative;
         margin-bottom: 30px;
-        .year-btn {
+        .year-btn,.btn-sty {
             min-width: 90px;
             font-size: 14px;
             margin-right: 5px;
             margin-bottom: 5px;
         }
         .btn-sty {
-            font-size: 16px;
-            padding: 9px;
-            border: 1px solid #409eff;
+            background-color: #fff;
+			color: #0052D9;
         }
         .change-chart-btn{
             float: right;
@@ -219,7 +225,7 @@ export default {
         }
     }
     .calendar-cont {
-        margin: 30px auto;
+        /* margin: 30px auto; */
         text-align: center;
         display: block;
         .el-radio-button__inner {

+ 104 - 41
src/views/predictEdb_manage/components/childData.vue

@@ -34,6 +34,29 @@
         <tableNoData text="暂无数据" size="mini"/>
       </div>
     </el-table>
+    <el-table
+			:data="tableData"
+			style="box-shadow: 0px 3px 6px rgba(155, 170, 219, 0.2);"
+			border>
+			<el-table-column
+				v-for="item in tableColumsTwo"
+				:key="item.label"
+				:label="item.label"
+				:width="item.widthsty"
+				:min-width="item.minwidthsty"
+				align="center"
+			>
+				<template #header>
+					<span>{{ item.label }}</span>
+				</template>
+				<template slot-scope="scope">
+					<span>{{ scope.row[item.key] }}</span>
+				</template>
+			</el-table-column>
+			<div slot="empty" style="padding: 50px 0 320px;">
+					<tableNoData :text="defaultWarn"/>
+			</div>
+		</el-table>
     <ul
       class="value-ul"
       ref="valueUl"
@@ -46,13 +69,15 @@
         :key="item.EdbDataId"
       >
         <span class="value-label">
-          <i class="new-tag" v-if="tableData[0].LatestDate===item.DataTime"></i>
-          {{ item.DataTime }}
+            <span style="position: relative;">
+                <i class="new-tag" v-if="tableData[0].LatestDate===item.DataTime"></i>
+                {{item.DataTime}}
+            </span>
         </span>
         <span
           :class="['value-label',{'predict-act': item.isPredic}]"
           style="min-width: 200px; text-align: center"
-          >{{ item.Value }}</span
+          ><span :class="['value-style',{'predict-act': item.isPredic}]">{{item.Value}}</span></span
         >
       </li>
       <li class="nodata value-item" v-if="!dataList.length">暂无数据</li>
@@ -81,42 +106,54 @@ export default {
   data() {
     return {
       tableColums: [
-				{
-					label: '指标ID',
-					key: 'EdbCode',
-					minwidthsty: '150px'
-				},
-				{
-					label: '频度',
-					key: 'Frequency',
-					widthsty: '80px'
-				},
-				{
-					label: '单位',
-					key: 'Unit',
-					widthsty: '80px'
-				},
-				{
-					label: '起始时间',
-					key: 'StartDate',
-					widthsty: '160px'
-				},
-				{
-					label: '预测截止日期',
-					key: 'EndDate',
-					widthsty: '160px'
-				},
-				{
-					label: '更新时间',
-					key: 'ModifyTime',
-					widthsty: '160px'
-				},
-				{
-					label: '添加人',
-					key: 'SysUserRealName',
-					widthsty: '100px'
-				},
-			],
+        {
+            label: '指标ID',
+            key: 'EdbCode',
+            widthsty: '280px'
+        },
+        {
+            label: '指标名称',
+            key: 'EdbName',
+            minwidthsty: '200px'
+        },
+        {
+            label: '频度',
+            key: 'Frequency',
+            widthsty: '100px'
+        },
+        {
+            label: '单位',
+            key: 'Unit',
+            widthsty: '140px'
+        },
+      ],
+      tableColumsTwo:[
+        {
+            label: '指标目录',
+            key: 'Menu',
+            widthsty: '280px',
+        },
+        {
+            label: '起始时间',
+            key: 'StartDate',
+            minwidthsty: '100px',
+        },
+        {
+            label: '预测截止日期',
+            key: 'EndDate',
+            minwidthsty: '100px'
+        },
+        {
+            label: '更新时间',
+            key: 'ModifyTime',
+            minminwidthsty: '120px',
+        },
+        {
+            label: '添加人',
+            key: 'SysUserRealName',
+            widthsty: '140px',
+        }
+      ],
       showData: false,
       tableData: [],
       page_no: 1,
@@ -137,6 +174,10 @@ export default {
         Item.PredictDataList && Item.PredictDataList.forEach(_ => {
           _.isPredic = true;
         })
+        const classify_arr = res.Data.ClassifyList || [];
+        let str = '';
+        classify_arr.length && classify_arr.reverse().map((item) => str += item.ClassifyName + '/');
+        this.$set(Item,'Menu',str);
         this.haveMore =  this.page_no < res.Data.Paging.Pages;
         this.dataList = this.page_no === 1 ? [...Item.PredictDataList,...Item.DataList] : [...this.dataList,...Item.DataList];
 
@@ -171,15 +212,24 @@ export default {
   },
 };
 </script>
+<style lang="scss">
+.data-wrapper {
+    .el-table--enable-row-transition .el-table__body td{
+        background: #fff !important;
+    }
+    .el-table td, .el-table th.is-leaf {
+        background: #F2F6FA !important;
+    }
+}
+</style>
 <style scoped lang="scss">
 .data-wrapper {
-  padding-top: 40px;
   .value-ul {
     margin-top: 10px;
     border-bottom: 1px solid #dcdfe6;
     border-top: 1px solid #dcdfe6;
     /* max-height: 520px; */
-    max-height: calc(100vh - 450px);
+    max-height: calc(100vh - 430px);
     overflow-y: auto;
     .value-item {
       /* width: 100%; */
@@ -189,9 +239,22 @@ export default {
       display: flex;
       justify-content: space-around;
       &:first-child { border-top: none; }
+      span{
+        flex: 1;
+        text-align: center;
+      }
       .value-label {
         position: relative;
         color: #666;
+        .value-style{
+            /* background-color: #ECF2FE;
+            color: #0052D9; */
+            padding:5px;
+            border-radius: 4px;
+            &.predict-act{
+                color: orange;
+            }
+        }
       }
       .predict-act {
         color: orange;

+ 2 - 2
src/views/predictEdb_manage/components/classifyDia.vue

@@ -32,7 +32,7 @@
 					</el-form-item>
 				</template>
 
-				<el-form-item label="分类名称" prop="classify_name">
+				<el-form-item label="目录名称" prop="classify_name">
 					<el-input
 					v-model="formData.classify_name"
 					style="width: 80%"
@@ -78,7 +78,7 @@ export default {
 			formData: {},
       formRules: {
         classify_name:[
-          { required: true, message: '分类名称不能为空', trigger: 'blur' },
+          { required: true, message: '目录名称不能为空', trigger: 'blur' },
         ]
       },
 

+ 112 - 3
src/views/predictEdb_manage/components/edbDetail.vue

@@ -6,7 +6,40 @@
             @refreshData="refreshData"
             ref="chartInfo"
         />
-        <div class="author" style="float:right">添加人:{{edbData.EdbInfo.SysUserRealName}}</div>
+        <div class="info" style="display: flex;justify-content: flex-end;">
+          <!--   <span>数据来源:{{edbData.EdbInfo.SourceName}}</span> -->
+            <span>添加人:{{edbData.EdbInfo.SysUserRealName}}</span>
+        </div>
+        <ul
+            class="value-ul"
+            v-show="showData&&dataList.length"
+            >
+            <li class="value-item" style="background-color: #EBEFF6;">
+                <span style="width:240px">日期(频度:{{EdbData.Frequency}})</span>
+                <span style="flex:1;">值</span>
+            </li>
+            <li
+                class="value-item"
+                v-for="item in dataList.slice(0,3)"
+                :key="item.EdbDataId"
+            >
+                <span class="value-label date" style="width:240px">
+                    <span style="position: relative;">
+                        <i class="new-tag" v-if="EdbData.LatestDate===item.DataTime"></i>
+                        {{ item.DataTime }}
+                    </span>
+                </span>
+                <span
+                    :class="['value-label',{'predict-act': item.isPredic}]"
+                    style="flex:1;"
+                >
+                    <span :class="['value-style',{'predict-act': item.isPredic}]">{{item.Value}}</span>
+                </span
+                >
+            </li>
+            <li class="nodata value-item" v-if="!dataList.length">暂无数据</li>
+        </ul>
+
     </div>
 </template>
 
@@ -45,6 +78,9 @@ export default {
                 DataList:null,
                 EdbInfo:{}
             },
+            showData:false,
+            dataList: [],
+            EdbData:{}
         }
     },
     methods: {
@@ -90,6 +126,7 @@ export default {
                         this.setChartImage()
                     })
                 }
+                this.getData()
             })
         },
         refreshData(type=''){
@@ -119,12 +156,84 @@ export default {
                 ImageUrl: Data.ResourceUrl,
             });
         },
+        getData(){
+            preDictEdbInterface.edbDataInfo({
+                EdbInfoId: this.id,
+                CurrentIndex: 1
+            }).then(res => {
+                this.showData = true;
+                if(res.Ret!==200) return 
+                const {Item} = res.Data
+                Item.PredictDataList && Item.PredictDataList.forEach(_ => {
+                    _.isPredic = true;
+                })
+                this.EdbData = Item
+                this.dataList = [...Item.PredictDataList,...Item.DataList]
+            })
+        },
 
     },
 
 }
 </script>
 
-<style>
-
+<style lang="scss" scoped>
+.value-ul {
+    margin-top: 10px;
+    border-bottom: 1px solid #EBEFF6;
+    .value-item {
+        padding: 10px 0;
+        border: 1px solid #EBEFF6;
+        border-bottom: none;
+        display: flex;
+        justify-content: space-around;
+        >span{
+            padding:0 16px;
+            box-sizing: border-box;
+        }
+        .value-label {
+            position: relative;
+            color: #666;
+            .value-style{
+                /* background-color: #ECF2FE;
+                color: #0052D9; */
+                padding:5px;
+                border-radius: 4px;
+                &.predict-act {
+                    color: orange;
+                }
+            }
+            &.date{
+                &::after{
+                    content: '';
+                    position:absolute;
+                    right:0;
+                    top:-14px;
+                    height:calc(100% + 28px);
+                    width:1px;
+                    background-color: #EBEFF6;
+                }
+            }
+        }
+        .predict-act {
+            color: orange;
+        }
+        .new-tag {
+            width: 6px;
+            height: 6px;
+            display: inline-block;
+            position: absolute;
+            left: -12px;
+            top: 50%;
+            transform: translateY(-50%);
+            border-radius: 50%;
+            background: #f00;
+        }
+    }
+    .nodata {
+        text-align: center;
+        padding: 40px 0;
+        color: #999;
+    }
+}
 </style>

+ 155 - 35
src/views/predictEdb_manage/predictEdb.vue

@@ -149,7 +149,7 @@
 							alt=""
 							style="width: 16px; height: 16px; margin-right: 10px"
 						/>
-						<span>添加分类</span>
+						<span>添加一级目录</span>
 					</div>
 				</div>
 				<span
@@ -167,30 +167,35 @@
 
 				<!-- 详情 -->
 				<div class="edb-detail-wrapper" v-if="select_id&&!showAssociateChart&&!showAssociateComputeData">
-					<div class="detail-top">
-						<span class="title">{{ currentLang==='en'?(edb_nameEn||edbName):edbName }}</span>
-						<ul class="action-ul">
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_enNameSetting"
-								class="editsty" @click="clickEdbNameHandle" v-if="currentLang==='ch'||!edb_nameEn">
+					<div class="detail-header">
+						<el-tabs v-model="activeTab" @tab-click="changeShowType">
+							<el-tab-pane label="走势图" name="Chart">
+							</el-tab-pane>
+							<el-tab-pane label="数据详情" name="Data">
+							</el-tab-pane>
+						</el-tabs>
+						<div class="edb-tool">
+							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_enNameSetting"
+								type="text" @click="clickEdbNameHandle" v-if="currentLang==='ch'||!edb_nameEn">
 								设置英文名称
-							</li>
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
-								class="editsty" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</li>
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_update"
-								class="editsty" @click="updateEdbPartHandle">更新</li>
-							<li class="editsty" @click="editEdbHandle('')" 
-								v-if="edbButton.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_edit)">编辑</li>
-							<li class="editsty" @click="saveEdbHandle" 
-								v-if="detail_show_chart&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_save)">保存</li>
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_recalcu"
-								class="editsty" @click="updateEdbHandle">重新计算</li>
-							<li class="deletesty" @click="delEdbHandle" 
-								v-if="edbButton.DeleteButton&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_del)">删除</li>
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_copyData"
-								class="editsty" @click="copyData">复制数据</li>
-							<li v-permission="permissionBtn.predictEdbPermission.edbPreData_viewData"
-								class="editsty" @click="detail_show_chart=!detail_show_chart">{{detail_show_chart ? '查看数据' : '查看图表'}} </li>
-						</ul>
+							</el-button>
+							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
+							type="text" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</el-button>
+							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_update"
+								type="text" @click="updateEdbPartHandle">刷新</el-button>
+							<el-button type="text" @click="editEdbHandle('')" 
+								v-if="edbButton.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_edit)">编辑</el-button>
+							<el-button type="text" @click="saveEdbHandle" 
+								v-if="detail_show_chart&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_save)">保存</el-button>
+							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_recalcu"
+								type="text" @click="updateEdbHandle">重新计算</el-button>
+							<el-button class="deletesty" @click="delEdbHandle" type="text"
+								v-if="edbButton.DeleteButton&&permissionBtn.checkPermissionBtn(permissionBtn.predictEdbPermission.edbPreData_del)">删除</el-button>
+							<el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_copyData"
+								type="text" @click="copyData">复制数据</el-button>
+							<!-- <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_viewData"
+								type="text" @click="detail_show_chart=!detail_show_chart">{{detail_show_chart ? '查看数据' : '查看图表'}} </el-button> -->
+						</div>
 					</div>
 
 					<!--  -->
@@ -402,6 +407,17 @@
       :isOpenDialog.sync="isLookHistory"
       :edbId="lookEdbId"
     />
+	<!-- 指数修匀弹窗 -->
+	<SmoothEdbDialog 
+			:is-open-smooth="computed_type==='alpha'"
+			:computed-source="computed_source"
+			:operationForm="operationForm"
+			:isPredict="true"
+			@cancel="computed_type=0"
+			@openPrev="isOpenComputed=true"
+			@addCallBack="addComputedCallBack"
+			@lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
+		/>
 
 	</div>
 </template>
@@ -427,6 +443,7 @@ import diffusionIndexDialog from '@/views/dataEntry_manage/databaseComponents/di
 import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
 import dataAssociateChart from '@/views/dataEntry_manage/databaseComponents/dataAssociateChart.vue'
 import dataAssociateComputeData from '@/views/dataEntry_manage/databaseComponents/dataAssociateComputeData.vue'
+import SmoothEdbDialog from '@/views/dataEntry_manage/databaseComponents/smoothEdbDialog.vue';
 
 export default {
 	name:'',
@@ -446,7 +463,8 @@ export default {
 		batchComputedDialog,
 		diffusionIndexDialog,
 		dataAssociateChart,
-		dataAssociateComputeData
+		dataAssociateComputeData,
+		SmoothEdbDialog
 	},
 	mixins:[ leftMixin ],
 	beforeRouteLeave (to, from, next) {
@@ -540,6 +558,7 @@ export default {
 				[64,formulaTip.get(61)],
 				[65,formulaTip.get(62)],
 				[66,formulaTip.get(63)],
+				['alpha',formulaTip.get('alpha')]
 			]),//公式说明
 
 			isShowRuleDialog: false,
@@ -568,7 +587,8 @@ export default {
 				{  name: '年化',type: 55 },
 				{ name: '降频',type: 54 },
 				{ name: '扩散指数',type: 56 },
-				{ name: '累计值',type: 'accumulate' }
+				{ name: '累计值',type: 'accumulate' },
+				{ name: '指数修匀',type:'alpha'}
 			],
 			batchTypes: [
 				{ name: '同比值',type: 32 },
@@ -578,7 +598,8 @@ export default {
 				{ name: 'N数值环差值',type: 44 },
 				{ name: '升频',type: 45 },
 				{ name: '累计值转月/季值',type: 'toMonthSeason' },
-				{ name: '累计值',type: 'accumulate' }
+				{ name: '累计值',type: 'accumulate' },
+				{ name: '指数修匀',type:'alpha'}
 			],
       isOnlyMe:false,//只看我的
 
@@ -589,6 +610,8 @@ export default {
 
 			showAssociateChart:false,//显示指标关联的图
 			showAssociateComputeData:false,//显示指标关联的引用计算指标
+
+			activeTab:'',
 		};
 	},
 	computed: {
@@ -622,6 +645,7 @@ export default {
 		// /* 表格id */
 		select_id(newval) {
 			this.detail_show_chart = true;
+			this.activeTab='Chart'
 			this.$nextTick(()=>{
 				//切换为曲线图 重置选择状态
 				if(this.$refs.detailComponentRef){
@@ -639,6 +663,7 @@ export default {
 		select_classify(newval) {
 			if(this.$refs.listRef) this.$refs.listRef.scrollTop = 0;
 			if(newval) {
+				this.activeTab = ''
 				this.public_page = 1;
 				this.getPublicList()
 			}
@@ -673,17 +698,27 @@ export default {
 			this.$nextTick(()=>{
 				setTimeout(() => {
 				const dom = document.querySelector(".el-tree-node.is-current");
-				const parentDom = document.querySelector(".tree-cont");
+				const parentDom = document.querySelector(".target_tree");
 				if (!dom || !parentDom) {
 					this.searchLoading = false;
 					return;
 				}
-				if (dom.offsetTop > parentDom.offsetHeight) {
+				/* if (dom.offsetTop > parentDom.offsetHeight) {
 					parentDom.scrollTo({
 						top: dom.offsetTop - parentDom.offsetHeight / 2,
 						left: 0,
 						behavior: "smooth",
 					});
+				} */
+				//parent可视区间:[scrollTop,scrollTop+offsetHeight]
+				//node位置:node.offsetTop
+				const overTop = dom.offsetTop+dom.clientHeight<parentDom.scrollTop
+				const overBottom = dom.offsetTop+dom.clientHeight+30>parentDom.scrollTop+parentDom.offsetHeight
+				if(overTop){
+					parentDom.scrollTop = dom.offsetTop-30
+				}
+				if(overBottom){
+					parentDom.scrollTop =  dom.offsetTop - parentDom.offsetHeight/2
 				}
 				this.searchLoading = false;
 			}, 300);
@@ -762,8 +797,31 @@ export default {
 			})
 			if(Ret !== 200) return
 			this.$message.success('保存成功')
+
+			this.setChartImage()
 		},
 
+		 /* 关联图片 */
+    setChartImage() {
+      let svg = this.$refs.detailComponentRef.$refs.chartInfo.$refs.chartRef.chart.getSVG({
+        chart: {
+          width: 340,
+          height: 230,
+        },
+      });
+      let form = new FormData();
+      form.append("Img", svg);
+      this.setImageHandle(form);
+    },
+
+    async setImageHandle(form) {
+      let { Data } = await dataBaseInterface.uploadImgSvg(form);
+      await preDictEdbInterface.setImg({
+        EdbInfoId: this.select_id,
+        ImageUrl: Data.ResourceUrl,
+      });
+    },
+
 		/* 添加一级目录 */
 		addLevelOneHandle() {
 			this.dialog_title = '添加';
@@ -1023,6 +1081,7 @@ export default {
 					//计算指标
 					this.setComputedDialogForm(res.Data,type);
 					this.computed_type =[47,48].includes(Source)?'joint': Source;
+					this.computed_type = [72,73].includes(Source)? 'alpha': Source;
 				}
 
 			})
@@ -1094,6 +1153,16 @@ export default {
 					moveVal: Source === 46 ? CalculateFormula : '',
 					calendar_type: Source === 49 ? Calendar : '',
 				}
+
+				if([72,73].includes(Source)){
+					this.operationForm = {
+						edb_id: EdbInfoId,
+						oldedb_id: CalculateList[0].FromEdbInfoId,
+						oldEdb_name: CalculateList[0].FromEdbName,
+						EdbName,Frequency,Unit,ClassifyId,Formula:CalculateFormula,
+						view: type === 'view'
+					}
+				}
 			}
 		},
 
@@ -1319,6 +1388,10 @@ export default {
 				this.dynamicNode = _node;
 				this.dynamicNode&&this.resetNodeStyle(this.dynamicNode)
 			})
+		},
+		changeShowType(){
+			if(!this.activeTab) return
+			this.detail_show_chart = this.activeTab==='Chart'?true:false
 		}
 	},
 	mounted() {
@@ -1346,6 +1419,50 @@ export default {
 	}
 }
 </script>
+<style lang="scss">
+.predictEdb-container{
+	.detail-header{
+		display: flex;
+		position: relative;
+		height: 60px;
+		.el-tabs{
+			width:200px;
+			.el-tabs__header{
+				margin-bottom: 0;
+			}
+			.el-tabs__nav{
+				display: flex;
+				width: 100%;
+				.el-tabs__item{
+					flex: 1;
+					text-align: center;
+					font-size: 16px;
+					height: 60px;
+					line-height: 60px;
+				}
+			}
+		}
+	}
+	.edb-tool{
+		flex: 1;
+		text-align: right;
+		display: flex;
+		gap: 16px;
+		justify-content: flex-end;
+		padding-right: 15px;
+		position: relative;
+		&::after{
+			position: absolute;
+			content:'';
+			width:100%;
+			left: 0;
+			bottom: 0;
+			height:2px;
+			background-color: #E4E7ED;
+		}
+	}
+}
+</style>
 <style lang='scss' scoped>
 @import "~@/styles/theme-vars.scss";
 *{ box-sizing: border-box;}
@@ -1404,11 +1521,13 @@ $mini-font: 12px; $normal-font: 14px;
 
 			.tree-cont {
 				padding: 0 20px 30px 20px;
-				max-height: calc(100vh - 280px);
-				overflow: auto;
+				/* max-height: calc(100vh - 280px);
+				overflow: auto; */
 			}
 			.target_tree {
 				color: #333;
+				max-height: calc(100vh - 400px);
+				overflow-y:auto;
 				.custom-tree-node {
 					display: flex !important;
 					justify-content: space-between;
@@ -1426,7 +1545,7 @@ $mini-font: 12px; $normal-font: 14px;
 				}
 			}
 			.noDepart {
-				margin: 60px 0;
+				margin: 30px 0;
 				display: flex;
 				align-items: center;
 				justify-content: center;
@@ -1474,8 +1593,9 @@ $mini-font: 12px; $normal-font: 14px;
 				}
 				.detail-wrap {
 					position: relative;
-					padding: 30px 20px;
-					height: calc(100vh - 190px);
+					padding: 16px;
+					height: calc(100vh - 180px);
+					overflow-y: auto;
 					.toggle-text {
 						position: absolute;
 						right: 20px;
@@ -1527,7 +1647,7 @@ $mini-font: 12px; $normal-font: 14px;
 						.chart-img {
 							width: 100%;
 							height: 230px;
-							object-fit: cover !important;
+							object-fit: fill !important;
 							cursor: pointer;
 						}
 						.item-bottom {

+ 93 - 4
src/views/report_manage/addreportNew.vue

@@ -49,6 +49,12 @@
 					>存草稿</el-button
 				>
 				<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
+					type="primary"
+					size="medium"
+					@click.native="clickreportadd('dsfb')"
+					>定时发布</el-button
+				>
+				<el-button
 					type="primary"
 					size="medium"
 					@click.native="clickreportadd('fb')"
@@ -293,8 +299,38 @@
 				<div v-if="tabsactive == 'MyETA批量插入'">
 					<importMyChart @handleImportMyChart="handleImportMyChart"/>
 				</div>
+				<div v-if="tabsactive == '语义分析插入'">
+					<importSemantics @handleImportSemantic="(item)=>insertHtml(item,'image')"/>
+				</div>
 			</div>
 		</div>
+
+		<!-- 定时发布弹窗 -->
+		<el-dialog 
+			v-dialogDrag 
+			:append-to-body="true" 
+			:visible.sync="showDSFB" 
+			width="500px" 
+			title="定时发布"
+		>
+			<div>
+				<div>
+					<span>发送时间</span>
+					<el-date-picker
+						v-model="taskTime"
+						type="datetime"
+						placeholder="选择日期时间"
+						value-format="yyyy-MM-dd HH:mm"
+						:picker-options="timePickerOpt"
+					/>
+				</div>
+				<p style="margin:15px 0">设置成功之后,研报将定时进行发送。</p>
+				<div style="text-align:right;margin:20px 0">
+					<el-button type="primary" plain @click="showDSFB=false">取消</el-button>
+					<el-button type="primary" @click="handleSetReportPrepublish">确定</el-button>
+				</div>
+			</div>
+		</el-dialog>
 	</div>
 </template>
 
@@ -309,7 +345,8 @@ import {
 	reportauthor,
 	getDraft,
 	dataBaseInterface,
-	sandInterface
+	sandInterface,
+	reportSetPrepublish
 } from '@/api/api.js';
 import http from '@/api/http.js';
 import VueFroala from 'vue-froala-wysiwyg';
@@ -317,6 +354,7 @@ import urlSlug from 'url-slug';
 import mixinMsg from './mixins/messagePush'
 import reportMixin from './mixins/reportMixin';
 import importMyChart from './components/importMyChart.vue'
+import importSemantics from './components/importSemantics.vue';
 export default {
 	mixins:[mixinMsg,reportMixin],
 	data() {
@@ -596,7 +634,7 @@ export default {
 						this.isMessagePost = false; 
 						this.reporteditMsg(params2,tp)
 					}else if(isPost){
-						this.$confirm('发布后,是否推送模板消息和客户群?', '发布提示', {
+						this.$confirm('发布后,是否推送模板消息?', '发布提示', {
 								confirmButtonText: '推送',
 								cancelButtonText: '不推送',
 								type: 'warning',
@@ -633,7 +671,7 @@ export default {
 						this.isMessagePost = false; 
 						this.reportaddMsg(params,tp)
 					}else if(isPost){
-						this.$confirm('发布后,是否推送模板消息和客户群?', '发布提示', {
+						this.$confirm('发布后,是否推送模板消息?', '发布提示', {
 								confirmButtonText: '推送',
 								cancelButtonText: '不推送',
 								type: 'warning',
@@ -674,6 +712,57 @@ export default {
 				}
 			});
 		},
+		// 定时发布报告
+		handleSetReportPrepublish(){
+			if(!this.taskTime){
+				this.$message.warning('请选择定时发布的时间')
+				return
+			}
+			const now=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+			console.log(now);
+			console.log(this.taskTime);
+			if(this.$moment(this.taskTime).isBefore(now,'second')){
+				this.$message.warning('定时发布不得早于当前时间')
+				return
+			}
+			console.log('定时去发布了');
+			this.$confirm('是否发布定时报告,并推送模板消息?', '发布提示', {
+				confirmButtonText: '推送',
+				cancelButtonText: '不推送',
+				type: 'warning',
+				distinguishCancelAndClose:true,
+				beforeClose:(action, instance,done)=>{
+					console.log(action, instance);
+					if(action==='close'||action==='cancel') {
+						//右上角或者不推送
+						reportSetPrepublish({
+							ReportId:Number(this.report_draft_id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:0,
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success('定时发布成功!')
+								this.$router.push({ path: '/reportlist' });
+							}
+						})
+					} else {
+						//confirmButton
+						reportSetPrepublish({
+							ReportId:Number(this.report_draft_id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:1,
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success('定时发布成功!')
+								this.$router.push({ path: '/reportlist' });
+							}
+						})
+					}
+					done()
+				}
+			})
+
+		},
 		//批量插入我的图表
 		handleImportMyChart(data){
 			//设置编辑器获取焦点
@@ -791,7 +880,7 @@ export default {
 			});
 		},
 	},
-	components: {importMyChart},
+	components: {importMyChart,importSemantics},
 	watch: {
 		'aeForm.add_type'(to, from) {
 			if (from == 2 && to == 1) {

+ 121 - 0
src/views/report_manage/components/importSemantics.vue

@@ -0,0 +1,121 @@
+<template>
+    <div class="import-mychart-wrap">
+        <div>
+            <el-input
+				placeholder="关键词搜索"
+				v-model="keyword"
+				size="medium"
+				prefix-icon="el-icon-search"
+                @input="handleChange"
+			/>
+		</div>
+		<div class="list" v-infinite-scroll="load" v-if="list.length>0">
+            <div class="item" v-for="item in list" :key="item.SaCompareId" @click="handleClickItem(item)">
+                <p>{{ item.Title }}</p>
+                <img :src="item.PicUrl" alt="">
+            </div>
+		</div>
+        <div v-if="list.length==0" class="empty-box">
+            无数据
+        </div>
+    </div>
+</template>
+
+<script>
+import {semanticInterface} from '@/api/modules/semanticsApi.js';
+export default {
+    data() {
+        return {
+            keyword:'',
+            pageSize:20,
+			CurrentIndex: 1,
+			list:[],
+            loading:false,
+            finished:false,
+
+        }
+    },
+    mounted(){
+        this.handleGetList()
+    },  
+    methods: {
+		async handleGetList(){
+            this.loading=true
+            const res=await semanticInterface.compareSearch({
+				PageSize: this.pageSize,
+				CurrentIndex: this.CurrentIndex,
+				Keyword: this.keyword
+			})
+            this.loading=false
+            let arr=res.Data.List||[]
+            arr=arr.map(item => {
+               return {
+                   ...item,
+                   PicUrl:item.ResultImg
+               } 
+            });
+
+            this.list=[...this.list,...arr]
+            if(!res.Data){
+                this.finished=true
+            }
+            if(res.Data&&res.Data.Paging.IsEnd){
+                this.finished=true
+            }
+		},
+
+        handleChange(){
+            console.log('aaa');
+            this.CurrentIndex=1
+            this.finished=false
+            this.list=[]
+            this.handleGetList()
+        },
+
+        load(){
+            if(this.finished) return
+            this.CurrentIndex++
+            this.handleGetList()
+        },
+
+        handleClickItem(item){
+           this.$emit('handleImportSemantic',item)
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap{
+    .list{
+        height: calc(100vh - 320px);
+        overflow-x: hidden;
+		overflow-y: auto;
+        .item{
+            width: 100%;
+            margin: 20px 0;
+            padding: 20px;
+            box-sizing: border-box;
+            border: 1px solid #eaeaea;
+            border-radius: 10px;
+            position: relative;
+            overflow: hidden;
+            p{
+                text-align: center;
+                font-size: 16px;
+                margin-bottom: 10px;
+                color: #5882EF;
+            }
+            img{
+                width: 100%;
+            }
+        }
+    }
+    .empty-box{
+        height: calc(100vh - 320px);
+        text-align: center;
+        color: #999;
+        padding-top: 100px;
+    }
+}
+</style>

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

@@ -120,7 +120,7 @@ export default {
         if(to.query.type){
             to.matched[1].name=`编辑${to.query.type=='day'?'晨报':'周报'}`
         }else{
-            to.matched[1].name='编辑晨报/周报'
+            to.matched[1].name='添加晨报/周报'
         }
         next()
     },

+ 100 - 90
src/views/report_manage/editChapterReport.vue

@@ -162,93 +162,91 @@
             </el-form-item>
           </el-form>
         </div>
-				<div v-if="tabsactive == '图表插入'">
-					<el-input
-						placeholder="图表名称"
-						v-model="key_word"
-						size="medium"
-						prefix-icon="el-icon-search"
-						@input="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}"
-					>
-					</el-input>
-					<el-radio-group v-model="chart_source" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="margin-top: 10px;">
-						<el-radio :label="1">ETA图库</el-radio>
-						<el-radio :label="2">商品价格曲线</el-radio> 
-						<el-radio :label="3">相关性图表</el-radio>
-						<el-radio :label="6">拟合方程曲线</el-radio>
-						<el-radio :label="7">统计特征</el-radio>
-					</el-radio-group>
-					<div style="margin: 10px 0">
-						<el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>
-					</div>
-					<div
-						id="reportwin"
-						ref="chartListRef"
-						style="
-							height: calc(100vh - 370px);
-							overflow-x: hidden;
-							overflow-y: auto;
-						"
-						v-infinite-scroll="loadReportHandle"
-						:infinite-scroll-immediate="false"
-					>
-						<template v-if="newreportlist.length">
-							<div
-								v-for="(item, index) in newreportlist"
-								:key="item.ChartInfoId"
-								:style="item.Disabled && 'cursor: not-allowed;'"
-								class="liststy"
-							>
-								<p class="color_primary">{{ item.ChartName }}</p>
-								<img
-									:src="item.ChartImage"
-									:id="'listnode' + index"
-									@click="insertHtml(item)"
-								/>
-							</div>
-						</template>
-
-						<tableNoData text="暂无图表" size="mini" v-else/>
-					</div>
-
-				</div>
-				<div v-if="tabsactive == '沙盘插入'">
-					<el-input
-						placeholder="沙盘名称/品种"
-						v-model="sandTabelQuery.Keyword"
-						size="medium"
-						prefix-icon="el-icon-search"
-					>
-					</el-input>
-					<div
-						id="sandTable-container"
-						ref="sandTable"
-						style="
-							height: calc(100vh - 370px);
-							overflow-x: hidden;
-							overflow-y: auto;
-						"
-						@scroll="sandTableHandleScroll"
-					>
-						<template v-if="sandTableList.length">
-							<div
-								v-for="(item, index) in sandTableList"
-								:key="item.SandboxId"
-								class="liststy"
-							>
-								<p class="color_primary">{{ item.Name }}</p>
-								<img
-									:src="item.PicUrl"
-									:id="'sandTable' + index"
-									@click="insertHtml(item,'image')"
-								/>
-								<p class="source-identification">来源:弘则研究</p>
-							</div>
-						</template>
-						<tableNoData text="暂无数据" size="mini" v-else/>
-					</div>
-				</div>
-				<div v-if="tabsactive == '表格插入'">
+        <div v-if="tabsactive == '图表插入'">
+          <el-input
+            placeholder="标题/子标题/作者"
+            v-model="key_word"
+            size="medium"
+            prefix-icon="el-icon-search"
+            @input="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}"
+          >
+          </el-input>
+          <el-radio-group v-model="chart_source" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="margin-top: 10px;">
+            <el-radio :label="1">ETA图库</el-radio>
+            <el-radio :label="2">商品价格曲线</el-radio>
+            <el-radio :label="3">相关性图表</el-radio>
+            <el-radio :label="6">拟合方程曲线</el-radio>
+            <el-radio :label="7">统计特征</el-radio>
+          </el-radio-group>
+          <div style="margin: 10px 0">
+            <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">只看我的</el-checkbox>
+          </div>
+          <div
+            id="reportwin"
+            ref="chartListRef"
+            style="
+              height: calc(100vh - 370px);
+              overflow-x: hidden;
+              overflow-y: auto;
+            "
+            v-infinite-scroll="loadReportHandle"
+            :infinite-scroll-immediate="false"
+          >
+          <template v-if="newreportlist.length">
+            <div
+              v-for="(item, index) in newreportlist"
+              :key="item.ChartInfoId"
+              class="liststy"
+              :style="item.Disabled && 'cursor: not-allowed;'"
+            >
+              <p class="color_primary">{{ item.ChartName }}</p>
+              <img
+                :src="item.ChartImage"
+                :id="'listnode' + index"
+                @click="insertHtml(item)"
+              />
+            </div>
+          </template>
+          <tableNoData text="暂无图表" size="mini" v-else/>
+          </div>
+        </div>
+        <div v-if="tabsactive == '沙盘插入'">
+          <el-input
+            placeholder="沙盘名称/品种"
+            v-model="sandTabelQuery.Keyword"
+            size="medium"
+            prefix-icon="el-icon-search"
+          >
+          </el-input>
+          <div
+            id="sandTable-container"
+            ref="sandTable"
+            style="
+              height: calc(100vh - 370px);
+              overflow-x: hidden;
+              overflow-y: auto;
+            "
+            @scroll="sandTableHandleScroll"
+          >
+            <template v-if="sandTableList.length">
+            <div
+              v-for="(item, index) in sandTableList"
+              :key="item.SandboxId"
+              class="liststy"
+            >
+              <p class="color_primary">{{ item.Name }}</p>
+              <img
+                :src="item.PicUrl"
+                :id="'sandTable' + index"
+                @click="insertHtml(item, 'image')"
+              />
+              <p class="source-identification">来源:弘则研究</p>
+            </div>
+            </template>
+            <tableNoData text="暂无数据" size="mini" v-else/>
+          </div>
+        </div>
+        <div v-if="tabsactive == '表格插入'">
 					<el-input
 						placeholder="表格名称"
 						v-model="sheetSearchObj.Keyword"
@@ -283,8 +281,11 @@
 						<tableNoData text="暂无数据" size="mini" v-else/>
 					</div>
 				</div>
-				<div v-if="tabsactive == 'MyETA批量插入'">
-					<importMyChart @handleImportMyChart="handleImportMyChart"/>
+        <div v-if="tabsactive == 'MyETA批量插入'">
+          <importMyChart @handleImportMyChart="handleImportMyChart" />
+        </div>
+        <div v-if="tabsactive == '语义分析插入'">
+					<importSemantics @handleImportSemantic="(item)=>insertHtml(item,'image')"/>
 				</div>
       </div>
     </div>
@@ -317,6 +318,7 @@ import mixinMsg from "./mixins/messagePush";
 import reportMixin from './mixins/reportMixin';
 import moment from "moment";
 import importMyChart from "./components/importMyChart.vue";
+import importSemantics from './components/importSemantics.vue';
 let ALOSSINS = null; //阿里云上传实例
 export default {
   beforeRouteEnter(to, from, next) {
@@ -329,7 +331,15 @@ export default {
   },
   mixins: [mixinMsg,reportMixin],
   data() {
+    let that=this
     return {
+      weekPanelTabs:[
+        "基础信息",
+        "图表插入",
+        "MyETA批量插入",
+        "沙盘插入",
+        "语义分析插入"
+      ],
       //批量导入图表
       importChartNum: 0, //批量导入图表的数量 如果大于0则说明在加载
 
@@ -855,7 +865,7 @@ export default {
       }
     },
   },
-  components: { importMyChart },
+  components: { importMyChart,importSemantics },
 };
 </script>
 

+ 109 - 2
src/views/report_manage/editreportNew.vue

@@ -49,6 +49,12 @@
 					>存草稿</el-button
 				>
 				<el-button v-permission="permissionBtn.reportManageBtn.reportManage_publish"
+					type="primary"
+					size="medium"
+					@click.native="clickreportadd('dsfb')"
+					>定时发布</el-button
+				>
+				<el-button
 					type="primary"
 					size="medium"
 					@click.native="clickreportadd('fb')"
@@ -290,8 +296,38 @@
 				<div v-if="tabsactive == 'MyETA批量插入'">
 					<importMyChart @handleImportMyChart="handleImportMyChart"/>
 				</div>
+				<div v-if="tabsactive == '语义分析插入'">
+					<importSemantics @handleImportSemantic="(item)=>insertHtml(item,'image')"/>
+				</div>
 			</div>
 		</div>
+
+		<!-- 定时发布弹窗 -->
+		<el-dialog 
+			v-dialogDrag 
+			:append-to-body="true" 
+			:visible.sync="showDSFB" 
+			width="500px" 
+			title="定时发布"
+		>
+			<div>
+				<div>
+					<span>发送时间</span>
+					<el-date-picker
+						v-model="taskTime"
+						type="datetime"
+						placeholder="选择日期时间"
+						value-format="yyyy-MM-dd HH:mm"
+						:picker-options="timePickerOpt"
+					/>
+				</div>
+				<p style="margin:15px 0">设置成功之后,研报将定时进行发送。</p>
+				<div style="text-align:right;margin:20px 0">
+					<el-button type="primary" plain @click="showDSFB=false">取消</el-button>
+					<el-button type="primary" @click="handleSetReportPrepublish">确定</el-button>
+				</div>
+			</div>
+		</el-dialog>
 	</div>
 </template>
 
@@ -305,7 +341,8 @@ import {
 	reportauthor,
 	classifyIdDetail,
 	dataBaseInterface,
-	sandInterface
+	sandInterface,
+	reportSetPrepublish
 } from 'api/api.js';
 import VueFroala from 'vue-froala-wysiwyg';
 import urlSlug from 'url-slug';
@@ -313,6 +350,7 @@ import http from '@/api/http.js';
 import mixinMsg from './mixins/messagePush'
 import reportMixin from './mixins/reportMixin';
 import importMyChart from './components/importMyChart.vue'
+import importSemantics from './components/importSemantics.vue';
 export default {
 	mixins:[mixinMsg,reportMixin],
 	data() {
@@ -530,6 +568,10 @@ export default {
 						content: data.Content,
 					};
 					this.ThsMsgIsSend=data.ThsMsgIsSend
+					// 回显定时发布时间
+					if(data.PrePublishTime){
+						this.taskTime=data.PrePublishTime
+					}
 				}
 			});
 		},
@@ -663,6 +705,71 @@ export default {
 				}
 			});
 		},
+		// 定时发布报告
+		handleSetReportPrepublish(){
+			if(!this.taskTime){
+				this.$message.warning('请选择定时发布的时间')
+				return
+			}
+			const now=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+			console.log(now);
+			console.log(this.taskTime);
+			if(this.$moment(this.taskTime).isBefore(now,'second')){
+				this.$message.warning('定时发布不得早于当前时间')
+				return
+			}
+			console.log('定时去发布了');
+			// 如果改报告已经推送过模板消息
+			if(this.ThsMsgIsSend==1){
+				reportSetPrepublish({
+					ReportId:Number(this.report_id),
+					PrePublishTime:this.taskTime,
+					PreMsgSend:0,
+				}).then(res=>{
+					if(res.Ret===200){
+						this.$message.success('定时发布成功!')
+						this.$router.push({ path: '/reportlist' });
+					}
+				})
+				return
+			}
+			this.$confirm('是否发布定时报告,并推送模板消息?', '发布提示', {
+				confirmButtonText: '推送',
+				cancelButtonText: '不推送',
+				type: 'warning',
+				distinguishCancelAndClose:true,
+				beforeClose:(action, instance,done)=>{
+					console.log(action, instance);
+					if(action==='close'||action==='cancel') {
+						//右上角或者不推送
+						reportSetPrepublish({
+							ReportId:Number(this.report_id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:0,
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success('定时发布成功!')
+								this.$router.push({ path: '/reportlist' });
+							}
+						})
+					} else {
+						//confirmButton
+						reportSetPrepublish({
+							ReportId:Number(this.report_id),
+							PrePublishTime:this.taskTime,
+							PreMsgSend:1,
+						}).then(res=>{
+							if(res.Ret===200){
+								this.$message.success('定时发布成功!')
+								this.$router.push({ path: '/reportlist' });
+							}
+						})
+					}
+					done()
+				}
+			})
+
+		},
 		//批量插入我的图表
 		handleImportMyChart(data){
 			//设置编辑器获取焦点
@@ -779,7 +886,7 @@ export default {
 			});
 		},
 	},
-	components: {importMyChart},
+	components: {importMyChart,importSemantics},
 };
 </script>
 

+ 7 - 5
src/views/report_manage/mixins/messagePush.js

@@ -1,4 +1,5 @@
 import { reportadd, reportedit, messagePushPost,dataBaseInterface,reportMessageSend } from "@/api/api.js";
+import { getUrlParams } from '@/utils/common'
 export default {
   data() {
     return {
@@ -26,7 +27,8 @@ export default {
             } else {
               this.publishreport(res.Data.ReportId);
             }
-          } else {
+          } else if(tp=='dsfb'){
+            this.showDSFB=true
             // this.$router.push({path:'/reportlist'});
           }
         }
@@ -53,7 +55,8 @@ export default {
             } else {
               this.publishreport(res.Data.ReportId);
             }
-          } else {
+          } else if(tp=='dsfb'){
+            this.showDSFB=true
             // this.$router.push({path:'/reportlist'});
           }
           //已经添加过报告
@@ -68,13 +71,12 @@ export default {
       $('iframe').each((k,i) => {
         try {
           let href = $(i).attr('src');
-          code_arr.push(href.slice(href.indexOf('code=') + 5));
+          code_arr.push(getUrlParams(href,'code'));
     
         } catch (err) {
         }
       });
-      
-      // console.log(code_arr);
+
       if(!code_arr.length) return this.$message.warning('请插入图表');
 
       const loading = this.$loading({

+ 28 - 0
src/views/report_manage/mixins/reportMixin.js

@@ -7,6 +7,23 @@ import {
   statisticFeatureInterface,
 } from "@/api/modules/chartRelevanceApi";
 export default {
+  watch:{
+    'taskTime'(){
+          this.taskTime=this.$moment(this.taskTime).format('YYYY-MM-DD HH:mm')+':00'
+			    const date = this.$moment(this.taskTime).startOf('day').format('x');
+	        const nowDate = this.$moment().startOf('day').format('x');
+	        // 如果选择的是今天 则需要禁用已经过去的时间节点
+	        if (date <= nowDate) {
+	            // 默认选择的最新时间 是当前时间的两分钟后 (留出2分钟的富裕时间)
+	            this.timePickerOpt.selectableRange = (
+	                `${this.$moment().add(2,'m').format('HH:mm:ss')} - 23:59:59`
+	            );
+	        }else {
+				// 如果是以后的日期,则不需要禁用时间节点
+	            this.timePickerOpt.selectableRange = '00:00:00 - 23:59:59';
+	        }
+		},
+  },
   data() {
     let that = this;
     return {
@@ -139,6 +156,7 @@ export default {
         "MyETA批量插入",
         "表格插入",
         "沙盘插入",
+        "语义分析插入"
       ],
 
       sheetSearchObj: {},
@@ -163,6 +181,16 @@ export default {
 
       isShowMe: false,
       autoSaveFlag: true, //是否开启自动保存
+
+      showDSFB:false,//显示定时发布弹窗
+			taskTime:'',//定时发布的时间
+			timePickerOpt:{
+				disabledDate(e){
+					return e.getTime()< new Date().getTime()-24 * 60 * 60 * 1000
+				},
+				selectableRange:'00:00:00 - 23:59:59',
+        format:'HH:mm'
+			},
     };
   },
 

+ 103 - 2
src/views/report_manage/reportEn/reportEditor.vue

@@ -64,6 +64,12 @@
 					>存草稿</el-button
 				>
 				<el-button v-permission="permissionBtn.enReportManageBtn.enReport_publish"
+					type="primary"
+					size="medium"
+					@click.native="clickreportadd('dsfb')"
+					>定时发布</el-button
+				>
+				<el-button
 					type="primary"
 					size="medium"
 					@click.native="clickreportadd('fb')"
@@ -299,6 +305,9 @@
 				<div v-if="tabsactive == 'MyETA批量插入'">
 					<importMyChart @handleImportMyChart="handleImportMyChart" :showEnMark="true" />
 				</div>
+				<div v-if="tabsactive == '语义分析插入'">
+					<importSemantics @handleImportSemantic="(item)=>insertHtml(item,'image')"/>
+				</div>
 			</div>
 		</div>
 
@@ -313,6 +322,33 @@
       :edblist="enChartInfo.ChartType===10?enEdblist:[]"
 		/>
 
+		<!-- 定时发布弹窗 -->
+		<el-dialog 
+			v-dialogDrag 
+			:append-to-body="true" 
+			:visible.sync="showDSFB" 
+			width="500px" 
+			title="定时发布"
+		>
+			<div>
+				<div>
+					<span>发送时间</span>
+					<el-date-picker
+						v-model="taskTime"
+						type="datetime"
+						placeholder="选择日期时间"
+						value-format="yyyy-MM-dd HH:mm"
+						:picker-options="timePickerOpt"
+					/>
+				</div>
+				<p style="margin:15px 0">设置成功之后,研报将定时进行发送。</p>
+				<div style="text-align:right;margin:20px 0">
+					<el-button type="primary" plain @click="showDSFB=false">取消</el-button>
+					<el-button type="primary" @click="handleConfirmDSFB">确定</el-button>
+				</div>
+			</div>
+		</el-dialog>
+
 	</div>
 </template>
 
@@ -329,6 +365,7 @@ import mixinMsg from '../mixins/messagePush'
 import reportMixin from '../mixins/reportMixin';
 import importMyChart from '../components/importMyChart.vue'
 import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue'
+import importSemantics from '../components/importSemantics.vue';
 export default {
 	mixins:[mixinMsg,reportMixin],
 	data() {
@@ -439,9 +476,26 @@ export default {
         language: "zh_cn",
         //允许粘贴的样式
         pasteAllowedStyleProps: ['font-family', 'font-size', 'color']
-      }
+      },
+
+			showDSFB:false,//显示定时发布弹窗
+			taskTime:'',//定时发布的时间
+			timePickerOpt:{
+				disabledDate(e){
+					return e.getTime()< new Date().getTime()-24 * 60 * 60 * 1000
+				},
+				selectableRange:'00:00:00 - 23:59:59'
+			},
 		};
 	},
+	beforeRouteEnter(to, from, next) {
+        if(to.query.id){
+            to.matched[1].name=`编辑英文研报`
+		}else{
+			to.matched[1].name=`添加英文研报`
+		}
+        next()
+    },
 	mounted() {
 		this.$route.query.id && this.getreportdetail();
 		this.getclassifylist();
@@ -473,6 +527,20 @@ export default {
 			this.$refs.sandTable.scrollTop=0
 			this.sandTabelQuery.CurrentIndex = 1
 			this.getSandTable()
+		},
+		'taskTime'(){
+			const date = this.$moment(this.taskTime).startOf('day').format('x');
+	        const nowDate = this.$moment().startOf('day').format('x');
+	        // 如果选择的是今天 则需要禁用已经过去的时间节点
+	        if (date <= nowDate) {
+	            // 默认选择的最新时间 是当前时间的两分钟后 (留出2分钟的富裕时间)
+	            this.timePickerOpt.selectableRange = (
+	                `${this.$moment().add(2,'m').format('HH:mm:ss')} - 23:59:59`
+	            );
+	        }else {
+				// 如果是以后的日期,则不需要禁用时间节点
+	            this.timePickerOpt.selectableRange = '00:00:00 - 23:59:59';
+	        }
 		}
 	},
 	methods: {
@@ -598,6 +666,10 @@ export default {
 						content: data.Content,
             overview:data.Overview||''
 					};
+					// 回显定时发布时间
+					if(data.PrePublishTime){
+						this.taskTime=data.PrePublishTime
+					}
 				}
 			});
 		},
@@ -674,7 +746,12 @@ export default {
 					});
 					window.open(href, "_blank");
 				} else if (tp === "fb") {
+					this.$confirm('是否确定立即发布报告?','提示',{type: 'warning'}).then(()=>{
 						this.publishreport(this.report_id);
+					})
+				}else if(tp==='dsfb'){
+					//定时发布
+					this.showDSFB=true
 				}
 			// if (tp == 'yl') { //预览
 			// 	sessionStorage.setItem('reportdtl', JSON.stringify(params));
@@ -698,6 +775,30 @@ export default {
 			});
 		},
 
+		//定时发布报告
+		handleConfirmDSFB(){
+			if(!this.taskTime){
+				this.$message.warning('请选择定时发布的时间')
+				return
+			}
+			const now=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+			console.log(now);
+			console.log(this.taskTime);
+			if(this.$moment(this.taskTime).isBefore(now,'second')){
+				this.$message.warning('定时发布不得早于当前时间')
+				return
+			}
+			reportEnInterface.enReportPrepblish({
+				ReportId:this.report_id,
+				PrePublishTime:this.taskTime
+			}).then(res=>{
+				if(res.Ret===200){
+					this.$message.success('定时发布成功!')
+					this.$router.push({ path: '/reportEnList' });
+				}
+			})
+		},
+
 		//批量插入我的图表
 		handleImportMyChart(data){
 			//设置编辑器获取焦点
@@ -817,7 +918,7 @@ export default {
 			});
 		},
 	},
-	components: {importMyChart,setEnNameDia},
+	components: {importMyChart,setEnNameDia,importSemantics},
 };
 </script>
 

+ 48 - 10
src/views/report_manage/reportEn/reportlist.vue

@@ -15,11 +15,23 @@
           <el-form-item label="">
             <el-button 
               v-permission="permissionBtn.enReportManageBtn.enReport_syncPolicy"
-              type="primary" 
+              type="primary"
+              size="medium"
               :loading="isPull" 
               @click="handlePullReport"
             >同步策略报告</el-button>
           </el-form-item>
+          <el-form-item label="">
+            <el-select
+              v-model="searchform.timeType"
+              placeholder="选择时间类型"
+              size="medium"
+              style="width:110px"
+            >
+              <el-option label="发布时间" value="publish_time"></el-option>
+              <el-option label="更新时间" value="modify_time"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="">
             <el-date-picker
               v-model="searchform.dateValue"
@@ -53,11 +65,23 @@
               size="medium"
             ></el-cascader>
           </el-form-item>
+          <el-form-item label="">
+            <el-select
+              v-model.number="searchform.publishState"
+              placeholder="发布筛选"
+              size="medium"
+              clearable
+              style="width: 140px"
+            >
+              <el-option label="已发布" :value="2"></el-option>
+              <el-option label="未发布" :value="1"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="">
             <el-select
               v-permission="permissionBtn.enReportManageBtn.enReport_sendEmail"
               v-model.number="searchform.EmailState"
-              placeholder="状态筛选"
+              placeholder="群发状态筛选"
               size="medium"
               clearable
               style="width: 140px"
@@ -68,7 +92,7 @@
           </el-form-item>
           <el-form-item>
             <el-input
-              placeholder="标题 / 作者"
+              placeholder="标题 / 创建人"
               v-model="searchform.key_word"
               clearable
               size="medium"
@@ -124,6 +148,12 @@
                 <span v-if="row.PvEmail&&row.Pv" style="color:#333">/</span>
                 <span v-if="row.Pv" style="color:#333">{{row.Pv}}</span>
               </span>
+              <span v-else-if="item.key==='PublishTime'">
+                <span>{{row.PrePublishTime?row.PrePublishTime:row.PublishTime}}</span>
+                <svg v-if="row.PrePublishTime&&row.State===1" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                  <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+                </svg>
+              </span>
 
               <span v-else-if="item.key==='handle'">
                 <template v-if="row.State===1">
@@ -326,12 +356,14 @@ export default {
   data() {
     return {
       searchform: {
+        timeType:'publish_time',
         dateValue:[],
         frequency:'',
         classifynameArr:'',
         state:'',
         key_word:'',
-        EmailState:''
+        EmailState:'',
+        publishState:''
       },
       optionsArr:[],
       frequencyArr: [ '年度','半年度','季度','月度','双周度','周度','日度','不定时' ],
@@ -460,7 +492,9 @@ export default {
         KeyWord:this.searchform.key_word,
         StartDate: this.searchform.dateValue ? this.searchform.dateValue[0] : '',
         EndDate: this.searchform.dateValue ? this.searchform.dateValue[1] : '',
-        EmailState:this.searchform.EmailState
+        EmailState:this.searchform.EmailState,
+        TimeType:this.searchform.timeType,
+        State:this.searchform.publishState.toString()
 			};
 			this.listLoading = true;
 			reportEnInterface.reportList(params).then(res => {
@@ -499,13 +533,17 @@ export default {
     },
 
     /* 发布报告 */
-    publishReport({Id}) {
-      reportEnInterface.reportPublish({ReportIds:String(Id)}).then(res=>{
-				if(res.Ret!==200) return
+    publishReport(item) {
+      this.$confirm(item.PrePublishTime?'该报告已设置定时发布,是否修改为立即发布?':'是否确定立即发布报告?','提示',{type: 'warning'}).then(()=>{
 
-        this.$message.success('发布成功');
-        this.getTableData();
+				reportEnInterface.reportPublish({ReportIds:String(item.Id)}).then(res=>{
+          if(res.Ret!==200) return
+          this.$message.success('发布成功');
+          this.getTableData();
+        })
+        
 			})
+      
     },
 
     /* 编辑报告 */

+ 2 - 2
src/views/report_manage/reportVariety.vue

@@ -40,7 +40,7 @@
         <!-- 品种编辑弹窗 -->
         <el-dialog 
             :modal-append-to-body='false' 
-            :title="!editBreedData.id?'新增分类':'编辑分类'" 
+            :title="!editBreedData.id?'添加品种':'编辑品种'" 
             :visible.sync="showEditBreed" 
             :close-on-click-modal="false"
             :center="true" 
@@ -63,7 +63,7 @@
                         </el-select>
                     </el-form-item>
                     <el-form-item label="后台排序">
-                        <el-input placeholder="后台排序" v-model="editBreedData.sort" type="number" style="width:400px"></el-input>
+                        <el-input placeholder="后台排序" min="0" v-model="editBreedData.sort" type="number" style="width:400px"></el-input>
                     </el-form-item>
                 </el-form>
                 <div style="text-align: center;margin-top:40px">

+ 53 - 11
src/views/report_manage/reportlist.vue

@@ -33,6 +33,18 @@
               </a>
             </template>
           </el-form-item>
+          <el-form-item label="">
+            <el-select
+              v-model="searchform.timeType"
+              placeholder="选择时间类型"
+              size="medium"
+              style="width:110px"
+              @change="search"
+            >
+              <el-option label="发布时间" value="publish_time"></el-option>
+              <el-option label="更新时间" value="modify_time"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="">
             <el-date-picker
               @change="search"
@@ -76,12 +88,25 @@
               size="medium"
             ></el-cascader>
           </el-form-item>
+          <el-form-item label="">
+            <el-select
+              v-model.number="searchform.publishState"
+              placeholder="发布筛选"
+              size="medium"
+              clearable
+              style="width: 140px"
+              @change="search"
+            >
+              <el-option label="已发布" :value="2"></el-option>
+              <el-option label="未发布" :value="1"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item label="">
             <el-select
               v-permission="permissionBtn.reportManageBtn.reportManage_reportList_sendTime"
               @change="search"
               v-model.number="searchform.msgIsSend"
-              placeholder="状态筛选"
+              placeholder="推送消息状态"
               size="medium"
               clearable
               style="width: 140px"
@@ -93,7 +118,7 @@
           <el-form-item>
             <el-input
               @input="search"
-              placeholder="标题 / 作者"
+              placeholder="标题 / 创建人"
               v-model="searchform.key_word"
               clearable
               size="medium"
@@ -184,7 +209,14 @@
             min-width="124"
             align="center"
             :formatter="formatterColumn"
-          ></el-table-column>
+          >
+            <template slot-scope="scope">
+              <span>{{scope.row.PrePublishTime?scope.row.PrePublishTime:scope.row.PublishTime|formatTime}}</span>
+              <svg style="position: relative;top:2px" v-if="scope.row.PrePublishTime&&scope.row.State == '1'" width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+                <path d="M15.2002 8C15.2002 4.13401 12.0662 1 8.20019 1C4.3342 1 1.20019 4.13401 1.2002 8C1.2002 11.866 4.3342 15 8.2002 15C12.0662 15 15.2002 11.866 15.2002 8ZM5.2002 10L5.2002 9L8.17491 9L11.2002 4.5L11.9073 5.20711L8.58912 10L5.2002 10Z" fill="#0052D9"/>
+              </svg>
+            </template>
+          </el-table-column>
           <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_reportList_sendTime)"
             prop="MsgSendTime"
             label="报告推送时间"
@@ -214,14 +246,14 @@
 							<a :href="hostapi+'?ReportId='+parseInt(scope.row.Id)" v-if="scope.row.VideoUrl" :download="scope.row.VideoName" style="cursor:pointer; color:#4099ef;">下载</a>
 						</template>
 					</el-table-column> -->
-          <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_reportList_uv)"
-            label="PV / UV"
+          <el-table-column
+            :label="hasUV?'PV / UV':'PV'"
             align="center"
             :render-header="renderHeader"
             width="140"
           >
             <template slot-scope="scope"
-              >{{ scope.row.Pv }}/{{ scope.row.Uv }}</template
+              >{{ hasUV? scope.row.Pv+'/'+scope.row.Uv:scope.row.Pv }}</template
             >
           </el-table-column>
           <el-table-column label="操作" align="center" min-width="130">
@@ -507,7 +539,7 @@
             class="el-icon-warning"
             style="font-size: 24px; color: #e6a23c; vertical-align: middle"
           ></i>
-          是否发布报告,且推送模板消息和客户群?
+          {{isDSFB?'该报告已设置定时发布,是否立即发布报告并推送模板消息?':'是否立即发布报告,并推送模板消息?'}}
         </div>
         <div style="margin-bottom: 20px; text-align: center">
           <el-button
@@ -515,7 +547,7 @@
             plain
             style="width: 100px"
             @click="handleClosePublish"
-            >取消发布</el-button
+            >取消</el-button
           >
           <el-button
             type="primary"
@@ -573,13 +605,17 @@ export default {
       let tag = false;
       this.tableData.forEach((item) => {
         if (this.batches.includes(item.Id)) {
-          if (item.NeedThsMsg != 0 && item.ThsMsgIsSend == 0) {
+          if (item.MsgIsSend== 0) {
             tag = true;
           }
         }
       });
       return tag;
     },
+    //是否有UV
+    hasUV(){
+      return this.permissionBtn.checkPermissionBtn(this.permissionBtn.reportManageBtn.reportManage_reportList_uv)
+    }
   },
   data() {
     return {
@@ -595,6 +631,7 @@ export default {
       listLoading: false,
       tableData: [],
       searchform: {
+        timeType:'publish_time',
         dateValue: "",
         frequency: "",
         classifynameArr: "",
@@ -602,6 +639,7 @@ export default {
         key_word: "",
         publish_sort: "desc",
         msgIsSend: "",
+        publishState:'',
       },
       batches: [],
       uploadloading: false,
@@ -622,6 +660,7 @@ export default {
       },
 
       showPublish: false,
+      isDSFB:false,//是否为定时发布
       tableKey:0,
     };
   },
@@ -694,14 +733,14 @@ export default {
             },
             "pv:报告被打开的次数,每次打开都计算一次(只统计有权限用户)"
           ),
-          h(
+          this.hasUV?h(
             "p",
             {
               slot: "content",
               attrs: { style: "display:block;padding:5px 0;width:420px;" },
             },
             "uv:访问报告的人数,每篇报告同一个人访问只计算一次(只统计有权限用户)"
-          ),
+          ):h(''),
           h(
             "el-button",
             {
@@ -877,6 +916,7 @@ export default {
       //发布报告
       this.batches = [];
       this.batches.push(item.Id);
+      this.isDSFB=item.PrePublishTime?true:false
 
       // 周报不需要弹窗直接发布
       // 2023/3/6 研报后台5.5中修改 周报校验是否上传了音频
@@ -1007,6 +1047,8 @@ export default {
         KeyWord: this.searchform.key_word,
         MsgIsSend: this.searchform.msgIsSend,
         // PublishSort:this.searchform.publish_sort,
+        State:this.searchform.publishState,
+        TimeType:this.searchform.timeType
       };
       if (this.searchform.dateValue) {
         params.StartDate = this.searchform.dateValue[0];

+ 18 - 2
src/views/resetpassword.vue

@@ -86,7 +86,7 @@
             ></i>
           </el-input>
         </el-form-item>
-        <el-form-item style="text-align: center; padding-top: 20px">
+        <el-form-item style="text-align: center;">
           <el-button type="primary" size="medium" @click.native="addSubmit"
             >确定</el-button
           >
@@ -107,6 +107,7 @@
 import { modifyPwd } from "@/api/api.js";
 import http from "@/api/http.js";
 import md5 from "@/utils/md5.js";
+import{checkPassWord} from '@/utils/commonOptions';
 export default {
   data() {
     return {
@@ -126,6 +127,15 @@ export default {
           },
         ],
         NewPwd: [
+            {
+                validator:(rule,value,callback)=>{
+                    if(!checkPassWord(value)){
+                        callback(new Error('密码要求8位及以上,包含数字、大写字母、小写字母、特殊字符中的三个类型'))
+                    }else{
+                        callback()
+                    }
+                }
+            },
           {
             required: true,
             message: "请输入确认密码",
@@ -188,4 +198,10 @@ export default {
 };
 </script>
 
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+.box-card{
+    .el-form-item{
+        margin-bottom: 40px;
+    }
+}
+</style>

+ 15 - 13
src/views/sandbox_manage/sandFlow/index.vue

@@ -119,9 +119,10 @@ export default {
 		},
 
 		/* 获取画布内容 */
-		getGraphData() {
+		getGraphData(SandboxVersionCode,modifyType) {
 			const { id,type } = this.$route.query;
-
+			const sandbox_versioncode = id||SandboxVersionCode
+			const modify_type = type||modifyType
 			// type === 'edit' && sandInterface.sandData({
 			// 	SandboxId: id
 			// }).then(res => {
@@ -137,9 +138,9 @@ export default {
 			// 	// 轮询
 			// 	this.$route.query.type === 'edit' && this.autoSave();
 			// })
-
+			if(!sandbox_versioncode) return
 			sandInterface.versionData({
-				SandboxVersionCode: id
+				SandboxVersionCode: id||SandboxVersionCode
 			}).then(res => {
 				if(res.Ret !== 200) return
 
@@ -149,14 +150,14 @@ export default {
 					classify: ChartPermissionId
 				}
 				this.initData = JSON.parse(Content);
-                this.$nextTick(()=>{
-                    this.graph.centerContent()
-                })
-				if(type === 'edit') {
+				this.$nextTick(()=>{
+					this.graph.centerContent()
+				})
+				if(modify_type === 'edit') {
 					this.sandInfo = res.Data;
 					// 轮询
 					this.autoSave();
-                    //this.graph.centerContent();
+					//this.graph.centerContent();
 				}
 			})
 		},
@@ -182,9 +183,9 @@ export default {
 				const params = new FormData();
 				params.append('Img',dataUri)
 				const { Data } = await dataBaseInterface.uploadImgSvg(params);
-				let SandboxVersionCode = (this.sand_id && classify === this.sandInfo.ChartPermissionId)  ? this.sand_id : '';
-				
-				const { Ret , Data : sandData} =	await sandInterface.sandSave({
+				//let SandboxVersionCode = (this.sand_id && classify === this.sandInfo.ChartPermissionId)  ? this.sand_id : '';
+				let SandboxVersionCode = this.sand_id
+				const { Ret , Data : sandData} = await sandInterface.sandSave({
 					SandboxVersionCode,
 					Name: name,
 					ChartPermissionId: Number(classify),
@@ -207,7 +208,8 @@ export default {
 						type:'edit',
 						},
 					});
-					this.getGraphData();
+					this.getGraphData(sandData.VersionCode,'edit');
+					return
 				}
 				
 				callback && callback();

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است