Bladeren bron

Merge branch 'master' into cygx_crm_14.7.1

bding 1 jaar geleden
bovenliggende
commit
88ff24b681
100 gewijzigde bestanden met toevoegingen van 7927 en 1331 verwijderingen
  1. 1 0
      config/index.js
  2. 3 0
      src/App.vue
  3. 3 2
      src/api/api.js
  4. 64 2
      src/api/modules/crmApi.js
  5. 136 0
      src/api/modules/overseasCustom.js
  6. 12 1
      src/api/modules/rai/YanXuanApi.js
  7. 7 0
      src/api/modules/rai/raiApi.js
  8. 4 0
      src/api/modules/rai/reportApi.js
  9. 8 1
      src/api/modules/roadshowApi.js
  10. 7 0
      src/api/modules/setApi.js
  11. 65 0
      src/api/modules/statisticApi.js
  12. BIN
      src/assets/img/home/mfyx_icon.png
  13. BIN
      src/assets/img/icons/like-heart.png
  14. 42 4
      src/routes/modules/customRoutes.js
  15. 22 0
      src/routes/modules/ficcXcxRoutes.js
  16. 19 0
      src/routes/modules/researchRoutes.js
  17. 16 0
      src/routes/modules/sellerRoutes.js
  18. 6 0
      src/routes/modules/statisticRoutes.js
  19. 2 2
      src/views/Home.vue
  20. 163 110
      src/views/Login.vue
  21. 4 6
      src/views/business_ETA_manage/businessAuth.vue
  22. 10 4
      src/views/contract_manage/components/ServiceDialog.vue
  23. 53 30
      src/views/contract_manage/components/allocationNumber.vue
  24. 9 1
      src/views/custom_manage/approvalTurn.vue
  25. 1 1
      src/views/custom_manage/approvalUpdate.vue
  26. 74 183
      src/views/custom_manage/compontents/CauthList.vue
  27. 17 13
      src/views/custom_manage/compontents/Contactdialog.vue
  28. 28 7
      src/views/custom_manage/compontents/CpessionTable.vue
  29. 32 4
      src/views/custom_manage/compontents/CpessionTableEquity.vue
  30. 2 1
      src/views/custom_manage/compontents/Ctimeline.vue
  31. 23 5
      src/views/custom_manage/compontents/FreezAuthList.vue
  32. 2 2
      src/views/custom_manage/contacts/contactsList.vue
  33. 45 19
      src/views/custom_manage/customList/addCustom.vue
  34. 78 27
      src/views/custom_manage/customList/applyTurn.vue
  35. 35 6
      src/views/custom_manage/customList/components/raiPermissionbox.vue
  36. 23 22
      src/views/custom_manage/customList/components/shareListDialog.vue
  37. 17 2
      src/views/custom_manage/customList/customAllList.vue
  38. 170 20
      src/views/custom_manage/customList/customDetail.vue
  39. 108 130
      src/views/custom_manage/customList/customList.vue
  40. 37 2
      src/views/custom_manage/customList/customListEn.vue
  41. 249 149
      src/views/custom_manage/customList/customShareList.vue
  42. 20 12
      src/views/custom_manage/customList/editCustom.vue
  43. 5 1
      src/views/custom_manage/customList/editCustomEn.vue
  44. 9 2
      src/views/custom_manage/customList/mixins/customlistMixin.js
  45. 98 0
      src/views/custom_manage/customList/mixins/quartersMixin.js
  46. 13 2
      src/views/custom_manage/customList/regionCustomDetail.vue
  47. 38 11
      src/views/custom_manage/customList/updateServe.vue
  48. 94 130
      src/views/custom_manage/customSearch.vue
  49. 90 0
      src/views/custom_manage/overseasList/components/roadShowsDialog.vue
  50. 173 0
      src/views/custom_manage/overseasList/components/selectSaleDialog.vue
  51. 147 0
      src/views/custom_manage/overseasList/components/totalClicksDialog.vue
  52. 594 0
      src/views/custom_manage/overseasList/overseasCustomList.vue
  53. 680 0
      src/views/custom_manage/overseasList/overseasCustomRoadshow.vue
  54. 437 0
      src/views/custom_manage/points/AddNewEntries.vue
  55. 231 0
      src/views/custom_manage/points/EntryRecords.vue
  56. 211 0
      src/views/custom_manage/points/RankingOverview.vue
  57. 258 0
      src/views/custom_manage/points/RatingOverview.vue
  58. 85 0
      src/views/custom_manage/points/XClassCustom.vue
  59. 213 0
      src/views/dataReport_manage/components/RenewalRateDetail.vue
  60. 162 0
      src/views/dataReport_manage/components/abnormalRenewalChart.vue
  61. 142 42
      src/views/dataReport_manage/equityCustomStatistics.vue
  62. 466 0
      src/views/dataReport_manage/equityPackageStatistics.vue
  63. 1 0
      src/views/dataReport_manage/index.scss
  64. 197 0
      src/views/dataReport_manage/statistic/abnormalRenewal.vue
  65. 106 28
      src/views/dataReport_manage/statistic/contractCustom.vue
  66. 63 14
      src/views/dataReport_manage/statistic/mixin.js
  67. 42 3
      src/views/dataReport_manage/statistic/newCustom.vue
  68. 74 4
      src/views/dataReport_manage/statistic/newCustomlist.vue
  69. 0 3
      src/views/dataReport_manage/statistic/todoTask.vue
  70. 364 0
      src/views/ficc_manage/chapterVariety.vue
  71. 807 0
      src/views/ficc_manage/reportVariety.vue
  72. 4 0
      src/views/ficc_manage/userTableColums.js
  73. 110 0
      src/views/interaction_manage/bannerStatistics.vue
  74. 6 1
      src/views/login_manage/EmailModel.vue
  75. 5 1
      src/views/login_manage/ForgetPassModel.vue
  76. 7 1
      src/views/login_manage/MobileModel.vue
  77. 1 1
      src/views/login_manage/modelMixins.js
  78. 11 6
      src/views/operation_manage/AIQA/AIQA.vue
  79. 1 1
      src/views/operation_manage/AIQA/components/messageItem.vue
  80. 1 2
      src/views/operation_manage/AIQA/components/newWindowHint.vue
  81. 17 8
      src/views/rai_manage/activityManage/activityManage.vue
  82. 16 20
      src/views/rai_manage/activityManage/applyManage.vue
  83. 4 4
      src/views/rai_manage/activityManage/components/addActivity.vue
  84. 1 1
      src/views/rai_manage/activityManage/roadShow/components/addVideoDlg.vue
  85. 1 1
      src/views/rai_manage/activityManage/roadShow/components/releaseAudio.vue
  86. 3 1
      src/views/rai_manage/activityManage/roadShowList.vue
  87. 1 1
      src/views/rai_manage/activityManage/specialResearch.vue
  88. 13 67
      src/views/rai_manage/activityManage/specialResearch/addResearch.vue
  89. 1 1
      src/views/rai_manage/activityManage/specialResearch/determineTravel.vue
  90. 121 134
      src/views/rai_manage/components/addChoiceness.vue
  91. 40 50
      src/views/rai_manage/components/addMorningMeeting.vue
  92. 60 11
      src/views/rai_manage/components/addRoadshow.vue
  93. 1 1
      src/views/rai_manage/components/addSummarizing.vue
  94. 57 4
      src/views/rai_manage/components/addSummary.vue
  95. 1 1
      src/views/rai_manage/components/addThisWeek.vue
  96. 1 2
      src/views/rai_manage/components/apply/applyDialog.vue
  97. 1 0
      src/views/rai_manage/components/reportComponents/RichTextMixins.js
  98. 14 1
      src/views/rai_manage/components/richText.vue
  99. 2 0
      src/views/rai_manage/cygxManage/components/lableDlg.vue
  100. 9 2
      src/views/rai_manage/cygxManage/lableManage.vue

+ 1 - 0
config/index.js

@@ -40,6 +40,7 @@ module.exports = {
 			// target:'http://rddpapi.brilliantstart.cn', // 接口的域名
 			// target:'https://admin.hzinsights.com', // 接口的域名
 	  	   target:'http://8.136.199.33:7777', // 接口的域名
+	  	  //  target:'http://192.168.77.7:8602', // 接口的域名
 			// secure:false,  // 如果是https接口,需要配置这个参数
 			changeOrigin:true, // 如果接口跨域,需要进行这个参数配置
 			pathRewrite:{

+ 3 - 0
src/App.vue

@@ -338,4 +338,7 @@ textarea {
 .el-autocomplete-suggestion-data-entry {
     width: auto !important;
 }
+.el-tabs__nav-wrap::after {
+  background: transparent !important;
+}
 </style>

+ 3 - 2
src/api/api.js

@@ -22,7 +22,7 @@ import { departInterence, videoInterence ,InteractionInterence,enAuthInterence}
 import { dataMainInterface } from './modules/statisticApi';
 
 //crm
-import { customInterence ,equityContacts} from './modules/crmApi';
+import { customInterence ,equityContacts ,xClassCustomApi} from './modules/crmApi';
 
 //合同
 import { contractInterface } from './modules/contractApi';
@@ -114,7 +114,8 @@ export {
   businessTripInterence,
   reportVarietyENInterence,
   businessCustomInterence,
-  assistanceDocInterence
+  assistanceDocInterence,
+  xClassCustomApi
 };
 
 //老接口 研报 ppt等

+ 64 - 2
src/api/modules/crmApi.js

@@ -129,6 +129,10 @@ const customInterence = {
     // return http.get('/custom/seller/check/list',params)
     return http.get("/custom/seller/check/listV2", params);
   },
+  /* 获取正式客户共享-原销售列表 */
+  getShareSale:(params)=>{
+    return http.get("/custom/seller/check/Sharelist2",params)
+  },
   /* 客户详情
 		CompanyId 
 	*/
@@ -249,6 +253,13 @@ const customInterence = {
   concactEdit: (params) => {
     return http.post("/custom/user/edit", params);
   },
+  /* 关注/取消关注 联系人
+  UserId CompanyId
+  Type 0取关 1关注
+  */
+  concactFollow: (params) => {
+    return http.post("/custom/follow", params);
+  },
   /* 获取权限基本信息 */
   authList: (params) => {
     return http.get("/custom/permission/list", params);
@@ -474,6 +485,12 @@ const customInterence = {
   salesShareList: (params) => {
     return http.get("/custom/seller/share/list", params);
   },
+  /**
+   * 获取分配销售列表,根据用户角色返回 共享客户组 or 权益销售组
+   */
+  getShareSaleList:(params)=>{
+    return http.get("/custom/seller/share/list", params);
+  },
   /**
    * 获取 共享客户列表
    * SortParam 排序字段
@@ -658,6 +675,10 @@ const customInterence = {
   roadShowList: (params) => {
     return http.get("/custom/roadShowList", params);
   },
+  //中文客户累计点击量
+  getZNCustomClickList:(params)=>{
+    return http.get('/custom/user/listByReport',params)
+  },
   /**
    * 销售ToDo
    */
@@ -1042,8 +1063,17 @@ const customInterence = {
    */
   saveToDoEditData:(params)=>{
     return http.post("/english_report/company_todo/add_public",params)
+  },
+  //新增开通或者关闭用户研选权限新建接口
+    /**
+   * 
+   * @param {* UserId 用户ID} params 
+   * @param {* Type 类型 } params 
+   * @returns 
+   */
+  yananxuanPermissionOpen:(params)=>{
+    return http.post("/custom/update/user/yananxuan/permission",params)
   }
-  
 };
 
 /*
@@ -1245,4 +1275,36 @@ const customAllInterence = {
     },
 }
 
-export { customInterence,customAllInterence, equityContacts,etaTrialInterence};
+/* X类客户评分 */
+const xClassCustomApi = {
+  //模板 列表
+  enterScoreDetail:(params)=>{
+      return http.get("/cygx/enterScore/detail",params)
+  },
+   //添加/ 更新录分
+   enterScoreUpdate:(params)=>{
+    return http.post("/cygx/enterScore/update",params)
+  },  
+  // X试用类客户检索
+  enterScoreSearchlist:(params)=>{
+      return http.get("/cygx/enterScore/company/searchlist",params)
+  },
+  // 录分列表接口
+  enterScoreList:(params)=>{
+    return http.get("/cygx/enterScore/list",params)
+  },
+  // 录分列表接口
+  enterScoreDelete:(params)=>{
+    return http.post("/cygx/enterScore/delete",params)
+  },  
+  // 评分总览接口
+  enterScoreScoreOverview:(params)=>{
+    return http.get("/cygx/enterScore/scoreOverview",params)
+  }, 
+  // 排名总览接口
+  enterScoreRankingOverview:(params)=>{
+    return http.get("/cygx/enterScore/rankingOverview",params)
+  }, 
+}
+
+export { customInterence,customAllInterence, equityContacts,etaTrialInterence,xClassCustomApi};

+ 136 - 0
src/api/modules/overseasCustom.js

@@ -0,0 +1,136 @@
+/**
+ * 海外客户管理
+ */
+import http from "@/api/http.js"
+
+export const overseasCustomInterence = {
+    /**
+     * 获取已保存的销售
+     * @param {*} params 
+     */
+    getSavedSalesList:(params)=>{
+        return http.get('/overseas_custom/sale/list',params)
+    },
+    /**
+     * 保存已选择的销售
+     * @param {Object} params 
+     * @param {Number[]} params.AddSellerIdArr 新增销售id
+     * @param {Number[]} params.DelSellerIdArr 删除销售id
+     * @returns 
+     */
+    saveSelectedSales:(params)=>{
+        return http.post('/overseas_custom/sale/save',params)
+    },
+    /**
+     * 获取海外客户统计数据
+     * @param {*} params 
+     * @returns 
+     */
+    getCustomStatus:(params)=>{
+        return http.get('/overseas_custom/custom/statistics',params)
+    },
+    /**
+     * 获取海外客户列表数据
+     * @param {Object} params 
+     * @param {String} params.CompanyStatus 客户状态:全部,正式,试用,关闭
+     * @param {String} params.SellerId 销售id ,拼接
+     * @param {Number} params.CustomType 客户类型:1 海外客户 2 隐藏的客户
+     * @param {String} params.SortField 排序字段:ViewTotal,RoadShowTotal,CreateTime
+     * @param {Number} params.SortDesc 排序类型:1 降序(默认) 2 升序
+     * @param {String} params.Keywords 
+     * @param {Number} params.CurrentIndex
+     * @param {Number} params.PageSize
+     * @returns 
+     */
+    getCustomList:(params)=>{
+        return http.get('/overseas_custom/custom/list',params)
+    },
+    /**
+     * 设置客户试用子标签
+     * @param {Object} params 
+     * @param {Number} params.CompanyId 客户id
+     * @param {Number} params.OverseasLabel 海外客户试用子标签:1未分类、2  推进、3 跟踪、4 预备
+     * @returns 
+     */
+    setCustomTryStatus:(params)=>{
+        return http.post('/overseas_custom/custom/overseas_label_set',params)
+    },
+    /**
+     * 设置客户隐藏/取消隐藏
+     * @param {Object} params 
+     * @param {Number} params.CompanyId
+     * @returns 
+     */
+    setCustomHide:(params)=>{
+        return http.post('/overseas_custom/custom/hide',params)
+    },
+    /**
+     * 设置客户状态为正式/重置
+     * @param {Object} params
+     * @param {Number} params.CompanyId
+     * @returns 
+     */
+    setCustomStatus:(params)=>{
+        return http.post('/overseas_custom/custom/status_set',params)
+    },
+    /**
+     * 获取客户统计信息
+     * @param {Object} params
+     * @param {String} params.Keywords
+     * @param {String} params.SellerId
+     * @param {Number} params.CustomType
+     * @returns 
+     */
+    getStatisticData:(params)=>{
+        return http.get('/overseas_custom/custom/statistics',params)
+    },
+    /**
+     * 获取客户试用统计信息
+     * @param {Object} params
+     * @param {String} params.Keywords
+     * @param {String} params.SellerId
+     * @param {Number} params.CustomType
+     * @returns 
+     */
+    overseasCustomInterence:(params)=>{
+        return http.get('/overseas_custom/custom/label/statistics',params)
+    },
+    
+    /**
+     * 海外客户路演 销售 研究列表
+     * @param {*} params AdminType: researcher seller
+     * @returns 
+     */
+    getOverseasRoadShowUsers: params => {
+        return http.get('/roadshow/overseas_custom/sys_user/list',params)
+    },
+
+    /**
+     * 海外客户路演列表 - 客户维度
+     * @param {*} params 
+     * ResearcherId SellerId  StartDate EndDate  CompanyStatus
+     * @returns 
+     */
+    getOverseasRoadShowList: params => {
+        return http.get('/roadshow/overseas_custom/calendar/list',params)
+    },
+    /**
+     * 海外客户路演列表 - 销售维度
+     * @param {*} params 
+     * DataType StartDate EndDate
+     * @returns 
+    */
+    getOverseasSellerRoadShowList: params => {
+        return http.get('/roadshow/overseas_custom/seller/list',params)
+    },
+    /**
+     * 海外客户路演列表 - 研究员维度
+     * @param {*} params 
+     * DataType StartDate EndDate
+     * @returns 
+    */
+    getOverseasResearcherRoadShowList: params => {
+        return http.get('/roadshow/overseas_custom/researcher/list',params)
+    }
+
+}

+ 12 - 1
src/api/modules/rai/YanXuanApi.js

@@ -45,7 +45,18 @@ const YanXuanApi = {
   getYanxuanShowButton: (params) => {
     return http.get("/cygx/yanxuan_special/show_button", params);
   },
-  
+  // 分享记录列表接口
+  getShareRecordList: (params) => {
+    return http.get("/cygx/mfyx/admin/share/list", params);
+  },
+  // 修改推荐人 备注信息
+  yanxuan_specialAuthorUpdate: (params) => {
+    return http.post("/cygx/yanxuan_special/author/update", params);
+  },
+  // 作者模糊查询
+  yanxuan_specialAuthorSearch: (params) => {
+    return http.get("/cygx/yanxuan_special/author/search", params);
+  },
 };
 
 export default YanXuanApi;

+ 7 - 0
src/api/modules/rai/raiApi.js

@@ -318,6 +318,13 @@ const raiInterface = {
   getNoTacticsfirst: (params) => {
     return http.get("/cygx/chartPermission/noTacticsfirst", params);
   },
+    /**
+   * 专项调研活动行业分类接口
+   * @returns
+   */
+    getActivitySpecial: (params) => {
+      return http.get("/cygx/chartPermission/activitySpecial", params);
+    },
   /**
    * 通过多个产业获取标的列表接口
    * @param {IndustrialManagementIdStr } params 分类ID,多个使用 ,隔开列如 1,3,5

+ 4 - 0
src/api/modules/rai/reportApi.js

@@ -33,6 +33,10 @@ const raiReport = {
   reportSelectionTarryList: (params) => {
     return http.get("/cygx/reportSelection/tarryList", params);
   },
+  // 文章置顶、取消置顶
+  summaryManageTopChange: (params) => {
+    return http.post("/cygx/summaryManage/top_change", params);
+  },
   
 };
 

+ 8 - 1
src/api/modules/roadshowApi.js

@@ -222,7 +222,14 @@ const roadshowInterence={
 	statisticDetailList: params => {
 		return http.get('/roadshow/report/calendar/list',params)
 	},
-
+	/**
+	 * 统计详情列表-海外路演
+	 * @param {} params DataType StartDate EndDate AdminIds AdminType
+	 * @returns 
+	 */
+	overseaStatisticDetailList: params => {
+		return http.get('/roadshow/overseas/calendar/list',params)
+	},
 	/**
 	 * 选择的研究员接口
 	 * @param {AdminIds} params DataType StartDate EndDate AdminId AdminType

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

@@ -318,6 +318,13 @@ const departInterence = {
 	 */
 	getPhoneAreaCode:params=>{
 		return http.get('/user_login/area_code/list',params)
+	},
+	/**
+	 * 小程序banner统计
+	 * @returns 
+	 */
+	getBannerStatistic:params=>{
+		return http.get('/banner/statistic',params)
 	}
 }
 

+ 65 - 0
src/api/modules/statisticApi.js

@@ -103,6 +103,14 @@ const dataMainInterface = {
 	addAscrib:params => {
 		return http.post('/custom/company_ascribe/add',params);
 	},
+	/**
+	 * 合同通过归因添加确认不续约接口
+	 * @param {KeyWord} params 
+	 * @returns  
+	*/
+	addAscribContract:params => {
+		return http.post('/custom/company_contract_no_renewed_ascribe/add',params);
+	},
 	/**
 	 * 修改归因标签
 	* @param {CompanyId} params 公司ID
@@ -123,6 +131,14 @@ const dataMainInterface = {
 	infoNoRenewedAscribe:params => {
 		return http.get('/custom/company_no_renewed_ascribe/detail',params);
 	},
+	/**
+	 * 合同确认归因不续约详情接口
+	* @param {CompanyContractId} params 合同ID
+	 * @returns  
+	*/
+	contractInfoNoRenewedAscribe:params => {
+		return http.get('/custom/company_contract_no_renewed_ascribe/detail',params);
+	},
 	/**
 	 * 获取收入统计列表接口
 	 * @param {PageSize} params 
@@ -233,6 +249,15 @@ const dataMainInterface = {
 		return http.get('/statistic_report/report/renew_company',params)
 	},
 
+	// 续约异常客户统计
+	unusualRenewalCustomStatistic: params => {
+		return http.get('/statistic_report/report/unusual_renew_company',params)
+	},
+	//续约异常客户统计图表数据
+	unusualRenewalCustomStatisticChartData:params=>{
+		return http.get('/statistic_report/report/unusual_renew_company/chart',params)
+	},
+
 	/**
 	 * 新增客户列表
 	 * @param {} params PageSize CurrentIndex SortParam SortType 	CompanyIds
@@ -341,7 +366,47 @@ const dataMainInterface = {
    chartDetailList:params=>{
     return http.post('/statistic_report/report/seller_chart_collect_log/detail',params)
   },
+ /**
+  * 权益客户统计列表接口
+  * @param {PageSize} params 
+  * @param {CurrentIndex} params 
+  * @param {EndDate} params 结束日期
+  * @param {CompanyType} params 
+  * @param {AdminId } params 销售id,多个用英文逗号隔开,空字符串为全部
+  * @param {RegionType } params 
+  * @param {StartDate} params 
+  * @param {DataType} params 
+  * @param {IsConfirm} params  是否确认续约: -1-默认全部; 0-待确认; 1-已确认
+  * @param {CompanyAscribeId} params  归因Id
+  * @returns  
+  */
+ incrementalCompanyContractPermissionList:params => {
+ 	return http.get('/statistic_report/merge_company/company_contract_permission/list',params);
+ },
+  /**
+  * 权益客户续约率统计
+  * @param {PageSize} params 
+  * @param {CurrentIndex} params 
+  * @param {EndDate} params 结束日期
+  * @param {StartDate} params 开始日期
+  * @param {ContractDataType} params 到期合同
+  * @param {AdminId} params 销售id
 
+  * @returns  
+  */
+  incrementalCompanyContractPercentageList:params => {
+	return http.get('/statistic_report/merge_company/company_contract_percentage/list',params);
+},
+incrementalCompanyContractPercentageListV2:params => {
+	return http.get('/statistic_report/merge_company/company_contract_percentage/listV2',params);
+},
+  /**
+  * 权益客户续约率统计所能查询的年份
+  * @returns  
+  */
+  incrementalCompanyContractGetYearList:params => {
+	return http.get('/statistic_report/merge_company/get_year_list',params);
+},
 }
 
 export {

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


BIN
src/assets/img/icons/like-heart.png


+ 42 - 4
src/routes/modules/customRoutes.js

@@ -52,7 +52,13 @@ export default [
       {
         path: "customListEn",
         component: () => import("@/views/custom_manage/customList/customListEn.vue"),
-        name: "英文客户列表",
+        name: "英文报告权限",
+        hidden: false,
+      },
+      {
+        path: "overseasCustomList",
+        component: () => import("@/views/custom_manage/overseasList/overseasCustomList.vue"),
+        name: "海外客户列表",
         hidden: false,
       },
       {
@@ -105,7 +111,7 @@ export default [
         hidden: true,
         meta: {
           pathFrom: "customListEn",
-          pathName: "英文客户列表",
+          pathName: "英文报告权限",
         },
       },
       {
@@ -115,7 +121,7 @@ export default [
         hidden: true,
         meta: {
           pathFrom: "customListEn",
-          pathName: "英文客户列表",
+          pathName: "英文报告权限",
         },
       },
       {
@@ -136,7 +142,7 @@ export default [
         hidden: true,
         meta: {
           pathFrom: "customListEn",
-          pathName: "英文客户列表",
+          pathName: "英文报告权限",
         },
       },
       {
@@ -425,6 +431,38 @@ export default [
           pathFrom: "businessETAList",
           pathName: "商家管理",
         }
+      },
+      {
+        path:'overseasCustomRoadshow',
+        name:"海外客户路演",
+        component: () => import('@/views/custom_manage/overseasList/overseasCustomRoadshow.vue'),
+        hidden: false
+      },
+      {
+        path:'XClassCustomPoints',
+        name:"X类客户派点",
+        component: () => import('@/views/custom_manage/points/XClassCustom.vue'),
+        hidden: false
+      },
+      {
+        path:'AddNewEntries',
+        name:"新增录分",
+        component: () => import('@/views/custom_manage/points/AddNewEntries.vue'),
+        hidden: false,
+        meta:{
+          pathFrom: "XClassCustomPoints",
+          pathName: "X类客户派点",
+        }
+      },
+      {
+        path:'EditNewEntries',
+        name:"查看明细",
+        component: () => import('@/views/custom_manage/points/AddNewEntries.vue'),
+        hidden: false,
+        meta:{
+          pathFrom: "XClassCustomPoints",
+          pathName: "X类客户派点",
+        }
       }
     ],
   },

+ 22 - 0
src/routes/modules/ficcXcxRoutes.js

@@ -90,6 +90,28 @@ export default [
 				name:'群发日志',
 				hidden:true
 			},
+			{
+				path:'bannerStatistics',
+				component:()=> import('@/views/interaction_manage/bannerStatistics.vue'),
+				name:'banner 统计',
+				hidden:true
+			},
+			{
+				path:'reportVariety',
+				component:()=> import('@/views/ficc_manage/reportVariety.vue'),
+				name:'报告分类配置',
+				hidden:true
+			},
+			{
+				path: "chapterVariety",
+				component: () => import("@/views/ficc_manage/chapterVariety.vue"),
+				name: "章节设置",
+				hidden: true,
+				meta: {
+				  pathFrom: "reportVariety",
+				  pathName: "报告分类配置",
+				},
+			  },
 
         ]
     }

+ 19 - 0
src/routes/modules/researchRoutes.js

@@ -0,0 +1,19 @@
+const home = (r) => require.ensure([], () => r(require("@/views/Home.vue")), "Home"); //主页
+
+export default [
+  {
+    path: "/",
+    component: home,
+    name: "买方研选管理",
+    hidden: false,
+    icon_path: require('@/assets/img/home/mfyx_icon.png'),
+    children: [
+      {
+        path: "shareRecordResearch",
+        component: () => import("@/views/research_manage/shareRecord.vue"),
+        name: "分享记录",
+        hidden: false,
+      },
+    ],
+  },
+];

+ 16 - 0
src/routes/modules/sellerRoutes.js

@@ -127,6 +127,22 @@ export default [
 				component: () => import('@/views/custom_manage/saleAuthManage.vue'),
 				hidden: false,
 			},
+			{
+				path:"abnormalRenewal",
+				name: '续约异常统计',
+				component: () => import('@/views/dataReport_manage/statistic/abnormalRenewal.vue'),
+				hidden: false,
+			},
+			{
+				path: 'abnormalRenewalCustomlist',
+				component: () => import('@/views/dataReport_manage/statistic/newCustomlist.vue'),
+				name: '续约异常客户列表',
+				meta: {
+					pathFrom: 'abnormalRenewal',
+					pathName: '续约异常统计' 
+				},
+				hidden: true
+			},
 		]
 	},
 ]

+ 6 - 0
src/routes/modules/statisticRoutes.js

@@ -51,6 +51,12 @@ export default [
 				name: '权益客户统计',
 				hidden: false
 			},
+			{
+				path: 'equityPackageStatistics',
+				component: () => import('@/views/dataReport_manage/equityPackageStatistics.vue'),
+				name: '权益套餐统计',
+				hidden: false
+			},
 			{
 				path: 'readClassify',
 				component: () => import('@/views/dataReport_manage/readClassify.vue'),

File diff suppressed because it is too large
+ 2 - 2
src/views/Home.vue


+ 163 - 110
src/views/Login.vue

@@ -73,11 +73,13 @@
 				</el-form-item>
 			</el-form> -->
 			<div class="login-box" id="login-container" v-if="activeModel!=='forgetPassModel'">
+				<div class="fixed-login-wrapper">
+
 				<h1 style="font-size: 38px;text-align: center;color: #333;margin-bottom: 30px;">
 					运营管理系统
 				</h1>
-				<el-tabs v-model="activeModel" @tab-click="handleClick">
-					<el-tab-pane label="账号登录" name="ordinaryModel">
+				<el-tabs v-model="activeModel">
+					<!-- <el-tab-pane label="账号登录" name="ordinaryModel">
 						<OrdinaryModel ref="ordinaryModel"
 							:loginCheck="loginCheck"
 							:accountCheck="accountCheck"
@@ -89,10 +91,22 @@
 						<MobileModel ref="mobileModel"
 							:areaCode="areaCode"
 						/>
-					</el-tab-pane>
-					<!-- <el-tab-pane label="邮箱登录" name="emailModel"> -->
-						<EmailModel ref="emailModel" v-show="activeModel=='emailModel'"/>
-					<!-- </el-tab-pane> -->
+					</el-tab-pane> -->
+
+					<OrdinaryModel ref="ordinaryModel"
+							:loginCheck="loginCheck"
+							:accountCheck="accountCheck"
+							@clearnHint="clearnHint"
+							@changeModel="changeModel('forgetPassModel')"
+							v-show="activeModel=='ordinaryModel'"
+					/>
+
+					<MobileModel ref="mobileModel"
+							:areaCode="areaCode"
+							v-show="activeModel=='mobileModel'"
+					/>
+
+					<EmailModel ref="emailModel" v-show="activeModel=='emailModel'"/>
 				</el-tabs>
 				<el-button
 					type="primary"
@@ -108,19 +122,39 @@
 							<div class="type-hint-line"></div>
 						</div>
 						<div class="another-type">
-							<div class="login-type-item"
+							<div class="login-type-box">
+								<div class="login-type-item" @click="activeModel='ordinaryModel';handleClick({name:'ordinaryModelMobile'})"
+								v-show="activeModel!=='ordinaryModel'">
+									<img src="~@/assets/img/icons/account-login-type.png">
+									<span>账号登录</span>
+								</div>
+								<div class="login-type-item" @click="activeModel='mobileModel';handleClick({name:'mobileModelMobile'})"
+								v-show="activeModel!=='mobileModel'">
+									<img src="~@/assets/img/icons/phone-login-type.png">
+									<span>手机号登录</span>
+								</div>
+								<div class="login-type-item" v-show="activeModel!=='emailModel'" 
+								@click="activeModel='emailModel';handleClick({name:'emailModelMobile'})">
+									<img src="~@/assets/img/icons/email-login-type.png">
+									<span>邮箱登录</span>
+								</div>
+							</div>
+							<!-- <div class="login-type-item"
 							@click="activeModel='emailModel';handleClick({name:'emailModel'})">
 								<img src="~@/assets/img/icons/email-login-type.png">
 								<span>邮箱登录</span>
-							</div>
+							</div> -->
 						</div>
 					</div>
+				</div>
 			</div>
 			<div class="login-box" v-else>
-				<ForgetPassModel 
-					ref="forgetPassModel"
-					:autoAccount="$refs.ordinaryModel?$refs.ordinaryModel.form.account:''"
-					@changeModel="changeModel('ordinaryModel')"/>
+				<div class="fixed-login-wrapper">
+					<ForgetPassModel 
+						ref="forgetPassModel"
+						:autoAccount="$refs.ordinaryModel?$refs.ordinaryModel.form.account:''"
+						@changeModel="changeModel('ordinaryModel')"/>
+				</div>	
 			</div>
 		</div>
 
@@ -507,7 +541,8 @@ export default {
 			departInterence.userLogin({
 				LoginType:2,
 				Mobile:mobile,
-				VerifyCode:checkCode
+				VerifyCode:checkCode,
+				TelAreaCode:this.$refs[model].areaCodeSelect,
 			}).then(res=>{
 				if(res.Ret!==200){
 					//刷新图形验证码
@@ -526,7 +561,7 @@ export default {
 			departInterence.userLogin({
 				LoginType:3,
 				Email:email,
-				VerifyCode:checkCode
+				VerifyCode:checkCode,
 			}).then(res=>{
 				if(res.Ret!==200){
 					//刷新图形验证码
@@ -660,111 +695,129 @@ export default {
 			width: 8%;
 		}
 
-		#login-container,.login-box{
-			width: 31%;
-			max-width: 570px;
-			box-sizing: border-box;
-			border-radius: 10px;
-			position: absolute;
-			top: 18%;
-			right: 14%;
-			z-index: 100;
-			font-size: 30px;
-			input::-webkit-input-placeholder {
-				color: #595959 !important;
-			}
-			.remember {
-				margin: 0px 0 20px;
-			}
-			.submit_btn {
-				width: 100%;
-				height: 50px;
-				background: #007eff;
-				font-size: 16px;
-				border-radius: 5px;
-				// margin-top: 30px;
-			}
-			.el-input input {
-				width: 100%;
-				height: 40px;
-				color: #333333;
-				font-size: 16px;
-			}
-			.el-input-group__append,
-			.el-input-group__prepend {
-				background-color: rgba(255, 255, 255, 0.8);
-				color: rgb(51, 51, 51);
-				border: none;
-			}
-			.el-input.el-input-group.el-input-group--prepend input {
-				background-color: rgba(255, 255, 255, 0.8);
-				color: rgb(51, 51, 51);
-				border: none;
-			}
-			.el-checkbox__label {
-				color: rgb(51, 51, 51);
-				font-size: 14px;
-			}
-			.el-checkbox__input.is-checked + .el-checkbox__label {
-				color: rgb(51, 51, 51);
-				font-size: 14px;
-			}
-			.el-form-item__content .el-input-group,
-			.el-form-item__label,
-			.el-tag .el-icon-close {
-				padding-bottom: 5px;
-				vertical-align: middle;
-				border-bottom: 1px solid #eaeaea;
-			}
-			.el-button--primary {
-				background: #007eff !important;
-				border: none;
-			}
-			.el-form-item__content {
-				padding-bottom: 5px;
-			}
-			.el-form-item {
-				margin-bottom: 30px;
-			}
+	}
+	#login-container,.login-box{
+		width: 31%;
+		
+		box-sizing: border-box;
+		border-radius: 10px;
+		position: absolute;
+		top: 18%;
+		right: 14%;
+		z-index: 100;
+		font-size: 30px;
+		.fixed-login-wrapper {
+			width: 460px;
+			margin: 0 auto;
+		}
+		input::-webkit-input-placeholder {
+			color: #595959 !important;
+		}
+		.remember {
+			margin: 0px 0 20px;
+		}
+		.submit_btn {
+			width: 100%;
+			height: 50px;
+			background: #007eff;
+			font-size: 16px;
+			border-radius: 5px;
+			// margin-top: 30px;
+		}
+		.el-input input {
+			width: 100%;
+			height: 40px;
+			color: #333333;
+			font-size: 16px;
+		}
+		.el-input-group__append,
+		.el-input-group__prepend {
+			background-color: rgba(255, 255, 255, 0.8);
+			color: rgb(51, 51, 51);
+			border: none;
+		}
+		.el-input.el-input-group.el-input-group--prepend input {
+			background-color: rgba(255, 255, 255, 0.8);
+			color: rgb(51, 51, 51);
+			border: none;
+		}
+		.el-checkbox__label {
+			color: rgb(51, 51, 51);
+			font-size: 14px;
+		}
+		.el-checkbox__input.is-checked + .el-checkbox__label {
+			color: rgb(51, 51, 51);
+			font-size: 14px;
+		}
+		.el-form-item__content .el-input-group,
+		.el-form-item__label,
+		.el-tag .el-icon-close {
+			padding-bottom: 5px;
+			vertical-align: middle;
+			border-bottom: 1px solid #eaeaea;
+		}
+		.el-button--primary {
+			background: #007eff !important;
+			border: none;
+		}
+		.el-form-item__content {
+			padding-bottom: 5px;
+		}
+		.el-form-item {
+			margin-bottom: 30px;
+		}
 
-			.another-login-type{
-				margin-top: 45px;
-				.another-type-hint{
+		.another-login-type{
+			margin-top: 45px;
+			.another-type-hint{
+				display: flex;
+				align-items: center;
+				.type-hint-line{
+					flex: 1;
+					height: 1px;
+					background-color: #C0C4CC;
+				}
+				.type-hint-text{
+					font-size: 18px;
+					color: #999999;
+					padding: 0 20px;
+				}
+			}
+			.another-type{
+				.login-type-box {
 					display: flex;
+					justify-content: center;
+					gap: 10%;
+				}
+				.login-type-item{
+					display: flex;
+					flex-direction: column;
+					justify-content: center;
 					align-items: center;
-					.type-hint-line{
-						flex: 1;
-						height: 1px;
-						background-color: #C0C4CC;
-					}
-					.type-hint-text{
-						font-size: 18px;
-						color: #999999;
-						padding: 0 20px;
+					margin-top: 20px;
+					cursor: pointer;
+					img{
+						height: 40px;
+						width: 40px;
+						margin-bottom: 4px;
 					}
-				}
-				.another-type{
-					.login-type-item{
-						display: flex;
-						flex-direction: column;
-						justify-content: center;
-						align-items: center;
-						margin-top: 20px;
-						cursor: pointer;
-						img{
-							height: 40px;
-							width: 40px;
-							margin-bottom: 4px;
-						}
-						span{
-							font-size: 16px;
-							color: #666666;
-						}
+					span{
+						font-size: 16px;
+						color: #666666;
 					}
 				}
 			}
 		}
 	}
+	@media screen and (max-width:1201px) {
+		.login-bg { display: none; }
+		#login-container ,.login-box{
+				width: 70%;
+				top:15%;
+				left: 50%;
+				transform: translateX(-50%);
+			}
+	}
 	@media screen and (max-width:650px) {
 		#login_wrapper_mobile{
 			// display: block;

+ 4 - 6
src/views/business_ETA_manage/businessAuth.vue

@@ -9,8 +9,6 @@
         </div>
         <div class="model-wrap">
             <el-button :type="model==='auth'?'primary':''" @click="model='auth'">菜单权限</el-button>
-            <span class="block"></span>
-            <el-button :type="model==='interence'?'primary':''" @click="model='interence'">接口权限</el-button>
         </div>
         <div class="auth-wrap" v-show="model==='auth'">
             <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" style="margin-bottom: 20px;">全选</el-checkbox>
@@ -26,7 +24,7 @@
                 @check-change="()=>{handleCheckChange()}">
             </el-tree>
         </div>
-        <div class="interence-wrap" v-show="model==='interence'">
+        <!-- <div class="interence-wrap" v-show="model==='interence'">
             <div class="interence-item">
                 <span>研报审批</span>
                 <el-radio-group v-model="isApprove">
@@ -38,7 +36,7 @@
                     <el-checkbox :label="1">研报列表</el-checkbox>
                 </el-checkbox-group>
             </div>
-        </div>
+        </div> -->
     </div>
 </template>
 
@@ -178,7 +176,7 @@ export default {
                 if(res.Ret!==200) return 
                 this.$message.success('权限设置成功')
 
-                if(typeof(this.isApprove)==='string'){
+                /* if(typeof(this.isApprove)==='string'){
                     this.$message.warning('请配置接口权限')
                     this.model='interence'
                     return
@@ -200,7 +198,7 @@ export default {
                     })
                     if(interenceRes.Ret!==200) return 
                     this.$message.success('接口权限设置成功')
-                }
+                } */
             }
             this.$router.push('/businessETAList')
         },

+ 10 - 4
src/views/contract_manage/components/ServiceDialog.vue

@@ -113,7 +113,7 @@
               >{{ item.ClassifyName }}:</el-checkbox
             >
             <el-checkbox-group :disabled="selectRowIndex === null" v-model="item.CheckList" @change="handleCheckChange(item)">
-              <el-checkbox :disabled="contractType!=='补充协议'&&tag.PermissionName==='宏观经济'" :label="tag.ChartPermissionId" v-for="tag in item.Items" :key="tag.ChartPermissionId">{{ tag.PermissionName }}</el-checkbox>
+              <el-checkbox :disabled="contractType!=='补充协议'&&tag.IsPublic==1" :label="tag.ChartPermissionId" v-for="tag in item.Items" :key="tag.ChartPermissionId">{{ tag.PermissionName }}</el-checkbox>
             </el-checkbox-group>
           </div>
         </div>
@@ -425,6 +425,7 @@ export default {
         if (res.Ret === 200) {
           let arr = res.Data.List;
           arr.forEach((item) => {
+            item.Items=item.Items||[]
             item.CheckList = [];
             item.CheckAll = false;
             item.indeterminate = false;
@@ -467,9 +468,14 @@ export default {
       e.CheckList = e.CheckAll ? arr : [];
       e.indeterminate = false;
       // 需求更改,合同类型为补充协议时不默认勾选宏观经济
-      if(e.ClassifyName==='宏观经济'&&this.contractType!=='补充协议'){
-        e.CheckList.push(1)
-      }
+      if(this.contractType!=='补充协议'){
+        e.Items.forEach(_e=>{
+          if(_e.IsPublic==1){
+            e.CheckList.push(_e.ChartPermissionId)
+          }
+        })
+        
+      } 
     },
 
     //选择单个

+ 53 - 30
src/views/contract_manage/components/allocationNumber.vue

@@ -7,37 +7,31 @@
           <el-button style="margin-top: 20px" type="primary" size="mini" @click="averageaAllocation">平均分配</el-button>
         </div>
 
-        <p>
-          1)单行业套餐只能在对应行业内部分配研究员贡献百分比<br />
-          2)多行业套餐先在行业间分配百分比(最低不低于平均值的一半),再分配到个人<br />
-          3)允许总额20%以内的负分<br />
-          4)转正后一个季度内可以提交和修改
-          <br />
-        </p>
+        <div>
+          <p v-for="(item, index) in textualList" :key="item.text">{{ index + 1 }}{{ item.text }}</p>
+        </div>
       </div>
       <div class="content-box">
         <div v-for="item in listArr" :key="item.ChartPermissionName">
-          <div class="industry-ul">
-            <span :class="['industry-name', item.ChartPermissionName == '买方研选' && 'name-yanxuan']">{{ item.ChartPermissionName }}</span>
-            <template v-if="item.ChartPermissionName !== '买方研选'">
-              <el-input :min="-100" :max="100" type="number" v-model="item.Proportion" size="small" @input="restrictInput(item)" style="width: 76px; margin: 0 5px 0 8px">
+          <div :class="['industry-ul', item.ChartPermissionName.includes('研选') && 'ul-yanxuan']">
+            <span :class="['industry-name', item.ChartPermissionName.includes('研选') && 'name-yanxuan']">{{ item.ChartPermissionName }}</span>
+            <template>
+              <el-input :min="-100" :max="100" type="number" v-model="item.Proportion" size="small" @input="restrictInput(item)" style="width: 80px; margin: 0 5px 0 8px">
                 <div class="per_cent_" slot="suffix">%</div>
               </el-input>
               <p style="width: 38px">{{ roundedResult(item) }}</p>
             </template>
-            <p style="width: 38px; height: 32px; line-height: 32px; text-align: center" v-else>{{ item.Money }}</p>
           </div>
-          <div v-for="study in item.List" :key="study.RealName" class="industry-ul">
-            <span :class="['study-name', item.ChartPermissionName == '买方研选' && 'name-yanxuan']">{{ study.RealName }}</span>
-            <template v-if="study.RealName !== '买方研选'">
+          <div v-for="study in item.List" :key="study.RealName" :class="['industry-ul', item.ChartPermissionName.includes('研选') && 'ul-yanxuan']">
+            <span :class="['study-name', item.ChartPermissionName.includes('研选') && 'name-yanxuan']">{{ study.RealName }}</span>
+            <template>
               <el-input :min="-100" :max="100" type="number" v-model="study.Proportion" size="small" style="width: 76px; margin: 0 5px 0 8px">
                 <div class="per_cent_" slot="suffix">%</div>
               </el-input>
               <p style="width: 38px">{{ roundedResult(study) }}</p>
             </template>
-            <p style="width: 38px; height: 32px; line-height: 32px; text-align: center" v-else>{{ study.Money }}</p>
           </div>
-          <div class="all-item" v-if="item.ChartPermissionName != '买方研选'">
+          <div class="all-item">
             <span> {{ allPerCentHandler(item) == 0 ? "" : `总占比:` }}</span>
             <span> {{ allPerCentHandler(item) == 0 ? "" : `${allPerCentHandler(item)}` }}</span>
           </div>
@@ -72,9 +66,32 @@ export default {
       listArr: [],
       allNum: 0,
       TotalPointsContent: "",
+      isXClass: false,
     };
   },
-  computed: {},
+  computed: {
+    textualList() {
+      let items = [
+        {
+          text: ")单行业套餐只能在对应行业内部分配研究员贡献百分比",
+        },
+        {
+          text: ")多行业套餐先在行业间分配百分比(最低不低于平均值的一半),再分配到个人",
+        },
+        {
+          text: ")允许总额20%以内的负分",
+        },
+        {
+          text: ")转正后一个季度内可以提交和修改",
+        },
+      ];
+      if (this.isXClass) {
+        return items.filter((item, index) => index == 0 || index == 3);
+      } else {
+        return items;
+      }
+    },
+  },
   watch: {
     allocationVisible: {
       handler(newVal) {
@@ -138,22 +155,19 @@ export default {
       if (res.Ret === 200) {
         this.allNum = res.Data.Money;
         this.listArr = res.Data.List;
+        this.isXClass = res.Data.IsXClass;
         this.TotalPointsContent = res.Data.TotalPointsContent;
       }
     },
     // 平均分配
     averageaAllocation() {
-      let isName = this.listArr.some((item) => item.ChartPermissionName == "买方研选");
-      let num = 100 / (isName ? this.listArr.length - 1 : this.listArr.length);
+      let num = (100 / this.listArr.length).toFixed(2);
+      console.log(num);
       this.listArr.forEach((item) => {
-        if (item.ChartPermissionName != "买方研选") {
-          item.Proportion = num;
-        }
-        let childrenNum = num / item.List.length;
+        item.Proportion = num;
+        let childrenNum = (num / item.List.length).toFixed(2);
         item.List.forEach((key) => {
-          if (key.RealName != "买方研选") {
-            key.Proportion = childrenNum;
-          }
+          key.Proportion = childrenNum;
         });
       });
     },
@@ -168,14 +182,17 @@ export default {
     justify-content: space-between;
   }
   .content-box {
+    width: 100%;
+    overflow: hidden;
+    overflow-x: auto;
     display: flex;
     .industry-ul {
       display: flex;
       align-items: center;
       margin: 30px 0;
-      width: 180px;
+      width: 188px;
       color: #333;
-      margin-right: 35px;
+      margin-right: 25px;
       .per_cent_ {
         line-height: 32px;
       }
@@ -211,7 +228,13 @@ export default {
     }
   }
   .name-yanxuan {
-    width: 65px !important;
+    width: 70px !important;
+  }
+  .points-name {
+    width: 80px !important;
+  }
+  .ul-yanxuan {
+    width: 220px !important;
   }
   /* 取消[type='number']的input的上下箭头 */
   input::-webkit-inner-spin-button {

+ 9 - 1
src/views/custom_manage/approvalTurn.vue

@@ -14,7 +14,7 @@
 							<span>合同类型: {{contractInfo.ContractType}}</span>
 						</li>
 						<li>
-							<span style="min-width:450px;marginRight:260px;display:inline-block;">合同期限:{{contractInfo.StartDate}}-{{contractInfo.EndDate}}({{contractInfo.StartDate|formateYear(contractInfo.EndDate)}})</span>
+							<span style="min-width:450px;marginRight:260px;display:inline-block;">合同期限:{{ContractTermTxt}}</span>
 							<span>合同金额:{{contractInfo.Money}}元</span>
 						</li>
 						<li>
@@ -267,6 +267,14 @@ export default {
 		}
 		this.getCompanyInfo()
 	},
+	computed:{
+		ContractTermTxt(){
+			let date = `${this.contractInfo.StartDate}-${this.contractInfo.EndDate}`;
+			let calculation = CalculationDate(this.contractInfo.StartDate,this.contractInfo.EndDate);
+			let str = this.contractInfo.Quarter ? this.contractInfo.Quarter + `(${date})` : date + `(${calculation})`;
+			return str
+		}
+	},
 }
 </script>
 <style lang='scss'>

+ 1 - 1
src/views/custom_manage/approvalUpdate.vue

@@ -12,7 +12,7 @@
 						<span>合同类型:{{contractInfo.ContractType}}</span><span class="contract_type_hint">{{contractInfo.SourceTag}}</span>
 					</li>
 					<li>
-						<span style="min-width:320px;marginRight:260px;display:inline-block;">合同期限:{{contractInfo.StartDate}}-{{contractInfo.EndDate}}({{diff_time}}年期)</span>
+						<span style="min-width:320px;marginRight:260px;display:inline-block;">合同期限:{{contractInfo.Quarter}}{{contractInfo.StartDate}}-{{contractInfo.EndDate}}({{diff_time}}年期)</span>
 						<span>合同金额:{{contractInfo.Money}}元</span>
 					</li>
 					<li>

+ 74 - 183
src/views/custom_manage/compontents/CauthList.vue

@@ -14,98 +14,23 @@
 		<!-- 权益拆分 -->
 		<div v-if="autharr[0] && autharr[0].RaiMerge == 2" class="qy_menuList">
 			<el-table :data="autharr[0].dataList" :show-header="false" border :span-method="spanMethod">
-				<el-table-column align="center">
+				<el-table-column align="center" :width="autharr[0].dataList[0][key].width?autharr[0].dataList[0][key].width:''" 
+				v-for="key in Object.keys(autharr[0].dataList[0])" :key="key">
 					<template slot-scope="scope">
-						<span v-if="!scope.row.PermissionTypeName">
-							{{scope.row.PermissionTypeName}}
-						</span>
-						<el-checkbox :label="scope.row.PermissionTypeName.value" v-else @change="handleCheckQY(scope.row.PermissionTypeName)"
-						v-model="scope.row.PermissionTypeName.isCheckAll" :disabled="scope.row.PermissionTypeName.isDisabled"
-						:indeterminate="scope.row.PermissionTypeName.isIndeterminate"></el-checkbox>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<el-checkbox v-if="scope.row.medicine.value === '医药'" :label="scope.row.medicine.value" :indeterminate="scope.row.medicine.isIndeterminate"
-						@change="handleCheckQY(scope.row.medicine)" v-model="scope.row.medicine.isCheckAll" :disabled="scope.row.medicine.isDisabled"></el-checkbox>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.medicine.value" class="checkbox-flex"
-							:disabled="scope.row.medicine.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<el-checkbox v-if="scope.row.consumption.value === '消费'" :label="scope.row.consumption.value" :indeterminate="scope.row.consumption.isIndeterminate"
-						@change="handleCheckQY(scope.row.consumption)" v-model="scope.row.consumption.isCheckAll" :disabled="scope.row.consumption.isDisabled"></el-checkbox>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.consumption.value" class="checkbox-flex"
-							:disabled="scope.row.consumption.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<el-checkbox v-if="scope.row.technology.value === '科技'" :label="scope.row.technology.value" :indeterminate="scope.row.technology.isIndeterminate"
-						@change="handleCheckQY(scope.row.technology)" v-model="scope.row.technology.isCheckAll" :disabled="scope.row.technology.isDisabled"></el-checkbox>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.technology.value" class="checkbox-flex"
-							:disabled="scope.row.technology.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<el-checkbox v-if="scope.row.smart.value === '智造'" :label="scope.row.smart.value" :indeterminate="scope.row.smart.isIndeterminate"
-						@change="handleCheckQY(scope.row.smart)" v-model="scope.row.smart.isCheckAll" :disabled="scope.row.smart.isDisabled"></el-checkbox>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.smart.value" class="checkbox-flex"
-							:disabled="scope.row.smart.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<span v-if="scope.row.strategy.value === '策略'">
-							{{scope.row.strategy.value}}
-						</span>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.strategy.value" class="checkbox-flex"
-							:disabled="scope.row.strategy.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<span v-if="scope.row.experts.value === '专家'">
-							{{scope.row.experts.value}}
-						</span>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.experts.value" class="checkbox-flex"
-							:disabled="scope.row.experts.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<span v-if="scope.row.roadshow.value === '路演服务'">
-							{{scope.row.roadshow.value}}
-						</span>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.roadshow.value" class="checkbox-flex"
-							:disabled="scope.row.roadshow.isDisabled">{{''}}</el-checkbox>
-						</el-checkbox-group>
-					</template>
-				</el-table-column>
-				<el-table-column align="center">
-					<template slot-scope="scope">
-						<span v-if="scope.row.choose.value === '买方研选'">
-							{{scope.row.choose.value}}
-						</span>
-						<el-checkbox-group v-model="qyCheckList" v-else >
-							<el-checkbox :label="scope.row.choose.value" class="checkbox-flex"
-							:disabled="scope.row.choose.isDisabled">{{''}}</el-checkbox>
+						<!-- 主客观 区分的品种+复选框-->
+						<el-checkbox :label="scope.row[key].value" @change="handleCheckQY(scope.row[key])"
+						v-model="scope.row[key].isCheckAll" :disabled="scope.row[key].isDisabled"
+						:indeterminate="scope.row[key].isIndeterminate"
+						v-if="(scope.row[key].ids && scope.row[key].ids.length) || (scope.row[key].bothIds&& scope.row[key].bothIds.length)"></el-checkbox>
+						<!-- 不区分 只有复选框-->
+						<el-checkbox-group v-model="qyCheckList" v-else-if="typeof(scope.row[key].value)=='number'">
+							<el-checkbox :label="scope.row[key].value" class="checkbox-flex"
+							:disabled="scope.row[key].isDisabled">{{''}}</el-checkbox>
 						</el-checkbox-group>
+						<!-- 只有品种名称 -->
+						<template v-else>
+							{{scope.row[key].value}}
+						</template>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -119,6 +44,20 @@
 </template>
 
 <script>
+// 权益的ID:
+/**
+ * 科技-主观(20)-客观(37)
+ * 消费-主观(21)-客观(38)
+ * 医药-主观(22)-客观(39)
+ * 智造-主观(19)-客观(36)
+ * 策略(23)
+ * 专家(29)
+ * 固收(53)
+ * 调研(54)
+ * 路演服务(30)
+ * 研选订阅(31)
+ * 研选扣点包(52)
+ */
 import { customInterence } from '@/api/api.js'
 export default {
 	name:'',
@@ -133,45 +72,36 @@ export default {
 	},
 	watch: {
 		autharr(value){
-			// console.log(value);
+			// console.log(value,'valuevaluevaluevalue');
 			if(value[0] && value[0].customType=='权益') this.qyCheckList = value[0].CheckList
 		},
 		qyCheckList(value){
+			let checkedIds=value||[]
 			// 根据复选框选择的情况 改变医药、消费、科技、智造、主客观复选框的状态
-			let arr = ['medicine','consumption','technology','smart']
-			for (let i = 0; i < arr.length; i++) {
-				let element = arr[i];
-				let arrLength = value.filter(item => {
-					return item == this.autharr[0].dataList[1][element].value || item == this.autharr[0].dataList[2][element].value
-				}).length
-				if(arrLength == 2){
-					this.autharr[0].dataList[0][element].isCheckAll=true
-					this.autharr[0].dataList[0][element].isIndeterminate=false
-				}else if(arrLength == 1){
-					this.autharr[0].dataList[0][element].isCheckAll=false
-					this.autharr[0].dataList[0][element].isIndeterminate=true
+			this.autharr[0].dataList.map(it =>{
+				if(it.PermissionTypeName&&it.PermissionTypeName.value){
+					let idArr = [...checkedIds,...it.PermissionTypeName.ids]
+					let idArrLen = idArr.length
+					// 去重后的
+					let idRemovalArrLen = [...new Set(idArr)].length
+					it.PermissionTypeName.isCheckAll = idArrLen-idRemovalArrLen == it.PermissionTypeName.ids.length
+					it.PermissionTypeName.isIndeterminate = idArrLen-idRemovalArrLen < it.PermissionTypeName.ids.length && 
+																									idArrLen-idRemovalArrLen > 0					
 				}else{
-					this.autharr[0].dataList[0][element].isCheckAll=false
-					this.autharr[0].dataList[0][element].isIndeterminate=false
-				}
-			}
-			for (let i = 0; i < 2; i++) {
-				let arrLength = value.filter(item => {
-					return item == this.autharr[0].dataList[i+1].medicine.value || item == this.autharr[0].dataList[i+1].consumption.value ||
-						item == this.autharr[0].dataList[i+1].technology.value || item == this.autharr[0].dataList[i+1].smart.value
-				}).length
-				if(arrLength == 4){
-					this.autharr[0].dataList[i+1].PermissionTypeName.isCheckAll=true
-					this.autharr[0].dataList[i+1].PermissionTypeName.isIndeterminate=false
-				}else if(arrLength == 0){
-					this.autharr[0].dataList[i+1].PermissionTypeName.isCheckAll=false
-					this.autharr[0].dataList[i+1].PermissionTypeName.isIndeterminate=false
-				}else{
-					this.autharr[0].dataList[i+1].PermissionTypeName.isCheckAll=false
-					this.autharr[0].dataList[i+1].PermissionTypeName.isIndeterminate=true
+					Object.values(it).forEach(permission =>{
+						if(permission.bothIds && permission.bothIds.length>1){
+							// 有主客观的
+							let idArr = [...checkedIds,...permission.bothIds]
+							let idArrLen = idArr.length
+							// 去重后的
+							let idRemovalArrLen = [...new Set(idArr)].length
+							permission.isCheckAll = idArrLen-idRemovalArrLen == permission.bothIds.length
+							permission.isIndeterminate = idArrLen-idRemovalArrLen < permission.bothIds.length && 
+																											idArrLen-idRemovalArrLen > 0
+						}
+					})
 				}
-			}
-			
+			})
 		}
 	},
 	data () {
@@ -194,7 +124,6 @@ export default {
 				// 权益拆分
 				checkArr = this.qyCheckList
 			}
-
 			customInterence.addTryout({
 				CompanyId:this.id,
 				ChartPermissionId:checkArr.join()
@@ -221,24 +150,27 @@ export default {
 				item.Items.map((it,i)=>{
 					if(item.CheckList.includes(it.ChartPermissionId) && it.PermissionType==1){
 						// 主观被选上,将客观的ID也push上
-						item.CheckList.push(item.Items[i+1].ChartPermissionId)
+						let ob=item.Items.find(pe => pe.PermissionName == it.PermissionName && pe.PermissionType==2)
+						item.CheckList.push(ob?ob.ChartPermissionId:0)
 					}else if(!item.CheckList.includes(it.ChartPermissionId) && it.PermissionType==1){
-						if(item.CheckList.indexOf(item.Items[i+1].ChartPermissionId)!=-1){
-							item.CheckList.splice(item.CheckList.indexOf(item.Items[i+1].ChartPermissionId),1)
+						// 主观被去除,将客观的ID也去除
+						let ob=item.Items.find(pe => pe.PermissionName == it.PermissionName && pe.PermissionType==2)
+						let obIndex = item.CheckList.indexOf(ob?ob.ChartPermissionId:0)
+						if(obIndex!=-1){
+							item.CheckList.splice(obIndex,1)
 						}
 					}
 				})
 			}
 			item.CheckList = [...new Set(item.CheckList)]
-			// console.log(item);
-			let len = item.CheckList.length;
+			let len = item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId)).length
 			item.checkAll = len === item.Items.length;
 			item.isIndeterminate = len > 0 && len < item.Items.length;
 		},
 		// 权益选择套餐方法
 		// 合并单元格
 		spanMethod({ row, rowIndex, column,columnIndex  }){
-			if([5,6,7,8].includes(columnIndex)){
+			if(Object.values(row)[columnIndex].merge){
 				if(rowIndex == 1){
 					return [2,1]
 				}else if(rowIndex == 2){
@@ -247,69 +179,28 @@ export default {
 			}
 		},
 		handleCheckQY(item){
-			// console.log(item);
-			let arr = ['medicine','consumption','technology','smart']
-			let arrCh = ['医药','消费','科技','智造']
 			// 全选
 			if(item.isCheckAll){
-				if(item.value == '主观'){
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
-						this.qyCheckList.push(this.autharr[0].dataList[1][element].value)
-						this.qyCheckList = [...new Set(this.qyCheckList)]
-					}
-				}else if(item.value == '客观'){
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
-						this.qyCheckList.push(this.autharr[0].dataList[2][element].value)
-						this.qyCheckList = [...new Set(this.qyCheckList)]
-					}
+				if(["客观","主观"].includes(item.value)){
+					this.qyCheckList = [...new Set([...this.qyCheckList,...item.ids])]
 				}else{
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
-						const elementCh = arrCh[i];
-						if(item.value == elementCh){
-							this.qyCheckList.push(this.autharr[0].dataList[1][element].value,this.autharr[0].dataList[2][element].value)
-							this.qyCheckList = [...new Set(this.qyCheckList)]
-							break
-						}
-					}
+					this.qyCheckList = [...new Set([...this.qyCheckList,...item.bothIds])]
 				}
 			}else{ //全部不选
-				if(item.value == '主观'){
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
+				if(["客观","主观"].includes(item.value)){
+					item.ids.map(pId =>{
 						// 需要删除的索引
-						let deleteIndex = this.qyCheckList.findIndex(id=> {
-							return id == this.autharr[0].dataList[1][element].value && (!this.autharr[0].dataList[2][element].isDisabled)
-						});
-						if(deleteIndex!=-1) this.qyCheckList.splice(deleteIndex,1)
-					}
-				}else if(item.value == '客观'){
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
-						let deleteIndex = this.qyCheckList.findIndex(id=> {
-							return id == this.autharr[0].dataList[2][element].value && (!this.autharr[0].dataList[2][element].isDisabled)
-						});
+						let deleteIndex = this.qyCheckList.findIndex(id=> id==pId && !(this.autharr[0].defaultAuth.includes(id)));
 						if(deleteIndex!=-1) this.qyCheckList.splice(deleteIndex,1)
-					}
+					})
 				}else{
-					for (let i = 0; i < arr.length; i++) {
-						const element = arr[i];
-						const elementCh = arrCh[i];
-						if(item.value == elementCh){
-							for (let i = 0; i < 2; i++) {
-								let deleteIndex = this.qyCheckList.findIndex(id=> {
-									return id == this.autharr[0].dataList[i+1][element].value && (!this.autharr[0].dataList[i+1][element].isDisabled)
-								});
-								if(deleteIndex!=-1) this.qyCheckList.splice(deleteIndex,1)
-							}
-							break
-						}
-					}
+					item.bothIds.map(pId =>{
+						// 需要删除的索引
+						let deleteIndex = this.qyCheckList.findIndex(id=> id==pId && !(this.autharr[0].defaultAuth.includes(id)));
+						if(deleteIndex!=-1) this.qyCheckList.splice(deleteIndex,1)
+					})
 				}
 			}
-			// console.log(this.qyCheckList);
 		}
 	},
 	created() {},

+ 17 - 13
src/views/custom_manage/compontents/Contactdialog.vue

@@ -80,8 +80,8 @@
             <el-input v-model="userForm.post" placeholder="请输入职位" style="width: 315px" clearable>
             </el-input>
           </el-form-item>
-          <el-form-item label="决策人" prop="desiger" style="margin-right: 30px">
-            <el-select v-model="userForm.desiger" placeholder="请选择是否是决策人" style="width: 280px">
+          <el-form-item label="是否KP" prop="desiger" style="margin-right: 30px">
+            <el-select v-model="userForm.desiger" placeholder="请选择是否是KP" style="width: 280px">
               <el-option v-for="(item, index) in ['否', '是']" :key="item" :label="item" :value="index">
               </el-option>
             </el-select>
@@ -201,7 +201,7 @@
 
 <script>
 import { validateTel, validatePwd } from "@/utils/validate.js";
-import { customInterence } from "@/api/api.js";
+import { customInterence, departInterence } from "@/api/api.js";
 import { lang } from 'moment';
 export default {
   name: "",
@@ -276,16 +276,7 @@ export default {
       }
     };
     return {
-      telCodeArr: [
-        { value: '86', label: '+86' },
-        { value: '852', label: "+852" },
-        { value: '886', label: '+886' },
-        { value: '1', label: '+1' },
-        { value: '65', label: '+65' },
-        { value: '62', label: '+62' },
-        { value:'081',label: '+081' },
-        { value:'44',label: '+44' }
-      ],
+      telCodeArr: [],
 
       isHaveUser: false, //已存在联系人弹窗
       uploadloading: false,
@@ -329,6 +320,18 @@ export default {
     };
   },
   methods: {
+    getPhoneCode(){
+        departInterence.getPhoneAreaCode().then(res=>{
+            if(res.Ret!==200) return 
+            this.telCodeArr = res.Data||[]
+            this.telCodeArr = this.telCodeArr.map(i=>{
+                return {
+                    value:i.Value,
+                    label:i.Name
+                }
+            })
+        })
+    },
     // 领取自己的流失客户点击下一步
     handleNext() {
       this.$refs.userForm.validate((valid) => {
@@ -728,6 +731,7 @@ export default {
   },
   watch: {
     isAddContact() {
+        this.getPhoneCode()
       if (this.userForm.Source) {
         this.userFormIndeterminacy = this.userForm.Source
       } else {

+ 28 - 7
src/views/custom_manage/compontents/CpessionTable.vue

@@ -132,21 +132,42 @@ export default {
 		},
 		// 是否可选择
 		canSelect(row) {
-			return row.ChartPermissionId === 1 ? false : true;
+			return row.IsPublic == 1 ? false : true;
 		}
 	},
 	created() {},
 	mounted() {
 		this.isRaiMerge = this.authList[0].RaiMerge
 		/* 处理表格数据格式 */
-		this.filterAuth = this.authList.map((item) => {
+		let tempArr=this.authList.map((item) => {
 			return item.Items;
 		});
-		this.filterAuth = this.filterAuth.flat(Infinity);
-		if(this.isRaiMerge==1){
+		tempArr = tempArr.flat(Infinity);
+		console.log(tempArr);
+		if(!this.isRaiMerge){
+			this.filterAuth = tempArr
+		}else if(this.isRaiMerge==1){
 			// 主客观合并 只取主观的
-			this.filterAuth = this.filterAuth.filter(it => {
-				return (['医药','消费','科技','智造'].includes(it.PermissionName) && it.PermissionType==1) || (!['医药','消费','科技','智造'].includes(it.PermissionName))
+			this.filterAuth = tempArr.filter(it => {
+				return it.PermissionType==1 || it.PermissionType==0
+			})
+		}else if(this.isRaiMerge==2){
+			// 主客观拆分 只取主观的
+			tempArr.map(item =>{
+				// 排下序 
+				if(item.PermissionType==1){
+					//主观 找客观
+					this.filterAuth.push(item)
+					let ob = tempArr.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+					ob && this.filterAuth.push(ob)
+				}else if(item.PermissionType==0){
+					this.filterAuth.push(item)
+				}else{
+					// 客观
+					if(!this.filterAuth.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+						this.filterAuth.push(item)
+					}
+				}
 			})
 		}
 		/* 选中的id数组 */
@@ -161,7 +182,7 @@ export default {
 		let check_Auth = this.filterAuth.filter((item) => {
 			return select.includes(item.ChartPermissionId);
 		});
-
+		console.log(check_Auth,'check_Auth');
 		if (this.fromType === 'edit') {
 			/* 展示表格选中的key */
 			let _this = this; 

+ 32 - 4
src/views/custom_manage/compontents/CpessionTableEquity.vue

@@ -36,6 +36,19 @@
 </template>
 
 <script>
+/**权益权限ID
+ * 科技-主观(20)-客观(37)
+ * 消费-主观(21)-客观(38)
+ * 医药-主观(22)-客观(39)
+ * 智造-主观(19)-客观(36)
+ * 策略(23)
+ * 专家(29)
+ * 固收(53)
+ * 调研(54)
+ * 路演服务(30)
+ * 研选订阅(31)
+ * 研选扣点包(52)
+ */
 export default {
 	props: {
 		authList: {
@@ -61,7 +74,7 @@ export default {
 	methods: {
 		/* 处理合并数组 */
 		getRowSpan() {
-            this.filterAuth.map((v, i, s) => {
+			this.filterAuth.map((v, i, s) => {
 				if (!v.PermissionTypeName) {
 				this.indexArrEquity.push(i);
 				}
@@ -200,9 +213,24 @@ export default {
 		}else {
 			/* 显示只有权限的数组 */
 			this.filterAuth = [];
-			this.filterAuth = check_Auth.filter((item) => {
-				return item.Status === '正式' || item.Status === '试用' || item.Status === '永续'||item.Status=='关闭'
-			});
+			check_Auth.map(item =>{
+				// 排序 以防合并问题
+				if(item.Status === '正式' || item.Status === '试用' || item.Status === '永续'||item.Status=='关闭'){
+					if(item.PermissionType==1){
+						//主观 找客观
+						this.filterAuth.push(item)
+						let ob = check_Auth.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+						ob && this.filterAuth.push(ob)
+					}else if(item.PermissionType==0){
+						this.filterAuth.push(item)
+					}else{
+						// 客观
+						if(!this.filterAuth.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+							this.filterAuth.push(item)
+						}
+					}
+				}
+			})
 			this.isMerge = this.filterAuth.some((item) => !item.IsMerge)
 		}
 		

+ 2 - 1
src/views/custom_manage/compontents/Ctimeline.vue

@@ -17,7 +17,7 @@
 					<span v-if="activity.Operation=='freeze'&&activity.ApproveContent" class="freeze-text" @click="showFreeze(activity)">冻结理由</span>
 					<span v-if="(specialOperationList.includes(activity.Operation))&&activity.ApproveContent" @click="showRemark(activity)" class="freeze-text">未续约说明</span>
 					<!-- <span v-if="activity.Operation=='try_out'&&!isHasTryOutRenewalReason" class="freeze-text" @click="showAddRemark(activity)">添加说明</span> -->
-					<span v-if="isShowBtn&&index==firstTryOutIdx" class="freeze-text" @click="showAddRemark(activity)">添加未续约说明</span>
+					<span v-if="activity.Remark=='正式转试用'" class="freeze-text" @click="showAddRemark(activity)">添加未续约说明</span>
 					<span v-if="activity.Operation==='close'&&activity.ApproveContent" @click="showCloseRemark(activity)" class="freeze-text">关闭理由</span>
 				</el-timeline-item>
 			</el-timeline>
@@ -177,6 +177,7 @@ export default {
 		},
 		// 显示添加说明弹窗
 		showAddRemark(e){
+			console.log(e);
 			this.activeActivity=e
 			this.isShowAddDia=true
 		},

+ 23 - 5
src/views/custom_manage/compontents/FreezAuthList.vue

@@ -4,9 +4,9 @@
 		<h3>请选择需要开通试用的品种:</h3>
 		<ul class="menu_lists">
 			<li v-for="item in autharr" :key="item.ClassifyName" class="menu_item">
-				<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="item.ClassifyName==='宏观经济'" style="marginRight:30px;fontWeight:bold;minWidth:90px;" @change="handleCheckAll(item)">{{item.ClassifyName+':'}}</el-checkbox>
+				<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="setSelectPerDisabled(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;" @change="handleCheckAll(item)">{{item.ClassifyName+':'}}</el-checkbox>
 				<el-checkbox-group v-model="item.CheckList"  @change="handleChecked(item)">
-					<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.ChartPermissionId===1" >{{list.PermissionName}}</el-checkbox>
+					<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.IsPublic===1" >{{list.PermissionName}}</el-checkbox>
 				</el-checkbox-group>
 			</li>
 		</ul>
@@ -29,12 +29,24 @@ export default {
 	methods: {
 		/* 选择全选或取消全选 */
 		handleCheckAll(item) {
-			// 取到所有的子菜单id
+			// // 取到所有的子菜单id
+			// let ids = item.Items.map(item =>{
+			// 	return item.ChartPermissionId
+			// })
+			// item.CheckList = item.checkAll ? ids : [];
+			// item.isIndeterminate = false;
+			//获取公有的id合集
+			let publicIds=[]
+
+			
 			let ids = item.Items.map(item =>{
+				if(item.IsPublic==1){
+					publicIds.push(item.ChartPermissionId)
+				}
 				return item.ChartPermissionId
 			})
-			item.CheckList = item.checkAll ? ids : [];
-			item.isIndeterminate = false;
+			item.CheckList = item.checkAll ? ids : publicIds;	
+        	item.isIndeterminate = publicIds.length>0&&!item.checkAll?true:false;
 		},
 		/* 复选框組选中时 */
 		handleChecked(item) {
@@ -42,6 +54,12 @@ export default {
 			item.checkAll = len === item.Items.length;
 			item.isIndeterminate = len > 0 && len < item.Items.length;
 		},
+		//控制权限设置是否禁用编辑
+		setSelectPerDisabled(data){
+			if(!data) return true
+			const arr=data.Items?data.Items.filter(_e=>_e.IsPublic==1):[]
+			return arr.length==data.Items.length
+		}
 	},
 	mounted() {},
 }

+ 2 - 2
src/views/custom_manage/contacts/contactsList.vue

@@ -2,7 +2,7 @@
   <div class="container-contactsList">
     <div class="top-wrap">
       <el-input style="width: 200px; margin-right: 20px" v-model="contactWay" placeholder="手机号/邮箱/姓名/公司名" prefix-icon="el-icon-search" clearable></el-input>
-      <el-select v-model="decisionValue" placeholder="是否决策人" @change="handelGetData" clearable>
+      <el-select v-model="decisionValue" placeholder="是否KP" @change="handelGetData" clearable>
         <el-option v-for="item in decisionOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
       </el-select>
       <el-select v-model="registerValue" placeholder="是否注册" @change="handelGetData" clearable>
@@ -66,7 +66,7 @@
         </el-table-column>
         <el-table-column align="center" prop="Status" width="100" label="状态"> </el-table-column>
         <el-table-column align="center" prop="SellerName" width="110" label="所属销售"> </el-table-column>
-        <el-table-column align="center" prop="IsMaker" width="80" label="决策人">
+        <el-table-column align="center" prop="IsMaker" width="80" label="是否KP">
           <template slot-scope="{ row }">
             {{ row.IsMaker == 1 ? "是" : "否" }}
           </template>

+ 45 - 19
src/views/custom_manage/customList/addCustom.vue

@@ -61,20 +61,23 @@
 				disabled
 				clearable></el-input>
 			</el-form-item>
-			<el-form-item label="客户地址" prop="city"  :rules="[{
+			<el-form-item v-if="dataForm.area==='海外'" label="所属国家" prop="Nation"
+				:rules="[{required:true,message: '所属国家不能为空', trigger: 'change' }]">
+				<i style="color:#f00;fontSize:20px;position:absolute;left:-90px;top:10%;">*</i>
+				<el-select v-model="dataForm.Nation" placeholder="请选择" filterable style="width: 400px;">
+					<el-option :label="item.cnName" :value="item.cnName" v-for="item in countryData" :key="item.code" >
+					<div style="display: flex;justify-content: space-between;">
+						<span>{{ item.cnName }}</span>
+						<span style="color: #8492a6; font-size: 13px">{{ item.code }}</span>
+					</div>
+					</el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item v-else label="客户地址" prop="city"  :rules="[{
 					required:true,
 					message: '客户地址不能为空', 
-					trigger: 'change' 
-        }]">
+					trigger: 'change' }]">
 				<i style="color:#f00;fontSize:20px;position:absolute;left:-90px;top:10%;">*</i>
-				<!-- <v-distpicker :province-source="province_sorce"
-                :city-source="city_sorce"  
-				:province="dataForm.province"
-				:city="dataForm.city"
-				hide-area 
-				@selected="selectRegion"
-				@province="provinceChange"
-				></v-distpicker> -->
 				<search-dist-picker @selected="selectRegion"/>
 			</el-form-item>
 			<el-form-item label="客户状态" prop="cuStatus" style="marginRight:120px;">
@@ -157,9 +160,9 @@
 				</label>
 				<ul class="menu_lists">
 					<li v-for="item in authList" :key="item.ClassifyName" class="menu_item">
-						<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="item.ClassifyName === '宏观经济'" @change="handleCheckAll(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
+						<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="setSelectPerDisabled(item)" @change="handleCheckAll(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
 						<el-checkbox-group  v-model="item.CheckList" @change="handleChecked(item)">
-							<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.ChartPermissionId==1">{{list.PermissionName}}</el-checkbox>
+							<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.IsPublic==1">{{list.PermissionName}}</el-checkbox>
 						</el-checkbox-group>
 					</li>
 				</ul>
@@ -222,6 +225,7 @@
 
 <script>
 import { customInterence } from '@/api/api.js'
+import country from "@/utils/countryData"
 //import{province_sorce,city_sorce} from '@/utils/distpicker';
 import Contactdia from '../compontents/Contactdialog'
 // import JurisdictionCheck from '../compontents/jurisdictionCheck.vue';
@@ -251,6 +255,7 @@ export default {
 	data () {
 /*     this.province_sorce=province_sorce
     this.city_sorce=city_sorce */
+		this.countryData = country
 		return {
 			codeDisable:false,//是否可编辑社会信用码国内可
 			companyList:[],
@@ -482,14 +487,23 @@ export default {
 				if(res.Ret === 200) {
 					let newArr = [];
 					res.Data.List.length&&res.Data.List.forEach(item => {
+						item.Items=item.Items||[]
+						const temarr=item.Items?item.Items.filter(_e=>_e.IsPublic==1):[]
 						let obj = {
-							checkAll:false,
-							isIndeterminate:item.ClassifyName === '宏观经济'?true:false,
 							...item,
+
+							// checkAll:false,
+							// isIndeterminate:item.ClassifyName === '宏观经济'?true:false,
+							// 修改为通过公有私有判断
+							checkAll:item.Items.length>0?temarr.length==item.Items.length:false,
+							isIndeterminate:item.Items.length>0?temarr.length==item.Items.length?false:item.Items.some(_e=>_e.IsPublic==1):false,
+							CheckList:item.CheckList||[],
+							
 						}
 						newArr.push(obj)
 					})
 					this.authList = newArr;
+					console.log(this.authList);
 					// if(this.dataForm.custype == '权益') {
 					// 	this.citiesEquity = res.Data.ListType ? res.Data.ListType[0].Items : [];
         			// 	this.citiesListEquity  = res.Data.List ? res.Data.List[0].Items : [];
@@ -508,6 +522,11 @@ export default {
 				}
 			})
 		},
+		//控制权限设置是否禁用编辑
+		setSelectPerDisabled(data){
+			const arr=data.Items?data.Items.filter(_e=>_e.IsPublic==1):[]
+			return arr.length==data.Items.length
+		},
 		/* 获取销售 */
 		getSale() {
 			customInterence.saleslist().then(res => {
@@ -589,7 +608,8 @@ export default {
 					Reasons:this.dataForm.addreason,
 					PermissionIds,
 					Scale:this.dataForm.money,
-					UserId:Number(id)
+					UserId:Number(id),
+					Nation:this.dataForm.area==='海外'?this.dataForm.Nation:''
 				}
 				customInterence.customAdd(params).then(res => {
 					if(res.Ret === 200) {
@@ -619,13 +639,19 @@ export default {
 		/* 选择全选或取消全选 */
 		handleCheckAll(item) {
 			// 取到所有的子菜单id
-		
+
+			//获取公有的id合集
+			let publicIds=[]
+
 			
 			let ids = item.Items.map(item =>{
+				if(item.IsPublic==1){
+					publicIds.push(item.ChartPermissionId)
+				}
 				return item.ChartPermissionId
 			})
-			item.CheckList = item.checkAll ? ids : [];	
-        	item.isIndeterminate = false;
+			item.CheckList = item.checkAll ? ids : publicIds;	
+        	item.isIndeterminate = publicIds.length>0&&!item.checkAll?true:false;
 		},
 		/* 复选框組选中时 */
 		handleChecked(item) {

+ 78 - 27
src/views/custom_manage/customList/applyTurn.vue

@@ -66,7 +66,7 @@
 									<i class="el-icon-info"></i>
 							</el-tooltip>
 						</el-form-item>
-						<el-form-item label="合同期限" prop="term" style="marginRight:60px;">
+						<el-form-item label="合同期限" prop="term" style="marginRight:60px;" :rules="{ required: true, message: '合同期限不能为空', trigger: 'blur' }" v-if="!isXClassCustom">
 							<i style="color:#f00;fontSize:20px;position:absolute;left:-90px;top:10%;">*</i>
 							<el-date-picker
 							v-model="formData.term"
@@ -79,6 +79,19 @@
 							style="width:400px;">
 							</el-date-picker>
 						</el-form-item>
+						<el-form-item label="合同期限" prop="term" :rules="{ required: true, message: '合同期限不能为空', trigger: 'change' }" style="marginRight:60px;" v-if="isXClassCustom">
+							<i style="color:#f00;fontSize:20px;position:absolute;left:-90px;top:10%;">*</i>
+							<div class="quarters-content">
+								<el-checkbox-group v-model="selectedQuarters" @input="checkboxInputHandler">
+									<el-checkbox v-for="quarter in quarters" :key="quarter.value" :label="quarter.label" :disabled="isDisabled(quarter)" >
+										{{ quarter.label }}
+									</el-checkbox>
+								</el-checkbox-group>
+								<div v-if="selectedQuarters.length > 0" class="quarters-text">
+										{{ selectedDateRange }}
+								</div>
+							</div>
+						</el-form-item>
 						<el-form-item label="合同金额" prop="amount" style="marginRight:60px;">
 							<i style="color:#f00;fontSize:20px;position:absolute;left:-90px;top:10%;">*</i>
 							<el-input 
@@ -119,15 +132,15 @@
 								<i style="color:#f00;fontSize:20px;position:absolute;left:-15px;top:10%;">*</i>
 								权限设置
 							</label>
-							<template  v-if="companyInfo.CompanyType=='权益' ||isRoleType== '权益'">
-								<raiPermissionbox v-for="item in authList" :key="item.ClassifyName" :data="item" :formData="formData"
+							<template  v-if="(companyInfo.CompanyType=='权益' || isRoleType== '权益') && !isXClassCustom" >
+								<raiPermissionbox ref="raiPermissionboxRef" v-for="item in authList" :key="item.ClassifyName" :data="item" :formData="formData"
 								:hasNoChild="hasNoChild"></raiPermissionbox>
 							</template>
 							<ul class="menu_lists" style="width:100%" v-else>
 								<li v-for="item in authList" :key="item.ClassifyName" class="menu_item">
-									<el-checkbox v-if="item.ClassifyName !== '权益'" :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="item.ClassifyName === '宏观经济' || item.disabled" @change="handleCheckAll(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
+									<el-checkbox  :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="setSelectVarietyDisabled(item)" @change="handleCheckAll(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
 									<el-checkbox-group v-model="item.CheckList" @change="handleChecked(item)">
-										<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.ChartPermissionId==1  || list.disabled">{{list.PermissionName}}</el-checkbox>
+										<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.IsPublic==1  || list.disabled">{{list.PermissionName}}</el-checkbox>
 									</el-checkbox-group>
 								</li>
 							</ul>
@@ -179,10 +192,16 @@ import pdf from 'vue-pdf'
 import {CalculationDate} from '@/utils/CalculationDate'
 import JurisdictionCheck from '../compontents/jurisdictionCheck.vue';
 import raiPermissionbox from './components/raiPermissionbox'
-
+import quartersMixin from './mixins/quartersMixin'
 export default {
 	name:'',
+	mixins:[quartersMixin],
 	components: {imgPreview,pdf ,JurisdictionCheck,raiPermissionbox},
+	computed:{
+		isXClassCustom(){
+			return	this.companyInfo.Status.includes('永续') || this.companyInfo.Status.includes('X类试用')
+		}
+	},
 	data () {
 		return {
 			companyInfo:JSON.parse(sessionStorage.getItem('companyInfo')) || {},//客户基本信息
@@ -200,9 +219,6 @@ export default {
 			hasNoChild:false, // 医药、消费、科技、智造是否没有主客观
 			authList:[],//权限列表
 			formRule:{
-				term:[
-					{ required: true, message: '合同期限不能为空', trigger: 'blur' },
-				],
 				amount:[
 					{ required: true, message: '合同金额不能为空', trigger: 'blur' },
 					{ type: 'number', message: '合同金额必须为数字'}
@@ -229,6 +245,11 @@ export default {
 		};
 	},
 	methods: {
+		setSelectVarietyDisabled(item){
+			//return item.ClassifyName === '宏观经济' || item.disabled
+			return item.Items.some(_e=>_e.IsPublic==1)||item.disabled
+		},
+
 		/* 重新申请获取上次申请的合同信息并回显 */
 		getLastContract() {
 			customInterence.reapplyDetail({
@@ -249,9 +270,10 @@ export default {
 						setmeal:res.Data.Item.PackageType,
 						qyBigServeCheck:res.Data.Item.RaiPackageType
 					}
+					this.selectedQuarters = res.Data.Item.Quarter.split(',')
 					let newArr = [];
 					/* 处理权限列表 */
-					if(this.companyInfo.CompanyType == '权益' || this.isRoleType== '权益') {
+					if((this.companyInfo.CompanyType == '权益' || this.isRoleType== '权益') && !this.isXClassCustom ) {
 						res.Data.Item.PermissionList[0].Items.map(item => {
 							item.disabled=item.isIndeterminate=false								
 							if(item.ChartPermissionId==22 && (!item.Child)) this.hasNoChild=true
@@ -259,7 +281,7 @@ export default {
 						/* 处理数据把复选框 拆分成三个*/
 						res.Data.Item.PermissionList.length&&res.Data.Item.PermissionList.forEach(item => {
 						let arr = item.Items.filter(key=> [22,21,20,19,23,30].includes(key.ChartPermissionId))
-						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032].includes(key.ChartPermissionId))
+						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032,52,53,54].includes(key.ChartPermissionId))
 						let ItemsUp = item.Items.filter(key=> key.PermissionName.includes('升级'))
 						let ItemsBig = item.Items.filter(key=> key.ChartPermissionId==0)
 							let obj = {
@@ -273,6 +295,8 @@ export default {
 						})
 					} else {
 						res.Data.Item.PermissionList.forEach(item => {
+							item.CheckList=item.CheckList||[]
+							item.Items=item.Items||[]
 						let obj = {
 							checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
 							isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
@@ -287,10 +311,13 @@ export default {
 			)},
 		/* 获取基本权限信息 */
 		getAuthBasic() {
-			customInterence.authList().then(res => {
+			customInterence.authList({
+				IsShowYanXuanKouDian:true,
+				CompanyStatus:this.companyInfo.Status 
+			}).then(res => {
 				let newArr = [];
 				if(res.Ret === 200) {
-					if(this.companyInfo.CompanyType == '权益' || this.isRoleType== '权益') {
+					if((this.companyInfo.CompanyType == '权益' || this.isRoleType== '权益') && !this.isXClassCustom) {
 						res.Data.List[0].Items.map(item => {
 							item.disabled=item.isIndeterminate=false								
 							if(item.ChartPermissionId==22 && (!item.Child)) this.hasNoChild=true
@@ -298,7 +325,7 @@ export default {
 						/* 处理数据把复选框 拆分成三个*/
 						res.Data.List.length&&res.Data.List.forEach(item => {
 						let arr = item.Items.filter(key=> [22,21,20,19,23,30].includes(key.ChartPermissionId))
-						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032].includes(key.ChartPermissionId))
+						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032,52,53,54].includes(key.ChartPermissionId))
 						let ItemsUp = item.Items.filter(key=> key.PermissionName.includes('升级'))
 						let ItemsBig = item.Items.filter(key=> key.ChartPermissionId==0)
 							let obj = {
@@ -312,9 +339,11 @@ export default {
 						})
 					}else {
 						res.Data.List.length&&res.Data.List.forEach(item => {
+							item.CheckList=item.CheckList||[]
+							item.Items=item.Items||[]
 					    	let obj = {
-					    		checkAll:false,
-					    		isIndeterminate:item.ClassifyName === '宏观经济'?true:false,
+					    		checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
+					    		isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
 					    		...item,
 					    	}
 					    	newArr.push(obj)
@@ -340,11 +369,12 @@ export default {
 		saveHandle() {
 			this.$refs.formData.validate((valid) => {
 				if (valid) {
-					
 					/* 处理权限列表 */
 					let checkArr = [];
 					let checkArrName = [];
-					if(this.companyInfo.CompanyType==='权益' || this.isRoleType== '权益'){
+					let hasMinusSignVal = 0
+					if((this.companyInfo.CompanyType==='权益' || this.isRoleType== '权益') && !this.isXClassCustom){
+					 	hasMinusSignVal = this.$refs.raiPermissionboxRef[0].minus_sign_val;		
 						this.authList.forEach(item => {
 								if(item.CheckList.length) {
 									checkArr.push(item.CheckList)
@@ -361,11 +391,15 @@ export default {
 									checkArr.push(item.CheckList)
 								}
 							})
-						}
+					}
+					const hasFiftyTwo = checkArr.flat(2).includes(52);
+					if(hasFiftyTwo && !hasMinusSignVal) return this.$message.error('请输入研选扣点数')
+
 					if(!checkArr.length && this.companyInfo.CompanyType === '权益') {
 						this.$message.warning('请选择权限!');
 						return
 					}else {
+						
 						let PermissionIds = [... new Set(checkArr.flat(2))].join(',');
 						let params = {
 							CompanyId:Number(this.companyInfo.CompanyId),
@@ -380,7 +414,8 @@ export default {
 							PermissionIds,
 							PackageType:this.formData.setmeal ? this.formData.setmeal : 0,
 							PermissionNames:checkArrName.length? checkArrName.join(','):'',
-							RaiPackageType:this.formData.qyBigServeCheck||0
+							RaiPackageType:this.formData.qyBigServeCheck||0,
+							Points:hasMinusSignVal||0
 						}
 						// console.log(params);
 						customInterence.applyTurn(params).then(res => {
@@ -538,16 +573,21 @@ export default {
 				})
 			} else {
 				  this.authList.forEach(item => {
-					 if(item.ClassifyName == '宏观经济') {
-						 item.CheckList = [1]
-						 item.isIndeterminate = true
-						 item.Items[1].disabled=false
+					if(item.Items.some(_e=>_e.IsPublic==1)){
+						item.CheckList = []
+						item.Items.forEach(_e=>{
+							if(_e.IsPublic==1){
+								item.CheckList.push(_e.ChartPermissionId)
+							}
+							_e.disabled=false
+						})
+						item.isIndeterminate = true
 					 }else {
 						 item.Items.forEach(key => {		
-							item.CheckList = []
 							key.Checked = false
 							key.disabled = false
 						})
+						item.CheckList = []
 						item.isIndeterminate = false
 						item.checkAll = false
 						item.disabled = false	
@@ -556,7 +596,10 @@ export default {
 				})
 				this.$message.warning('请勾选品种')
 			}
-		}
+		},
+	checkboxInputHandler(){
+		this.formData.term = this.selectedQuarters ? [this.selectedDateRange.split(" ~ ")[0],this.selectedDateRange.split(" ~ ")[1]]:[]
+	}
 	
 	},
 	created() {},
@@ -651,6 +694,14 @@ export default {
 			}
 		}
 	}
-
+	.quarters-content {
+		position: relative;
+		.quarters-text {
+			position: absolute;
+			left: 0;
+			top: 20px;
+			color: #f00;
+		}
+	}
 }
 </style>

+ 35 - 6
src/views/custom_manage/customList/components/raiPermissionbox.vue

@@ -43,10 +43,15 @@
           <div class="rai-checkbox-upS-box" >
             <el-checkbox :label="itP.ChartPermissionId" v-for="(itP,inP) in data.ItemsPrivate" 
             :key="itP.ChartPermissionId" :disabled="itP.disabled" :style="{'height':hasNoChild?'48px':'95px','width':itemsPrivateWidth[inP]}"
-            class="rai-checkbox-item upS-item" @change="e => handlePrivateChecked(e,itP,data)">{{ itP.PermissionName }}</el-checkbox>
+            class="rai-checkbox-item upS-item" @change="e => handlePrivateChecked(e,itP,data)">
+            {{ itP.PermissionName }}
+            <p v-if="itP.ChartPermissionId == 31" class="checkbox-text">(30000元/年)</p>
+            <p v-if="itP.ChartPermissionId == 52" class="checkbox-text">(点/2000元)</p>
+            <input @click.stop @input="validateInteger" placeholder="请输入点数" style="margin-left:10px" v-if="itP.ChartPermissionId == 52 && data.CheckList.includes(52)" v-model="minus_sign_val" />
+            </el-checkbox>
           </div>
         </el-checkbox-group>
-        <div class="rai-checkbox-notice-box">
+        <div class="rai-checkbox-notice-box" v-if="data.ItemsUp.length>0">
           <span class="rai-checkbox-notice" v-if="formData.qyBigServeCheck">
             同时包含{{formData.qyBigServeCheck==2?"10":"16"}}次专项调研</span>
           <p class="rai-checkbox-notice" v-if="equityGroupDisabled(data.CheckList)">同时包含升级行业各5次专项调研</p>
@@ -60,9 +65,9 @@
   export default {
     name:'raiPermissionbox',
     data() {
-		  this.itemsPrivateWidth=['84px','146px','146px']
+		  this.itemsPrivateWidth=['84px','146px','260px','84px']
       return {
-        
+        minus_sign_val:''
       }
     },
     props:{
@@ -80,7 +85,6 @@
       }
     },
     created(){
-      // console.log(this.data);
       // 回显
       if(this.data.CheckList && this.data.CheckList.length>0){
         this.data.Items.map(item =>{
@@ -209,6 +213,15 @@
       },
       getQyBigServeCheckNumber(permissionName){
         return permissionName.includes('70')?1:2
+      },
+      // 只允许输入数字和删除键
+      validateInteger() {
+        this.minus_sign_val = this.minus_sign_val.replace(/[^0-9]/g, '');
+
+        // 如果输入不为空,则转换为整数
+        if (this.minus_sign_val !== '') {
+          this.minus_sign_val = parseInt(this.minus_sign_val, 10);
+        }
       }
     }
   }
@@ -257,10 +270,11 @@
 					display: flex;
 					align-items: center;
 					border: solid 1px #DCDFE6;
+          border-left: none;
 					height: 48px;
 					margin-right: -1px;
 					margin-left: -192px;
-					padding-left: 40px;
+					padding-left: 200px;
 					.rai-checkbox-notice {
 						color: #f00;
 					}
@@ -269,7 +283,22 @@
 			.rai-checkbox-upS-box{
 				display: flex;
 				.upS-item{
+          position: relative;
 					justify-content: flex-start;
+          .checkbox-text {
+            position: absolute;
+            font-size: 12px;
+            color: #999;
+            bottom: 15px;
+            left: 20px;
+          }
+          input {
+            width: 90px;
+            height: 30px;
+            border-radius: 4px;
+            padding-left: 10px;
+            border: 1px solid #dcdfe6;
+          }
 				}
 			}
 			.rai-checkbox-item{

+ 23 - 22
src/views/custom_manage/customList/components/shareListDialog.vue

@@ -4,24 +4,25 @@
         :close-on-click-modal="false"
         :modal-append-to-body="true"
         :append-to-body="true"
-        :title="`${customInfo.CompanyName}——服务记录`"
+        :title="`${customInfo.CompanyName}——沟通记录`"
         class="share-list-dialog"
         @close="closeDia"
     >
         <div class="dialog-cotainer">
             <div class="add-box" v-if="allowEdit">
-                <p class="label">服务描述</p>
+                <p class="label">沟通描述</p>
                 <el-input
                     type="textarea"
-                    placeholder="请输入服务描述"
+                    placeholder="请输入沟通描述"
                     v-model="recordContent"
-                    maxlength="100"
-                    show-word-limit
                     :rows="3"
                 />
+                <div v-if="allowEdit" style="margin-top:10px">
+                    <el-button type="primary" @click="addNewRecord">保存</el-button>
+                </div>
             </div>
             <div class="table-box">
-                <p class="label" >历史服务</p>
+                <p class="label" >历史沟通</p>
                 <el-table 
                     border 
                     :data="recordList"
@@ -38,7 +39,7 @@
                         v-if="allowEdit"
                         label="操作"
                         align="center"
-                        width="160"
+                        width="120"
                     >
                     <template slot-scope="{row,$index}">
                         <el-button type="text" size="small" style="color:#409eff;"
@@ -52,14 +53,8 @@
                 </el-table>
             </div>
         </div>
-        <div class="foot-container">
-            <template v-if="allowEdit">
-                <el-button type="primary" @click="addNewRecord">保存</el-button>
-                <el-button @click="closeDia">取 消</el-button>
-            </template>
-            <template v-else>
-                <el-button type="primary" @click="closeDia">知道了</el-button>
-            </template>
+        <div class="foot-container" v-if="!allowEdit">
+            <el-button type="primary" @click="closeDia">知道了</el-button>
         </div>
     </el-dialog>
 </template>
@@ -84,16 +79,16 @@ export default {
     data() {
         return {
             tableColumns:[{
-                label:'服务描述',
+                label:'沟通描述',
                 key:'Content',
-                minWidth:300
+                minWidth:350
             },{
                 label:'创建人',
                 key:'SysAdminName'
             },{
                 label:'创建时间',
                 key:'CreateTime',
-                minWidth:180
+                minWidth:150
             }],
             recordContent:'',
             recordList:[],
@@ -111,8 +106,12 @@ export default {
     methods: {
         getRecordList(){
             this.tableLoading = true
+            console.log(this.customInfo)
+
+            let CompanyType = this.$route.path==='/overseasCustomList' ? this.customInfo.Source : 2;
             customInterence.getRecordList({
-                CompanyId:this.customInfo.CompanyId
+                CompanyId:this.customInfo.CompanyId,
+                CompanyType
             }).then(res=>{
                 if(res.Ret!==200) return 
                 this.recordList = res.Data
@@ -127,12 +126,14 @@ export default {
         },
         addNewRecord(){
             if(!this.recordContent.length){
-                this.$message.warning('请输入服务描述')
+                this.$message.warning('请输入沟通描述')
                 return
             }
+            let CompanyType = this.$route.path==='/overseasCustomList' ? this.customInfo.Source : 2;
             customInterence.addRecord({
                 CompanyId:this.customInfo.CompanyId,
-                Content:this.recordContent
+                Content:this.recordContent,
+                CompanyType
             }).then(res=>{
                 if(res.Ret!==200) return 
                 this.$message.success('添加成功')
@@ -141,7 +142,7 @@ export default {
             })
         },
         deleteRecord(data){
-            this.$confirm('服务记录删除后不可恢复,确认删除吗?','提示',{
+            this.$confirm('沟通记录删除后不可恢复,确认删除吗?','提示',{
                 confirmButtonText: '确定',
                 cancelButtonText: '取消',
                 type:'warning',

+ 17 - 2
src/views/custom_manage/customList/customAllList.vue

@@ -793,8 +793,23 @@
                         let authEquity = [] //权益
                         res.Data.ListRai ? res.Data.ListRai.forEach(item => { //权益
                             // 过滤没有权限的套餐
-                            authEquity.push(item.Items.filter(it => item.CheckList.includes(it
-                                .ChartPermissionId)))
+                            let check_Auth = item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId))
+                            check_Auth.map(item =>{
+                                // 排序 以防合并问题
+                                if(item.PermissionType==1){
+                                    //主观 找客观
+                                    authEquity.push(item)
+                                    let ob = check_Auth.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+                                    ob && authEquity.push(ob)
+                                }else if(item.PermissionType==0){
+                                    authEquity.push(item)
+                                }else{
+                                    // 客观
+                                    if(!authEquity.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+                                        authEquity.push(item)
+                                    }
+                                }
+                            })
                         }) : ''
                         this.lookAuthListEquity = authEquity.flat(Infinity) //权益
                     }

+ 170 - 20
src/views/custom_manage/customList/customDetail.vue

@@ -20,7 +20,11 @@
 							<label class="label">所属区域</label>
 							<span class="con">{{basicform.RegionType}}</span>
 						</li>
-						<li >
+						<li v-if="basicform.RegionType==='海外'">
+							<label class="label">所属国家</label>
+							<span class="con">{{basicform.Nation}}</span>
+						</li>
+						<li v-else>
 							<label class="label">客户地址</label>
 							<span class="con">{{basicform.Province}}<span v-if="basicform.Province">/</span>{{basicform.City}}</span>
 						</li>
@@ -150,11 +154,12 @@
 						<el-button type="primary" @click="addConcat">添加联系人</el-button>
 						<el-button type="primary" @click.native="importHandle">批量导入</el-button>
 						<!-- <span style="fontSize:16px;color:#AAB4CC;">(请至少添加一位联系人)</span> -->
-						<!-- <el-button v-if="RoleType=='admin' || RoleType=='权益'" style="margin-left:20px" type="primary" @click="exportDataIsShow=true">导出数据</el-button> -->
+						<!-- <el-button v-if="RoleType=='admin' || isUserYanXuanButtonShow" style="margin-left:20px" type="primary" @click="exportDataIsShow=true">导出数据</el-button> -->
 						<a :href="downTemplate" download style="fontSize:14px;color:#409eff;margin-left:30px">下载导入模板</a>
 					</div>
 				</div>
 				<div style="display: flex">
+				  <template v-if="!isUserYanXuanButtonShow">
 					<el-select 
 						v-model="IsSubscribe"
 						placeholder="是否关注公众号" 
@@ -195,6 +200,7 @@
 							{{ item.ProductName }}
 						</el-option>
 					</el-select>
+				  </template>
 					<el-input
 						placeholder="姓名/手机号码/邮箱"
 						v-model="search_txt"
@@ -210,6 +216,7 @@
 				ref="userTable"
 				:data="userTable"
 				v-loading="isShowloadding"
+				:row-class-name="setRowClass"
 				element-loading-text="数据加载中..."
 				border>
 					<el-table-column
@@ -224,6 +231,7 @@
 							<img :src="$icons.card" alt="" style="width:17px;cursor:pointer;marginRight:5px;"
 							v-if="scope.row.BusinessCardUrl"
 							@click="reviewCard(scope.row.BusinessCardUrl)">
+							<img src="~@/assets/img/icons/like-heart.png" class="name-follow-heart" v-if="scope.row.IsFollow==1">
 							<span :class="{'isShared':scope.row.IsShared}">{{scope.row.RealName}}</span>
 						</template>
 					</el-table-column>
@@ -243,30 +251,55 @@
 					</el-table-column>
 					<el-table-column
 					prop="IsMaker"
-					label="决策人"
+					label="是否KP"
 					align="center">
 						<template slot-scope="scope"> <span>{{scope.row.IsMaker==1?'是':'否'}}</span> </template>
 					</el-table-column>
-					<el-table-column
-					prop="IsRegister"
-					label="是否注册"
-					align="center">
-						<template slot-scope="scope"> <span>{{scope.row.IsRegister?'已注册':'未注册'}}</span> </template>
-					</el-table-column>
-					<el-table-column
-					prop="CreatedTime"
-					label="注册时间"
-					min-width="150"
-					align="center">
-						<template slot-scope="scope"> <span>{{scope.row.RegisterTime|formatTime}}</span> </template>
-					</el-table-column>
+					<!-- crm 14.7 -->
+					<template v-if="isUserYanXuanButtonShow">
+						<el-table-column
+						prop="IsRegister"
+						label="是否绑定"
+						width="90"
+						align="center">
+							<template slot-scope="scope">
+								<div style="text-align:left; display: flex;align-items: center;">
+									<img v-if="scope.row.MfyxIsBinding" style="width:16px;height:16px;margin-right: 5px;" src="~@/assets/img/icons/icon_1.png" alt="">
+									<img v-else style="width:16px;height:16px;margin-right: 5px;" src="~@/assets/img/icons/icon_2.png" alt="">
+									<span>{{scope.row.MfyxIsBinding?'已绑定':'未绑定'}}</span> 
+								</div>
+							</template>
+						</el-table-column>
+						<el-table-column
+						prop="CreatedTime"
+						label="绑定时间"
+						min-width="150"
+						align="center">
+							<template slot-scope="scope"> <span>{{scope.row.MfyxBindingTime}}</span> </template>
+						</el-table-column>
+					</template>
+					<template v-else>
+						<el-table-column
+						prop="IsRegister"
+						label="是否注册"
+						align="center">
+							<template slot-scope="scope"> <span>{{scope.row.IsRegister?'已注册':'未注册'}}</span> </template>
+						</el-table-column>
+						<el-table-column
+						prop="CreatedTime"
+						label="注册时间"
+						min-width="150"
+						align="center">
+							<template slot-scope="scope"> <span>{{scope.row.RegisterTime|formatTime}}</span> </template>
+						</el-table-column>
+					</template>
 					<el-table-column
 					prop="IsSubscribeHzyj"
 					label="是否关注公众号"
 					min-width="90"
 					align="center">
 						<template slot-scope="scope">
-							<div style="text-align:left">
+							<div style="text-align:left" v-if="RoleType !=='权益'">
 								<img v-if="scope.row.IsSubscribeHzyj==1" style="width:16px;height:16px" src="~@/assets/img/icons/icon_1.png" alt="">
 								<img v-else style="width:16px;height:16px" src="~@/assets/img/icons/icon_2.png" alt="">
 								<span>弘则研究</span>
@@ -278,7 +311,17 @@
 							</div>
 						</template>
 					</el-table-column>
+					<!-- crm 14.7 -->
+					<el-table-column
+					v-if="isUserYanXuanButtonShow"
+					prop="IsRegister"
+					label="互动次数"
+					align="center">
+						<template slot-scope="scope"> <span class="editsty" @click="MfyxInteractionNumHandler(scope.row)">{{scope.row.MfyxInteractionNum}}</span> </template>
+					</el-table-column>
+					<!-- crm 14.7 -->
 					<el-table-column
+					v-if="!isUserYanXuanButtonShow"
 					prop="ViewTotal"
 					label="累计阅读次数"
 					align="center">
@@ -292,23 +335,50 @@
 						<template slot-scope="scope"> <span>{{scope.row.ViewTotal?scope.row.LastViewTimeStr:''|formatTime}}</span> </template>
 					</el-table-column>
 					<el-table-column
+					v-if="!isUserYanXuanButtonShow"
 					label="研报统计"
 					align="center">
 						<template slot-scope="scope"> <span v-if="scope.row.ViewTotal!=0" class="editsty" @click="lookReport(scope.row)" :disabled="!isContractButtonShow" >点击查看</span></template>
 					</el-table-column>
 					<el-table-column
-						v-if="ficcform"
+						v-if="ficcform && !isUserYanXuanButtonShow"
 						prop="YbProductViewTotal"
 						label="其他统计"
 						min-width="110"
 						align="center">
 						<template slot-scope="scope"> <span :class="scope.row.YbProductViewTotal?'editsty':''" @click="lookReadInfo(scope.row)">{{scope.row.YbProductViewTotal||'0'}}</span> </template>
 					</el-table-column>
+					<!-- crm 14.7 -->
+					<template v-if="isUserYanXuanButtonShow">
+						<el-table-column
+						prop="IsRegister"
+						label="个人研选订阅权限"
+						width="140"
+						align="center">
+							<template slot-scope="scope"> 
+								<div style="text-align:left; display: flex;align-items: center;">
+									<img v-if="scope.row.MfyxStatus=='试用'" style="width:16px;height:16px;margin-right: 5px;" src="~@/assets/img/icons/icon_1.png" alt="">
+									<img v-else style="width:16px;height:16px;margin-right: 5px;" src="~@/assets/img/icons/icon_2.png" alt="">
+									<span>{{scope.row.MfyxStatus}}</span> 
+								</div>
+							</template>
+						</el-table-column>
+						<el-table-column
+						prop="CreatedTime"
+						label="研选服务期限"
+						min-width="150"
+						align="center">
+							<template slot-scope="scope"> <span>{{scope.row.MfyxStartDate}} -- {{scope.row.MfyxEndDate}}</span> </template>
+						</el-table-column>
+					</template>
 					<el-table-column label="操作" align="center" min-width="150">
 						<template slot-scope="scope"  v-if="isContractButtonShow">
 							<div class="contact-opt-box" style="color:#4099ef; font-size:14px;">
 								<span  class="editsty" @click="editContact(scope.row)">编辑</span>
 								<span class="editsty move" style="margin:0 5px;" @click="handleShowMove(scope.row)">移动</span>
+								<span style="margin-right:5px;" :class="scope.row.IsFollow==1?'deletesty':'editsty'"
+								@click="followContact(scope.row)"
+								>{{ scope.row.IsFollow==1?'取消关注':'关注' }}</span>
 								<span class="deletesty" @click.stop="delConcat(scope.row)">删除</span>
 								<!-- <block v-if="RoleType!='权益'&&ficcform&&['正式','试用','永续'].includes(ficcform.Status)">
 								<span 
@@ -329,6 +399,7 @@
 									style="color:#bbb"
 								>图表权限</span>
 								</block> -->
+								<p v-if="isUserYanXuanButtonShow" class="editsty" @click="isOpenMfyxStatusHandler(scope.row)">{{scope.row.MfyxStatus =='试用'?'关闭研选订阅试用':'开通研选订阅试用'}} </p>
 							</div>
 						</template>
 					</el-table-column>
@@ -481,7 +552,7 @@
 					<el-table-column align="center" label="邮箱">
 						<template slot-scope="scope">{{scope.row.Email||''}}</template>
 					</el-table-column>
-					<el-table-column align="center" label="是否决策人">
+					<el-table-column align="center" label="是否KP">
 						<template slot-scope="scope">{{scope.row.IsMaker==1?'是':'否'}}</template>
 					</el-table-column>
 					<el-table-column align="center" label="职位">
@@ -660,6 +731,7 @@ import ExportData from '../compontents/exportData.vue'
 import ProductReadInfo from '../compontents/ProductReadInfo.vue'
 import DeductDetailDlg from './components/deductDetailDlg.vue'
 import HistoryContract from '../compontents/historyContract.vue'
+import { async } from '@antv/x6/lib/registry/marker/async'
 export default {
 	name:'',
 	components: { Ctimeline, Contactdia, Readia, ElImageViewer, CpessionTable, pdf, chartAuthDialog, ExportData, CpessionTableEquity, ProductReadInfo, DeductDetailDlg, HistoryContract },
@@ -789,6 +861,7 @@ export default {
 
 			isShowResearchNumber:false,// 研选服务点数明细 弹框
 			isShowDlgType:'',
+			isUserYanXuanButtonShow:false,//是否显示研选的按钮以及表格
 		};
 	},
 	methods: {
@@ -980,6 +1053,7 @@ export default {
 				})
 			if(res.Ret!==200) return 
 			this.isContractButtonShow=res.Data.IsContractButtonShow
+			this.isUserYanXuanButtonShow = res.Data.IsUserYanXuanButtonShow
 			this.formatCustomDetail(res)
 		},
 		formatCustomDetail(res){
@@ -998,6 +1072,8 @@ export default {
 					if(res.Data.FiccItem){
 						let auth = [];
 						res.Data.FiccItem.PermissionList.forEach(item=> {
+							item.Items=item.Items||[]
+							item.CheckList=item.CheckList||[]
 							let obj = {
 								checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
 								isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
@@ -1259,7 +1335,29 @@ export default {
 			this.isAddContact = true;
 			this.diatit = '编辑联系人';
 		},
-		
+		// 关注与取消关注
+		followContact(row){
+			// console.log(row);
+			let isFollow = row.IsFollow==1
+			let confirmText = isFollow?'是否取消':'是否设为'
+			this.$confirm(`${confirmText}特别关注?`, "提示", {
+        type: "warning",
+      }).then(() => {
+				let params={
+					UserId:row.UserId,
+					CompanyId:row.CompanyId,
+					Type:isFollow?0:1
+				}
+				customInterence.concactFollow(params).then(res=>{
+					if(res.Ret == 200){
+						this.$message.success(isFollow?"取消成功":"关注成功")
+						this.getuserTable()
+					}
+				})
+
+			})
+			.catch(() => {});
+		},
 		// 删除联系人判断 试用、正式、永续、冻结状态下的客户 如只剩一个联系人不允许删除
 		/**
 		 * 1.如果是非管理员用户则直接根据数量判断
@@ -1538,6 +1636,48 @@ export default {
 		this.isShowDlgType = type
 		this.isShowResearchNumber =true
 	},
+	// 点击了互助详情数量
+	MfyxInteractionNumHandler(item){
+		const { href } = this.$router.resolve({
+        path:  "/mutualList" ,
+        query: {
+          id: item.UserId,
+          CompanyId: item.CompanyId,
+        },
+      });
+      window.open(href, "_blank");
+	},
+	// 开通严选
+    isOpenMfyxStatusHandler(item) {
+	 if(item.BusinessCardUrl){
+      let str = `${item.MfyxStatus == "试用" ? "关闭" : "开通"}`;
+      this.$confirm(`确定要${str}个人的研选订阅试用权限吗?`, `${str}试用`, {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          const res = await customInterence.yananxuanPermissionOpen({
+            UserId: item.UserId,
+            Type: item.MfyxStatus == "试用" ? 0 : 1,
+          });
+          if (res.Ret === 200) {
+            this.$message.success("操作成功");
+            this.getuserTable();
+          }
+        })
+	 } else {
+		this.$alert('该联系人尚未添加名片,请点击编辑,上传名片后再开通试用', '开通试用', {
+          confirmButtonText: '知道了',
+        });
+	 }
+    },
+	// 设置表格行的样式
+	setRowClass({row}){
+		if(row.NotRead && row.IsFollow==1){
+			return "not-read-seven-days"
+		}
+	}
 	},
 	mounted() {
 		this.getDetail();
@@ -1677,6 +1817,16 @@ export default {
 		align-items: center;
 		margin-bottom: 28px;
 	}
+	.name-follow-heart{
+		width:25px;
+		height: 15px;
+		position: absolute;
+		left: 0;
+    top: 0;
+	}
+	.not-read-seven-days{
+		background-color: #FFF8F8;
+	}
 }
 .customDetail_contract_dialog {
 	max-height: 810px;

+ 108 - 130
src/views/custom_manage/customList/customList.vue

@@ -24,6 +24,14 @@
 		<div class="customList_bot">
 			<div class="customList_top">
 				<el-row :span="24">
+					<el-select v-model="fromArea" placeholder="请选择所属区域" style="width:200px;marginRight:10px;marginBottom:8px;" clearable @change="changeFromArea">
+						<el-option
+							v-for="item in areaArr"
+							:key="item"
+							:label="item.name"
+							:value="item.name">
+						</el-option>
+					</el-select>
 					<el-select v-model="type" placeholder="请选择客户类型" style="width:200px;marginRight:10px;marginBottom:8px;" clearable v-if="Role=='finance'||Role=='admin'" @change="changeType">
 						<el-option
 							v-for="item in typeArr"
@@ -303,6 +311,8 @@
 								</el-select>
 							</template>
 						</p>
+						<!-- 共享客户显示咨询组销售 -->
+						<span v-if="scope.row.IsShare==1 && scope.row.ShareSeller">{{ scope.row.ShareSeller }}</span>
 					</template>
 					</el-table-column>
           <el-table-column
@@ -1032,7 +1042,7 @@ ShareListDialog},
 				BtnRemarkView: '备注',
 				BtnShare:'设置共享',
 				BtnCancelShare:'取消共享',
-				BtnServiceRecord:'服务记录',
+				BtnServiceRecord:'沟通记录',
 				BtnClose:'关闭',
 				BtnLoss:'转流失'
 			},	// 按钮命令列表
@@ -1277,7 +1287,8 @@ ShareListDialog},
 				PackageType: this.setmealSelect ? Number(this.setmealSelect) : 0,
 				TodoStatus:this.todoType,
 				SortByTodo:this.SortByTodo,
-				TryStage: this.act_trialTag
+				TryStage: this.act_trialTag,
+				RegionType:this.fromArea
 			}
 			customInterence.customList(params).then(res => {
 				if(res.Ret === 200) {
@@ -1588,7 +1599,7 @@ ShareListDialog},
 				this.lookRemarkHandle(query.data)
 			}else if(query.type=='设置共享' || query.type=='取消共享'){
 				this.shareSetting(query.data)
-			}else if(query.type=='服务记录'){
+			}else if(query.type=='沟通记录'){
 				this.handleShowShareRecode(query.data)
 			}else if(query.type=='关闭'){
 				this.openCloseReasonDialog(query.data)
@@ -1725,8 +1736,25 @@ ShareListDialog},
 					let authEquity =[] //权益
 					res.Data.ListRai ?	res.Data.ListRai.forEach(item=> {//权益
 						// 过滤没有权限的套餐
-						authEquity.push(item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId)))
+						let check_Auth = item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId))
+						check_Auth.map(item =>{
+						// 排序 以防合并问题
+							if(item.PermissionType==1){
+								//主观 找客观
+								authEquity.push(item)
+								let ob = check_Auth.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+								ob && authEquity.push(ob)
+							}else if(item.PermissionType==0){
+								authEquity.push(item)
+							}else{
+								// 客观
+								if(!authEquity.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+									authEquity.push(item)
+								}
+							}
+						})
 					}):''
+
 					this.lookAuthListEquity = authEquity.flat(Infinity) //权益
 				}
 			})
@@ -1857,6 +1885,8 @@ ShareListDialog},
 					// res.Data.List 有值为 ficc
 					// res.Data.ListRai 有值为 权益
 					res.Data.List ? res.Data.List.forEach(item=> {
+						item.Items=item.Items||[]
+						item.CheckList=item.CheckList||[]
 						let obj = {
 							checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
 							isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
@@ -1867,10 +1897,24 @@ ShareListDialog},
 						auth.push(obj)
 					}):
 					// 权益 RaiMerge 0不管 1合并 2拆分 所传入的数据结构不一样
+					/**权益权限ID
+					 * 科技-主观(20)-客观(37)
+					 * 消费-主观(21)-客观(38)
+					 * 医药-主观(22)-客观(39)
+					 * 智造-主观(19)-客观(36)
+					 * 策略(23)
+					 * 专家(29)
+					 * 固收(53)
+					 * 调研(54)
+					 * 路演服务(30)
+					 * 研选订阅(31)
+					 * 研选扣点包(52)
+					 */
 					res.Data.ListRai[0].RaiMerge==1?res.Data.ListRai.forEach(item=> { // 合并
+						let checkedLen = item.Items.filter(it => item.CheckList && item.CheckList.includes(it.ChartPermissionId)).length
 						let obj = {
-							checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
-							isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
+							checkAll:checkedLen === item.Items.length,
+							isIndeterminate:checkedLen > 0 && checkedLen < item.Items.length,
 							defaultAuth:item.CheckList,
 							...item,
 						}
@@ -1882,134 +1926,68 @@ ShareListDialog},
 							...item,
 						}	
 						// 组合所需的数据格式
-						obj.dataList=[
-							{
-								PermissionTypeName:'',
-								medicine:{
-									value:'医药',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==2
-								},
-								consumption:{
-									value:'消费',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==2
-								},
-								technology:{
-									value:'科技',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==2
-								},
-								smart:{
-									value:'智造',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==2
-								},
-								strategy:{
-									value:'策略'
-								},
-								experts:{
-									value:'专家'
-								},
-								roadshow:{
-									value:'路演服务'
-								},
-								choose:{
-									value:'买方研选'
+						let subjectivityIds=item.Items.filter(it => it.PermissionType==1).map(it => it.ChartPermissionId)//主观的ids
+						let subjectivityLength=subjectivityIds.length//有几个主观的id
+						let subjectivityCheckedLen = item.CheckList.filter(id => subjectivityIds.includes(id)).length//选中的有几个主观的id
+						let objectivityIds=item.Items.filter(it => it.PermissionType==2).map(it => it.ChartPermissionId)//客观的ids
+						let objectivityCheckedLen = item.CheckList.filter(id => objectivityIds.includes(id)).length//有几个客观的id
+						let objectivityLength=objectivityIds.length//选中的有几个客观的id
+						let arr = [{PermissionTypeName:''},
+											{PermissionTypeName:{
+												value:'主观',
+												isIndeterminate:subjectivityCheckedLen>0 && subjectivityCheckedLen<subjectivityLength,
+												isCheckAll:subjectivityCheckedLen == subjectivityLength,
+												isDisabled:subjectivityCheckedLen == subjectivityLength,
+												ids:subjectivityIds
+											}},
+											{PermissionTypeName:{
+												value:'客观',
+												isIndeterminate:objectivityCheckedLen > 0 && objectivityCheckedLen < objectivityLength,
+												isCheckAll:objectivityCheckedLen == objectivityLength,
+												isDisabled:objectivityCheckedLen == objectivityLength,
+												ids:objectivityIds
+											}}]
+						item.Items.map(cp =>{
+							if(cp.PermissionType==0){
+								// 没有主客观的权限
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									width:cp.PermissionName=='研选扣点包'?'100px':'',
+									merge:true
+								}
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'主观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[0].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[0].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[2].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[2].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[4].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[4].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[6].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[6].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'客观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[1].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[1].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[3].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[3].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[5].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[5].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[7].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[7].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+							}else if(cp.PermissionType==1){
+								// 找出对应的客观Id
+								let objectivity = item.Items.find(it => it.PermissionName == cp.PermissionName && it.PermissionType==2)
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									isIndeterminate:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==1,
+									isCheckAll:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length == 2,
+									isDisabled:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==2,
+									bothIds:[cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0]
+								}
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
+								}
+							}else{
+								// 分主客观的客观
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
 								}
 							}
-						]
-
+						})
+						obj.dataList=arr
 						auth.push(obj)
 					})
 					this.authList = auth;

+ 37 - 2
src/views/custom_manage/customList/customListEn.vue

@@ -8,6 +8,23 @@
         <el-button type="primary" @click="isUnDoStatisticShow=true" style="height: 40px;width: 110px;padding:0;text-align:center;line-height:40px;">未完成TO-DO</el-button>
       </div>
       <div>
+        <el-cascader
+            v-model="sales"
+            placeholder="请选择销售"
+            :options="salesArr"
+            :props="{
+                emitPath:false,
+                multiple: true,
+                label:'RealName',
+                children:'ChildrenList',
+                value:'AdminId'
+            }"
+            :show-all-levels="false"
+            collapse-tags
+            clearable
+            filterable
+            @change="getList('search')">
+        </el-cascader>
         <el-cascader
           v-model="varietyVal"
           :options="varietyOpt"
@@ -21,6 +38,7 @@
           }"
           placeholder="请选择阅读权限"
           @change="handleChangeVariety"
+          style="margin-left:20px"
         />
         <el-input 
           v-model="searchParams.Keywords" 
@@ -250,12 +268,17 @@ import reportVarietyEnSet from '@/components/reportVarietyEnSet.vue'
         showSetVariety:false,
         checkedVariety:[],
         activeItem:{},//当前编辑权限的客户信息
+
+        //销售筛选
+        sales:[],
+        salesArr:[]
       }
     },
     created(){
       this.getList()
       this.getSellerList()
       this.getENReportVarietyOpts()
+      this.getSale()
     },  
     methods: {
       handleSaveVariety(){
@@ -327,7 +350,11 @@ import reportVarietyEnSet from '@/components/reportVarietyEnSet.vue'
         this.varietyVal&&this.varietyVal.forEach(_e => {
           arr.push(_e[1])
         });
-        customInterence.getCustomListEn({...this.searchParams,EnPermissionIds:arr.join(',')}).then(res=>{
+        customInterence.getCustomListEn({
+            ...this.searchParams,
+            EnPermissionIds:arr.join(','),
+            Sellers:this.sales.join(',')
+        }).then(res=>{
           // console.log(res);
           if(res.Ret == 200){
             this.dataList = res.Data.List || []
@@ -508,7 +535,15 @@ import reportVarietyEnSet from '@/components/reportVarietyEnSet.vue'
           this.$message.success(`${Enabled===1?'禁用':'启用'}成功`)
           this.getList()
         })
-      }
+      },
+      /* 获取销售 */
+      getSale() {
+        customInterence.getSale({Status:0}).then(res => {
+            if(res.Ret === 200) {
+                this.salesArr = res.Data.List||[];
+            }
+        })
+      },
     },
   }
 </script>

+ 249 - 149
src/views/custom_manage/customList/customShareList.vue

@@ -3,23 +3,62 @@
 	<div class="customList_container" id="customList_container" ref="cusContainer">
 		<div class="customList_bot">
       <div class="customList_bot_search">
-        <div style="margin-bottom: 8px;" v-if="Role=='thisAdmin'">
+        <div style="margin-bottom: 8px;" v-if="!IsShareGroup">
           <el-select v-model="status" placeholder="请选择状态" @change="getTableData" style="width: 214px; margin-right: 20px;">
-            <el-option :label="item" :value="index" v-for="(item,index) in statusList" :key="index" ></el-option>
+            <el-option :label="item.label" :value="item.value" v-for="(item,index) in statusList" :key="index" ></el-option>
           </el-select>
-          <el-select v-model="sales" placeholder="请选择分配销售" style="width: 214px; margin-right: 20px;" 
+		  <el-cascader
+			v-model="originalSales"
+			placeholder="请选择原销售"
+			style="width:240px;marginRight:10px;marginBottom:8px;"
+			:options="originalSalesArr"
+			:props="defaultSalesProps"
+			:show-all-levels="false"
+			collapse-tags
+			clearable
+			filterable
+			@change="getTableData"
+			v-if="roleType!=='ficc_seller'"
+		  />
+          <!-- <el-select v-model="sales" placeholder="请选择分配销售" style="width: 214px; margin-right: 20px;" 
           clearable filterable multiple collapse-tags @change="getTableData">
             <el-option :label="item.RealName" :value="item.AdminId" v-for="item in salesArr" :key="item.AdminId" ></el-option>
-          </el-select>
+          </el-select> -->
+          <el-cascader
+            v-model="sales"
+            :options="salesArr"
+            :show-all-levels="false"
+            placeholder="请选择分配销售"
+            :props="{
+                multiple:true,
+                emitPath:false,
+                value:'AdminId',
+                label:'RealName',
+                children:'ChildrenList'
+            }"
+            @change="getTableData">
+          </el-cascader>
         </div>
         <div v-else>
             <el-button type="primary" @click="$router.push('/customCityList')">查看同城客户</el-button>
-        </div>
+			<el-cascader
+				v-model="originalSales"
+				placeholder="请选择原销售"
+				style="width:200px;marginRight:10px;marginBottom:8px;"
+				:options="originalSalesArr"
+				:props="defaultSalesProps"
+				:show-all-levels="false"
+				collapse-tags
+				clearable
+				filterable
+				@change="getTableData"
+			/>
+        </div> 
         <el-input 
           placeholder="客户名称/社会信用码/手机号码/邮箱"
           v-model="search_txt"
           style="max-width:531px;margin-bottom: 8px;"
-          @input="getTableData"
+          @input="handleCurrentChange(1)"
           clearable>
             <i slot="prefix" class="el-input__icon el-icon-search"></i>
           </el-input>
@@ -291,7 +330,8 @@
 								</span> -->
 								<div class="font-tool" style="display:flex;flex-direction:column;">
 									<span class="editsty" v-for="item in getToolBtnList(scope.row).slice(0,3)" :key="item.type" @click="itemclickHandle({type:item.type,data:scope.row})">
-										{{item.type==='分配销售'?scope.row.ShareSellerId?'修改销售':'分配销售':item.type}}
+										<!-- {{item.type==='分配销售'?scope.row.ShareSellerId?'修改销售':'分配销售':item.type}} -->
+										{{btnName(item,scope.row)}}
 									</span>
 								</div>
 								<el-dropdown size="medium" placement="bottom-start" @command="itemclickHandle" style="height: 16px;margin-left: 5px;" v-if="getToolBtnList(scope.row).length>3">
@@ -300,7 +340,7 @@
 										<el-dropdown-menu slot="dropdown">
 											<el-dropdown-item :command="{type:item.type,data:scope.row}" 
 											v-for="item in getToolBtnList(scope.row).slice(3)" :key="item.type">
-												<span>{{item.type}}</span>
+												<span>{{btnName(item,scope.row)}}</span>
 											</el-dropdown-item>
 										</el-dropdown-menu>
 									</span>
@@ -335,6 +375,7 @@
 		:close-on-click-modal="false"
 		:modal-append-to-body='false'
 		:title="assignedSellerTitle"
+		class="changeSaleDia"
 		@close="cancelAssign"
 		center
 		width="444px">
@@ -343,13 +384,27 @@
 					<span style="fontSize:16px;">{{assignform.CompanyName}}</span>
 				</el-form-item>
 				<el-form-item label="分配销售" prop="SellsId">
-					<el-select
+					<!-- <el-select
 						v-model="assignform.SellsId"
 						placeholder="请选择修改的销售"
 						style="width: 240px"
 						filterable>
 						<el-option :label="item.RealName" :value="item.AdminId" v-for="item in salesArr" :key="item.AdminId"></el-option>
-					</el-select>
+					</el-select> -->
+					<el-cascader
+						v-model="assignform.SellsId"
+						:options="salesArr"
+						:show-all-levels="false"
+						placeholder="请选择分配销售"
+						style="width: 240px"
+						:props="{
+							multiple:false,
+							emitPath:false,
+							value:'AdminId',
+							label:'RealName',
+							children:'ChildrenList'
+						}">
+					</el-cascader>
 				</el-form-item>
 			</el-form>	
 			<div style="display:flex;justify-content:center;margin:60px 0 35px;">
@@ -464,18 +519,21 @@ export default {
 			}else{
 				return 'thisSeller';
 			}
+		},
+		roleType(){
+			return localStorage.getItem('Role') || ''
 		}
 	},
 	data () {
 
-		this.statusList = ['全部','已分配','待分配']
+		this.statusList = [{label:'未共享',value:3},{label:'已分配',value:1},{label:'待分配',value:2}]
 		return {
 			adminId:localStorage.getItem('AdminId'),
 			sales:[],
 			salesArr:[],//销售
 			tableData:[],
 			isShowloadding:false,
-			status:2,
+			status:'',
 			search_txt:'',
 			total:0,
 			page_no:1,
@@ -504,8 +562,9 @@ export default {
 				BtnUpdate: '续约申请',
 				BtnAddAgreement: '补充协议',
 				BtnTryOut: '增开试用',
-				BtnServiceRecord:'服务记录',
-				BtnRemarkView:'备注'
+				BtnServiceRecord:'沟通记录',
+				BtnRemarkView:'备注',
+				BtnShare:'设置共享',
 			},	// 按钮命令列表
 			accumulativeFrequencyDlg:false,//路演业阅读的弹框
 			accumulativeFrequencyItem:{},
@@ -523,35 +582,73 @@ export default {
 			completeForm:{},
 			isAddTrial:false,
 			authList:[],
+
+			originalSales:'',
+			originalSalesArr:[],
+			defaultSalesProps:{
+				multiple: true,
+				label:'RealName',
+				children:'ChildrenList',
+				value:'AdminId'
+			},//销售级联配置
+
+			IsShareGroup:false,//是否为咨询组销售
 		};
 	},
 	methods: {
+		// 用于返回按钮名称
+		btnName(btnItem,row){
+			if(btnItem.code=='BtnShare') return row.IsShare===1?'取消共享':'设置共享'
+			if(btnItem.code=='BtnModifySeller') return row.ShareSellerId?'修改销售':'分配销售'
+			return btnItem.type
+		},
 		/* 获取表格 */
 		getTableData() {
 			this.isShowloadding = true;
+			// 处理销售筛选
+			let salesArr=[]
+			if(this.originalSales.length){
+				salesArr=this.originalSales.map(item=>{
+					return item[item.length-1]
+				})
+			}
+
 			let params = {
 				SortParam:this.sort_param,//自定义排序字段
 				SortType:this.sort_type,//排序方式
 				PageSize:this.pageSize,
 				CurrentIndex:this.page_no,
 				Keyword:this.search_txt,
-				ListParam:this.Role=='thisSeller'?1:this.status, // 销售只能看分配给自己的共享客户,即状态需要是已分配
-				SellerId:this.sales.join(',')
+				ListParam:this.status, 
+				SellerId:this.sales.join(','),
+				OriginalSellerId:salesArr.join(','),
 			}
 			customInterence.getShareCustomList(params).then(res => {
 				if(res.Ret === 200) {
 					this.total = res.Data.Paging.Totals || 0;
 					this.tableData = res.Data.List || [];
 					this.isShowloadding = false;
+					this.IsShareGroup=res.Data.IsShareGroup||false
+					this.status=res.Data.Status
 				}
 			})
 		},
-		/* 获取销售 */
+		/* 获取可分配销售 */
 		getSale() {
-			customInterence.salesShareList().then(res => {
-				console.log(res);
+			customInterence.getShareSaleList().then(res => {
 				if(res.Ret === 200) {
 					this.salesArr = res.Data|| []
+					//无子级的组无法选择
+					const filterNodes = (arr)=>{
+						arr.length &&arr.forEach((item) => {
+							item.ChildrenList && filterNodes(item.ChildrenList);
+							if (!Number(item.AdminId)&&!item.ChildrenList) {
+								item.disabled = true
+							}
+						})
+					}
+					filterNodes(this.salesArr)
+					console.log('salesArr',this.salesArr)
 				}
 			})
 		},
@@ -569,7 +666,7 @@ export default {
 			const {BtnItem} = data
 			for(const i in this.btnCommandList){
 				if(BtnItem[i]){
-					toolList.push({type:this.btnCommandList[i]})
+					toolList.push({type:this.btnCommandList[i],code:i+''})
 				}
 			}
 			return toolList
@@ -581,16 +678,27 @@ export default {
 				this.assignedSellerFun(query.data)
 			}else if(query.type=='查看权限'){
 				this.lookHandle(query.data)
-			}else if(query.type=='服务记录'){
+			}else if(query.type=='沟通记录'){
 				this.handleShowShareRecode(query.data)
 			}else if(query.type=='备注'){
 				this.handleShowRemark(query.data)
 			}else if(["续约申请","补充协议"].includes(query.type)){
 				this.handleOpenContractChoose(query.type,query.data)
-			}else if("增开试用"){
+			}else if(query.type=="增开试用"){
 				this.addTrialHandle(query.data)
+			}else if(query.type=='设置共享' || query.type=='取消共享'){
+				this.shareSetting(query.data)
 			}
 		},
+		// 设置/取消 共享
+		shareSetting(row){
+			customInterence.setCustomShare({CompanyId:row.CompanyId,IsShare:row.IsShare==0?1:0}).then(res=>{
+				if(res.Ret==200){
+					this.$message.success(row.IsShare==0?'设置共享成功':'取消共享成功')
+					this.getTableData()
+				}
+			})
+		},
 		/* 查看权限 */
 		lookHandle(item) {
 			this.lookTitle = item.CompanyName;
@@ -608,7 +716,23 @@ export default {
 					let authEquity =[] //权益
 					res.Data.ListRai ?	res.Data.ListRai.forEach(item=> {//权益
 						// 过滤没有权限的套餐
-						authEquity.push(item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId)))
+						let check_Auth = item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId))
+						check_Auth.map(item =>{
+						// 排序 以防合并问题
+							if(item.PermissionType==1){
+								//主观 找客观
+								authEquity.push(item)
+								let ob = check_Auth.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+								ob && authEquity.push(ob)
+							}else if(item.PermissionType==0){
+								authEquity.push(item)
+							}else{
+								// 客观
+								if(!authEquity.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+									authEquity.push(item)
+								}
+							}
+						})
 					}):''
 					this.lookAuthListEquity = authEquity.flat(Infinity) //权益
 				}
@@ -620,6 +744,9 @@ export default {
 				CompanyId:row.CompanyId,
 				SellsId:row.ShareSellerId==0?'':row.ShareSellerId+'',
 			}
+			//根据当前角色 获取salesArr
+			//若是ficc角色 取咨询组销售(一级)
+			//若是rai角色 去权益销售组(多级)
 			this.assignedSellerShow = true;
 		},
 		/* 页码改变 */
@@ -638,6 +765,10 @@ export default {
 		saveAssign() {
 			this.$refs.assignform.validate((valid) => {
 				if (valid) {
+					if(!Number(this.assignform.SellsId)){
+						this.$message.warning("请选择销售而不是分组!")
+						return
+					}
 					let param={
 						CompanyId:this.assignform.CompanyId,
 						SellsId:+this.assignform.SellsId
@@ -793,10 +924,24 @@ export default {
 						auth.push(obj)
 					}):
 					// 权益 RaiMerge 0不管 1合并 2拆分 所传入的数据结构不一样
+					/**权益权限ID
+					 * 科技-主观(20)-客观(37)
+					 * 消费-主观(21)-客观(38)
+					 * 医药-主观(22)-客观(39)
+					 * 智造-主观(19)-客观(36)
+					 * 策略(23)
+					 * 专家(29)
+					 * 固收(53)
+					 * 调研(54)
+					 * 路演服务(30)
+					 * 研选订阅(31)
+					 * 研选扣点包(52)
+					 */
 					res.Data.ListRai[0].RaiMerge==1?res.Data.ListRai.forEach(item=> { // 合并
+						let checkedLen = item.Items.filter(it => item.CheckList && item.CheckList.includes(it.ChartPermissionId)).length
 						let obj = {
-							checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
-							isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
+							checkAll:checkedLen === item.Items.length,
+							isIndeterminate:checkedLen > 0 && checkedLen < item.Items.length,
 							defaultAuth:item.CheckList,
 							...item,
 						}
@@ -808,134 +953,68 @@ export default {
 							...item,
 						}	
 						// 组合所需的数据格式
-						obj.dataList=[
-							{
-								PermissionTypeName:'',
-								medicine:{
-									value:'医药',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==2
-								},
-								consumption:{
-									value:'消费',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==2
-								},
-								technology:{
-									value:'科技',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==2
-								},
-								smart:{
-									value:'智造',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==2
-								},
-								strategy:{
-									value:'策略'
-								},
-								experts:{
-									value:'专家'
-								},
-								roadshow:{
-									value:'路演服务'
-								},
-								choose:{
-									value:'买方研选'
+						let subjectivityIds=item.Items.filter(it => it.PermissionType==1).map(it => it.ChartPermissionId)//主观的ids
+						let subjectivityLength=subjectivityIds.length//有几个主观的id
+						let subjectivityCheckedLen = item.CheckList.filter(id => subjectivityIds.includes(id)).length//选中的有几个主观的id
+						let objectivityIds=item.Items.filter(it => it.PermissionType==2).map(it => it.ChartPermissionId)//客观的ids
+						let objectivityCheckedLen = item.CheckList.filter(id => objectivityIds.includes(id)).length//有几个客观的id
+						let objectivityLength=objectivityIds.length//选中的有几个客观的id
+						let arr = [{PermissionTypeName:''},
+											{PermissionTypeName:{
+												value:'主观',
+												isIndeterminate:subjectivityCheckedLen>0 && subjectivityCheckedLen<subjectivityLength,
+												isCheckAll:subjectivityCheckedLen == subjectivityLength,
+												isDisabled:subjectivityCheckedLen == subjectivityLength,
+												ids:subjectivityIds
+											}},
+											{PermissionTypeName:{
+												value:'客观',
+												isIndeterminate:objectivityCheckedLen > 0 && objectivityCheckedLen < objectivityLength,
+												isCheckAll:objectivityCheckedLen == objectivityLength,
+												isDisabled:objectivityCheckedLen == objectivityLength,
+												ids:objectivityIds
+											}}]
+						item.Items.map(cp =>{
+							if(cp.PermissionType==0){
+								// 没有主客观的权限
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									width:cp.PermissionName=='研选扣点包'?'100px':'',
+									merge:true
+								}
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'主观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[0].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[0].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[2].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[2].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[4].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[4].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[6].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[6].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'客观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[1].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[1].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[3].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[3].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[5].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[5].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[7].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[7].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+							}else if(cp.PermissionType==1){
+								// 找出对应的客观Id
+								let objectivity = item.Items.find(it => it.PermissionName == cp.PermissionName && it.PermissionType==2)
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									isIndeterminate:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==1,
+									isCheckAll:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length == 2,
+									isDisabled:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==2,
+									bothIds:[cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0]
+								}
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
+								}
+							}else{
+								// 分主客观的客观
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
 								}
 							}
-						]
-
+						})
+						obj.dataList=arr
 						auth.push(obj)
 					})
 					this.authList = auth;
@@ -944,9 +1023,25 @@ export default {
 			this.addTryId = item.CompanyId;
 			this.isAddTrial = true;
 		},
+
+		/* 获取销售 */
+		getoriginalSale() {
+			/* let status=0;
+			customInterence.getSale({"Status":status}).then(res => {
+				if(res.Ret === 200) {
+					this.originalSalesArr = res.Data.List||[];
+				}
+			}) */
+			customInterence.getShareSale().then(res=>{
+				if(res.Ret === 200){
+					this.originalSalesArr = res.Data.List||[]
+				}
+			})
+		},
 	},
 	created() {
 		this.getSale()
+		this.getoriginalSale()
 		this.getTableData()
 	}
 }
@@ -961,6 +1056,11 @@ export default {
 			}
 		}
 	}
+	.changeSaleDia{
+		.el-cascader .el-input{
+			width: 100%;
+		}
+	}
 </style>
 <style lang='scss' scoped>
 	.ficc-package {

+ 20 - 12
src/views/custom_manage/customList/editCustom.vue

@@ -45,16 +45,18 @@
 						<el-form-item label="所属区域" prop="RegionType" style="width:26%">
 							<span style="color:#333;font-size: 15px;">{{basicform.RegionType}}</span>
 						</el-form-item>
-						<el-form-item label="客户地址" prop="City" style="width:33%">
-							<!-- <v-distpicker :province-source="province_sorce"
-                :city-source="city_sorce" 
-								:province="basicform.Province"
-								:city="basicform.City"
-								hide-area
-								@selected="selectRegion"
-								@province="provinceChange"
-								:disabled="!canEidtBtns.BaseInfoEdit">
-							</v-distpicker> -->
+						<el-form-item v-if="basicform.RegionType==='海外'" label="所属国家" prop="Nation" style="width:33%"
+							:rules="[{required:true,message: '所属国家不能为空', trigger: 'change' }]">
+							<el-select v-model="basicform.Nation" placeholder="请选择" filterable style="width:80%;">
+								<el-option :label="item.cnName" :value="item.cnName" v-for="item in countryData" :key="item.code" >
+									<div style="display: flex;justify-content: space-between;">
+										<span>{{ item.cnName }}</span>
+										<span style="color: #8492a6; font-size: 13px">{{ item.code }}</span>
+									</div>
+								</el-option>
+							</el-select>
+						</el-form-item>
+						<el-form-item v-else label="客户地址" prop="City" style="width:33%">
 							<search-dist-picker 
 								:provinceInfo="basicform.Province"
 								:cityInfo="basicform.City"
@@ -271,7 +273,7 @@
 					</el-table-column>
 					<el-table-column
 					prop="IsMaker"
-					label="决策人"
+					label="是否KP"
 					align="center">
 						<template slot-scope="scope"> <span>{{scope.row.IsMaker==1?'是':'否'}}</span> </template>
 					</el-table-column>
@@ -467,6 +469,7 @@ import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
 // import CpessionTableEquity from '../compontents/CpessionTableEquity.vue'
 import autocomplete from "@/components/autocomplete.vue";
 import searchDistPicker from '@/components/searchDistPicker.vue';
+import country from "@/utils/countryData"
 
 export default {
 	name:'',
@@ -503,6 +506,7 @@ export default {
 	data () {
 /*     this.province_sorce=province_sorce
     this.city_sorce=city_sorce */
+		this.countryData = country
 		return {
 			isCheck: false,
 			canEidtBtns:{},
@@ -737,6 +741,8 @@ export default {
 					if(res.Data.FiccItem){
 						let auth = [];
 						res.Data.FiccItem.PermissionList.forEach(item=> {
+							item.Items=item.Items||[]
+							item.CheckList=item.CheckList||[]
 							let obj = {
 								checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
 								isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
@@ -744,6 +750,7 @@ export default {
 							}
 							auth.push(obj)
 						})
+						console.log(auth);
 						this.ficcform={...this.ficcform,authList:auth}
 					}
 					// 处理权益权限列表格式
@@ -1076,7 +1083,8 @@ export default {
 				Province:this.basicform.Province,
 				CompanyName:this.basicform.CompanyName,
 				CreditCode:this.basicform.CreditCode,
-				Products:params_arr
+				Products:params_arr,
+				Nation:this.basicform.RegionType==='海外'?this.basicform.Nation:''
 			}
 			
 			customInterence.customEdit(params).then(res => {

+ 5 - 1
src/views/custom_manage/customList/editCustomEn.vue

@@ -280,7 +280,11 @@ import reportVarietyEnSet from '@/components/reportVarietyEnSet.vue'
       editSubmit(){
         this.$refs.editForm.validate(valid=>{
           if(valid){
-            customInterence.addCustomEn({...this.editForm,EnPermissions:this.$refs.varietyIns.checkedItems||[]}).then(res=>{
+            customInterence.addCustomEn({
+                ...this.editForm,
+                EnPermissions:this.$refs.varietyIns.checkedItems||[],
+                Nation:this.editForm.Country
+            }).then(res=>{
               if(res.Ret == 200){
                 let messageEle=this.$message.success(this.$route.path == '/addCustomEn'?'添加客户成功':'编辑客户成功')
                 setTimeout(()=>{

+ 9 - 2
src/views/custom_manage/customList/mixins/customlistMixin.js

@@ -29,7 +29,9 @@ export default {
             isShareRecodeDialogShow:false,//控制服务记录弹窗
             allowEdit:true,//是否允许编辑服务记录
 			isCloseCustomDialogShow:false,
-			closeReason:''
+			closeReason:'',
+			fromArea:'',
+			areaArr:[{name:'国内'},{name:'海外'}],
 		}
 	},
 
@@ -112,6 +114,11 @@ export default {
 				})
 				
 			}).catch(()=>{})
-		}
+		},
+		/* 筛选所属区域 */
+		changeFromArea(){
+			this.page_no = 1;
+			this.getTableData()
+		},
 	}
 }

+ 98 - 0
src/views/custom_manage/customList/mixins/quartersMixin.js

@@ -0,0 +1,98 @@
+export default {
+  data() {
+    return {
+      selectedQuarters: [],
+      quarters: this.generateQuarters(),
+      showAlert: true,
+    };
+  },
+  computed: {
+    selectedDateRange() {
+      if (this.selectedQuarters.length) {
+        const sortedQuarters = [...this.selectedQuarters].sort();
+        const startDate = this.quarterToDateRange(sortedQuarters[0]).split(" ~ ")[0];
+        const endDate = this.quarterToDateRange(sortedQuarters[this.selectedQuarters.length - 1]).split(" ~ ")[1];
+        return `${startDate} ~ ${endDate}`;
+      }
+      return "";
+    },
+  },
+  methods: {
+    generateQuarters() {
+      const currentDate = new Date();
+      const currentYear = currentDate.getFullYear();
+      let currentQuarter = Math.floor(currentDate.getMonth() / 3) + 1;
+
+      let quarters = [];
+
+      for (let i = 3; i >= 0; i--) {
+        // 包括当前季度和前三个季度
+        let year = currentYear;
+        let quarter = currentQuarter - i;
+
+        while (quarter <= 0) {
+          year--; // 上一年
+          quarter += 4; // 季度数增加
+        }
+
+        quarters.push({
+          label: `${year}Q${quarter}`,
+          value: `${year}Q${quarter}`,
+        });
+      }
+
+      return quarters;
+    },
+
+    isDisabled(quarter) {
+      if (this.selectedQuarters.length === 0) return false;
+      const sortedSelected = [...this.selectedQuarters].sort();
+      const firstIndex = this.quarters.findIndex((q) => q.value === sortedSelected[0]);
+      const lastIndex = this.quarters.findIndex((q) => q.value === sortedSelected[sortedSelected.length - 1]);
+
+      const currentIndex = this.quarters.findIndex((q) => q.value === quarter.value);
+
+      return currentIndex < firstIndex - 1 || currentIndex > lastIndex + 1;
+    },
+
+    quarterToDateRange(quarterLabel) {
+      const [year, q] = quarterLabel.split("Q");
+
+      switch (parseInt(q)) {
+        case 1:
+          return `${year}-01-01 ~ ${year}-03-31`;
+        case 2:
+          return `${year}-04-01 ~ ${year}-06-30`;
+        case 3:
+          return `${year}-07-01 ~ ${year}-09-30`;
+        case 4:
+          return `${year}-10-01 ~ ${year}-12-31`;
+      }
+    },
+    isConsecutiveSelection() {
+      const sortedSelectedIndexes = this.selectedQuarters.map((sq) => this.quarters.findIndex((aq) => aq.value === sq)).sort((a, b) => a - b);
+      for (let i = 0; i < sortedSelectedIndexes.length - 1; i++) {
+        if (sortedSelectedIndexes[i + 1] - sortedSelectedIndexes[i] !== 1) {
+          return false;
+        }
+      }
+
+      return true;
+    },
+  },
+
+  watch: {
+    selectedQuarters(newValue, oldValue) {
+      if (!newValue.length) return;
+      if (!this.isConsecutiveSelection() && this.showAlert) {
+        this.showAlert = false;
+        this.selectedQuarters.pop();
+        this.$message.error("只能选择相邻的季度");
+        this.$nextTick(() => {
+          this.selectedQuarters.pop();
+          this.showAlert = true;
+        });
+      }
+    },
+  },
+};

+ 13 - 2
src/views/custom_manage/customList/regionCustomDetail.vue

@@ -10,14 +10,14 @@
                 @cell-mouse-enter="getCustomDetail"
             >
                 <el-table-column
-                    v-for="item in tableColumns"
+                    v-for="item in tableColumnsComputed"
                     :key="item.label"
                     :label="item.label"
                     :width="item.widthsty"
                     :min-width="item.minwidthsty"
                     :prop="item.key"
                     align="center"
-                    :sortable="['viewTotal','RoadShowTotal','LastViewTime','ExpireDay','createTime'].includes(item.key) ? 'custom' : false"
+                    :sortable="['viewTotal','RoadShowTotal','LastViewTime','ExpireDay'].includes(item.key) ? 'custom' : false"
                 >
                     <template slot-scope="{row}">
 
@@ -155,6 +155,10 @@ export default {
             label: '所属销售',
             key: 'SellerName',
           },
+          {
+            label: '分配销售',
+            key: 'ShareSeller',
+          },
           {
             label: '客户状态',
             key: 'Status',
@@ -198,6 +202,13 @@ export default {
       showMore(){
         const AdminName = localStorage.getItem('AdminName')
         return AdminName==='ydlou'
+      },
+      tableColumnsComputed(){
+        if(this.title.includes('正式')){
+          return this.tableColumns
+        }else{
+          return this.tableColumns.filter(item => item.label!='分配销售')
+        }
       }
     },
     methods: {

+ 38 - 11
src/views/custom_manage/customList/updateServe.vue

@@ -111,14 +111,14 @@
 								权限设置
 							</label>
 							<template  v-if="companyInfo.CompanyType=='权益' || isRoleType== '权益'">
-								<raiPermissionbox v-for="item in authList" :key="item.ClassifyName" :data="item" :formData="dataForm"
+								<raiPermissionbox  ref="raiPermissionboxRef" v-for="item in authList" :key="item.ClassifyName" :data="item" :formData="dataForm"
 								:hasNoChild="hasNoChild"></raiPermissionbox>
 							</template>
 							<ul v-else class="menu_lists" style="width:100%">
 								<li v-for="item in authList" :key="item.ClassifyName" class="menu_item">
-									<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="($route.path=='/updateCustom'&&item.ClassifyName === '宏观经济') || item.disabled" @change="handleCheckAll(item)" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
+									<el-checkbox :indeterminate="item.isIndeterminate" v-model="item.checkAll" :disabled="setSelectPerDisabled(item)" @change="handleCheckAll(item,'auth')" style="marginRight:30px;fontWeight:bold;minWidth:90px;">{{item.ClassifyName+':'}}</el-checkbox>
 									<el-checkbox-group v-model="item.CheckList" @change="handleChecked(item)">
-										<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.disabled||($route.path=='/updateCustom'&&list.ChartPermissionId==1)">{{list.PermissionName}}</el-checkbox>
+										<el-checkbox v-for="list in item.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item" :disabled="list.disabled||($route.path=='/updateCustom'&&list.IsPublic==1)">{{list.PermissionName}}</el-checkbox>
 									</el-checkbox-group>
 								</li>
 							</ul>
@@ -433,7 +433,7 @@ export default {
 						/* 处理数据把复选框 拆分成三个*/
 						res.Data.Item.PermissionList.length&&res.Data.Item.PermissionList.forEach(item => {
 						let arr = item.Items.filter(key=> [22,21,20,19,23,30].includes(key.ChartPermissionId))
-						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032].includes(key.ChartPermissionId))
+						let ItemsPrivate = item.Items.filter(key=> [29,31,52,20031,20032,53,54].includes(key.ChartPermissionId))
 						let ItemsUp = item.Items.filter(key=> key.PermissionName.includes('升级'))
 						let ItemsBig = item.Items.filter(key=> key.ChartPermissionId==0)
 							let obj = {
@@ -496,7 +496,9 @@ export default {
 		// },
 		/* 获取基本权限信息 */
 		getAuthBasic() {
-			customInterence.authList().then(res => {
+			customInterence.authList({
+				IsShowYanXuanKouDian:true,
+			}).then(res => {
 				if(res.Ret === 200) {
 					let newArr = [];
 					if(this.companyInfo.CompanyType == '权益' || this.isRoleType== '权益') {
@@ -507,7 +509,7 @@ export default {
 						/* 处理数据把复选框 拆分成三个*/
 						res.Data.List.length&&res.Data.List.forEach(item => {
 						let arr = item.Items.filter(key=> [22,21,20,19,23,30].includes(key.ChartPermissionId))
-						let ItemsPrivate = item.Items.filter(key=> [29,31,20031,20032].includes(key.ChartPermissionId))
+						let ItemsPrivate = item.Items.filter(key=> [29,31,52,20031,20032,53,54].includes(key.ChartPermissionId))
 						let ItemsUp = item.Items.filter(key=> key.PermissionName.includes('升级'))
 						let ItemsBig = item.Items.filter(key=> key.ChartPermissionId==0)
 							let obj = {
@@ -521,6 +523,8 @@ export default {
 						})
 					}else {
 					res.Data.List.length&&res.Data.List.forEach(item => {
+						item.Items=item.Items||[]
+						const temarr=item.Items?item.Items.filter(_e=>_e.IsPublic==1):[]
 						item.Items=item.Items.map(item2=>{
 							return{
 								...item2,
@@ -528,8 +532,8 @@ export default {
 							}
 						})
 						let obj = {
-							checkAll:false,
-							isIndeterminate:item.ClassifyName === '宏观经济'?true:false,
+							checkAll:item.Items.length>0?temarr.length==item.Items.length:false,
+							isIndeterminate:item.Items.length>0?temarr.length==item.Items.length?false:item.Items.some(_e=>_e.IsPublic==1):false,
 							...item,
 						}
 						newArr.push(obj)
@@ -539,6 +543,11 @@ export default {
 				}
 			})
 		},
+		setSelectPerDisabled(data){
+			const arr=data.Items?data.Items.filter(_e=>_e.IsPublic==1):[]
+			return (this.$route.path=='/updateCustom'&&arr.length==data.Items.length) || data.disabled
+			//($route.path=='/updateCustom'&&item.IsPublic==1) || item.disabled
+		},
 		/* 获取历史签约 */
 		getDealList() {
 			customInterence.historydeal({
@@ -715,7 +724,9 @@ export default {
 							this.$message.warning('同行业有重叠的合同期限,请核实后再提交')
 							return false
 						}
-						
+						const hasFiftyTwo = checkArr.flat(2).includes(52);
+						const hasMinusSignVal = this.companyInfo.CompanyType === '权益' ? this.$refs.raiPermissionboxRef[0].minus_sign_val : 0	
+						if(hasFiftyTwo && !hasMinusSignVal) return this.$message.error('请输入研选扣点数')
 						let PermissionIds = checkArr.flat(2).join(',');
 						let params = {
 							CompanyId:this.companyInfo.CompanyId,
@@ -730,7 +741,8 @@ export default {
 							PayMethod:this.dataForm.payway,
 							PermissionIds:PermissionIds,
 							PackageType:Number(this.dataForm.setmeal),
-							RaiPackageType:this.dataForm.qyBigServeCheck||0
+							RaiPackageType:this.dataForm.qyBigServeCheck||0,
+							Points:hasMinusSignVal||0
 						}
 
 						console.log(params);
@@ -752,7 +764,22 @@ export default {
 			this.$router.push({path:`/${this.$route.meta.pathFrom}`})
 		},
 		/* 选择全选或取消全选 */
-		handleCheckAll(item) {
+		handleCheckAll(item,type) {
+			if(type=='auth'){
+				//获取公有的id合集
+				let publicIds=[]
+
+				
+				let ids = item.Items.map(item =>{
+					if(item.IsPublic==1){
+						publicIds.push(item.ChartPermissionId)
+					}
+					return item.ChartPermissionId
+				})
+				item.CheckList = item.checkAll ? ids : publicIds;	
+				item.isIndeterminate = publicIds.length>0&&!item.checkAll?true:false;
+				return
+			}
 			// 取到所有的子菜单id
 			let ids = item.Items.map(item =>{
 				return item.ChartPermissionId

+ 94 - 130
src/views/custom_manage/customSearch.vue

@@ -861,7 +861,23 @@ export default {
 					let authEquity =[] //权益
 					res.Data.ListRai ?	res.Data.ListRai.forEach(item=> {//权益
 						// 过滤没有权限的套餐
-						authEquity.push(item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId)))
+						let check_Auth = item.Items.filter(it => item.CheckList.includes(it.ChartPermissionId))
+						check_Auth.map(item =>{
+						// 排序 以防合并问题
+							if(item.PermissionType==1){
+								//主观 找客观
+								authEquity.push(item)
+								let ob = check_Auth.find(it => it.PermissionName == item.PermissionName && it.PermissionType!=1)
+								ob && authEquity.push(ob)
+							}else if(item.PermissionType==0){
+								authEquity.push(item)
+							}else{
+								// 客观
+								if(!authEquity.find(t => t.ChartPermissionId == item.ChartPermissionId)){
+									authEquity.push(item)
+								}
+							}
+						})
 					}):''
 					this.lookAuthListEquity = authEquity.flat(Infinity) //权益
 					this.isPermissionTypeShow = this.lookAuthListEquity.some(item => !item.IsMerge)
@@ -1341,10 +1357,24 @@ export default {
 						auth.push(obj)
 					}):
 					// 权益 RaiMerge 0不管 1合并 2拆分 所传入的数据结构不一样
-					res.Data.ListRai[0].RaiMerge==1?res.Data.ListRai.forEach(item=> { // 合并
+						/**权益权限ID
+						 * 科技-主观(20)-客观(37)
+						 * 消费-主观(21)-客观(38)
+						 * 医药-主观(22)-客观(39)
+						 * 智造-主观(19)-客观(36)
+						 * 策略(23)
+						 * 专家(29)
+						 * 固收(53)
+						 * 调研(54)
+						 * 路演服务(30)
+						 * 研选订阅(31)
+						 * 研选扣点包(52)
+						*/
+					 	res.Data.ListRai[0].RaiMerge==1?res.Data.ListRai.forEach(item=> { // 合并
+						let checkedLen = item.Items.filter(it => item.CheckList && item.CheckList.includes(it.ChartPermissionId)).length
 						let obj = {
-							checkAll:item.CheckList&&item.CheckList.length===item.Items.length?true:false,
-							isIndeterminate:item.CheckList&&item.CheckList.length>0 && item.CheckList.length<item.Items.length,
+							checkAll:checkedLen === item.Items.length,
+							isIndeterminate:checkedLen > 0 && checkedLen < item.Items.length,
 							defaultAuth:item.CheckList,
 							...item,
 						}
@@ -1352,138 +1382,72 @@ export default {
 					}): res.Data.ListRai.forEach(item=> { // 拆分
 						let obj = {
 							defaultAuth:item.CheckList,
-							customType:'权益',
+							customType:item.ClassifyName,
 							...item,
 						}	
 						// 组合所需的数据格式
-						obj.dataList=[
-							{
-								PermissionTypeName:'',
-								medicine:{
-									value:'医药',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[1].ChartPermissionId].includes(id)).length ==2
-								},
-								consumption:{
-									value:'消费',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[2].ChartPermissionId,obj.Items[3].ChartPermissionId].includes(id)).length ==2
-								},
-								technology:{
-									value:'科技',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[4].ChartPermissionId,obj.Items[5].ChartPermissionId].includes(id)).length ==2
-								},
-								smart:{
-									value:'智造',
-									isIndeterminate:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==1,
-									isCheckAll:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 2,
-									isDisabled:item.CheckList.filter(id => [obj.Items[6].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==2
-								},
-								strategy:{
-									value:'策略'
-								},
-								experts:{
-									value:'专家'
-								},
-								roadshow:{
-									value:'路演服务'
-								},
-								choose:{
-									value:'买方研选'
+						let subjectivityIds=item.Items.filter(it => it.PermissionType==1).map(it => it.ChartPermissionId)//主观的ids
+						let subjectivityLength=subjectivityIds.length//有几个主观的id
+						let subjectivityCheckedLen = item.CheckList.filter(id => subjectivityIds.includes(id)).length//选中的有几个主观的id
+						let objectivityIds=item.Items.filter(it => it.PermissionType==2).map(it => it.ChartPermissionId)//客观的ids
+						let objectivityCheckedLen = item.CheckList.filter(id => objectivityIds.includes(id)).length//有几个客观的id
+						let objectivityLength=objectivityIds.length//选中的有几个客观的id
+						let arr = [{PermissionTypeName:''},
+											{PermissionTypeName:{
+												value:'主观',
+												isIndeterminate:subjectivityCheckedLen>0 && subjectivityCheckedLen<subjectivityLength,
+												isCheckAll:subjectivityCheckedLen == subjectivityLength,
+												isDisabled:subjectivityCheckedLen == subjectivityLength,
+												ids:subjectivityIds
+											}},
+											{PermissionTypeName:{
+												value:'客观',
+												isIndeterminate:objectivityCheckedLen > 0 && objectivityCheckedLen < objectivityLength,
+												isCheckAll:objectivityCheckedLen == objectivityLength,
+												isDisabled:objectivityCheckedLen == objectivityLength,
+												ids:objectivityIds
+											}}]
+						item.Items.map(cp =>{
+							if(cp.PermissionType==0){
+								// 没有主客观的权限
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									width:cp.PermissionName=='研选扣点包'?'100px':'',
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'主观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[0].ChartPermissionId,obj.Items[2].ChartPermissionId,
-										obj.Items[4].ChartPermissionId,obj.Items[6].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[0].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[0].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[2].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[2].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[4].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[4].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[6].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[6].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
 								}
-							},
-							{
-								PermissionTypeName:{
-									value:'客观',
-									isIndeterminate:[1,2,3].includes(item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length),
-									isCheckAll:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length == 4,
-									isDisabled:item.CheckList.filter(id => [obj.Items[1].ChartPermissionId,obj.Items[3].ChartPermissionId,
-										obj.Items[5].ChartPermissionId,obj.Items[7].ChartPermissionId].includes(id)).length ==4
-								},
-								medicine:{
-									value:obj.Items[1].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[1].ChartPermissionId)
-								},
-								consumption:{
-									value:obj.Items[3].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[3].ChartPermissionId)
-								},
-								technology:{
-									value:obj.Items[5].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[5].ChartPermissionId)
-								},
-								smart:{
-									value:obj.Items[7].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[7].ChartPermissionId)
-								},
-								strategy:{
-									value:obj.Items[8].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[8].ChartPermissionId)
-								},
-								experts:{
-									value:obj.Items[9].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[9].ChartPermissionId)
-								},
-								roadshow:{
-									value:obj.Items[10].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[10].ChartPermissionId)
-								},
-								choose:{
-									value:obj.Items[11].ChartPermissionId,
-									isDisabled:item.CheckList.includes(obj.Items[11].ChartPermissionId)
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId),
+									merge:true
+								}
+							}else if(cp.PermissionType==1){
+								// 找出对应的客观Id
+								let objectivity = item.Items.find(it => it.PermissionName == cp.PermissionName && it.PermissionType==2)
+								arr[0][cp.PermissionName]={
+									value:cp.PermissionName,
+									isIndeterminate:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==1,
+									isCheckAll:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length == 2,
+									isDisabled:item.CheckList.filter(id => [cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0].includes(id)).length ==2,
+									bothIds:[cp.ChartPermissionId,objectivity?objectivity.ChartPermissionId:0]
+								}
+								arr[1][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
+								}
+							}else{
+								// 分主客观的客观
+								arr[2][cp.PermissionName]={
+									value:cp.ChartPermissionId,
+									isDisabled:item.CheckList.includes(cp.ChartPermissionId)
 								}
 							}
-						]
-
+						})
+						obj.dataList=arr
 						auth.push(obj)
 					})
 					this.authList = auth;
@@ -1553,7 +1517,7 @@ export default {
 		btnList(btnItem,part){
 			const allBtnList=[]
 			for (const key in btnItem) {
-				btnItem[key]&&key!=='BtnClose' && allBtnList.push(key)
+				btnItem[key]&&key!=='BtnClose'&&key!=='BtnShare' && allBtnList.push(key)
 			}
 			if(part==='front'){
 				// 返回前三个按钮

+ 90 - 0
src/views/custom_manage/overseasList/components/roadShowsDialog.vue

@@ -0,0 +1,90 @@
+<template>
+    <el-dialog custom-class="total-click-dialog"
+        :title="`${customData.CompanyName}-路演详情`"
+        :visible.sync="isRoadDetailShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="$emit('close')"
+        width="842px"
+        v-dialogDrag
+        center
+    >
+        <div class="table-wrap" v-loading="tableLoading">
+            <p>累计路演次数:{{dataList.length}}</p>
+            <el-table :data="dataList"  height="300" border @sort-change="clickNumSortChange" v-loading="showLoading" element-loading-text="加载中">
+                <el-table-column  v-for="column in columns" :key="column.key" :label="column.label" align="center" :prop="column.key">
+                    <template slot-scope="{row}">
+                    {{row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import { customInterence } from "@/api/api.js";
+export default {
+    props:{
+        isRoadDetailShow:{
+            type:Boolean,
+            default:false
+        },
+        customData:{
+            type:Object,
+            default:{}
+        },
+    },
+    data() {
+        return {
+            columns:[{
+                label:"路演日期",
+                key:'RoadShowTime'
+            },{
+                label:"路演形式",
+                key:'RoadshowType'
+            },{
+                label:"路演平台/路演城市",
+                key:'RoadshowPlatform'
+            },{
+                label:"研究员",
+                key:'Researchers'
+            },{
+                label:"对接销售",
+                key:'SysUserRealName'
+            }],
+            dataList:[],
+            tableLoading:false,
+        };
+    },
+    watch:{
+        isRoadDetailShow(newVal){
+            if(newVal){
+                this.getTableData()
+            }else{
+                this.dataList=[]
+            }
+        }
+    },
+    methods: {
+        getTableData(){
+            this.tableLoading = true
+            customInterence.roadShowList({
+                CompanyId:this.customData.CompanyId
+            }).then(res=>{
+                this.tableLoading = false
+                if(res.Ret!==200) return 
+                this.dataList = res.Data||[]
+            })
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+.table-wrap{
+    .el-table{
+        margin:20px 0 30px 0;
+    }
+}
+</style>

+ 173 - 0
src/views/custom_manage/overseasList/components/selectSaleDialog.vue

@@ -0,0 +1,173 @@
+<template>
+    <el-dialog custom-class="select-sale-dialog"
+        title="选择销售"
+        :visible.sync="isSelectSaleShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="$emit('close')"
+        width="692px"
+        v-dialogDrag
+        center
+    >
+        <div class="dialog-content-wrap" v-loading="dialogLoading" :element-loading-text="loadingText">
+            <el-cascader v-model="sales" 
+                ref="saleCascader"
+                placeholder="请选择销售"
+                :key="saleCascaderKey"
+                :options="AllSalesArr" 
+                :props="{
+                    value: 'AdminId',
+                    label: 'RealName',
+                    children: 'ChildrenList',
+                    multiple: true,
+                    emitPath:false,
+                }"
+                collapse-tags :show-all-levels="false"
+                clearable filterable
+                @change="changeSelect"
+                ></el-cascader>
+            <p style="margin-top:20px;">已选用户</p>
+            <div class="selected-wrap">
+                <div class="select-item" v-for="item in selectList" :key="item.value">
+                    <span>{{ item.label }}</span>
+                    <i class="el-icon-error" @click="cancelSelect(item)"></i>
+                </div>
+            </div>
+        </div>
+        <div class="btn-wrap">
+            <el-button type="primary" plain @click="$emit('close')">取消</el-button>
+            <el-button type="primary" @click="choosedSales" :disabled="dialogLoading">确认</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+
+import {dataAuthInterface , customInterence } from '@/api/api.js'
+export default {
+    props:{
+        isSelectSaleShow:{
+            type:Boolean,
+            default:false
+        },
+        selectedSalesArr:{
+            type:Array,
+            default:[]
+        }
+    },
+    data() {
+        return {
+            sales:[],
+            selectList:[],
+            saleCascaderKey:0,
+            AllSalesArr:[],
+            dialogLoading:false,
+            loadingText:''
+        };
+    },
+    watch:{
+        isSelectSaleShow(newval){
+            if(newval){
+                this.getSalesList()
+            }else{
+                this.loadingText = ''
+            }
+        }
+    },
+    methods: {
+        //获取销售列表
+        //由于中英文客户的销售列表不一致,获取系统全部人员列表作为销售列表
+        getSalesList(){
+            this.dialogLoading = true
+            customInterence.getSale({Status:0}).then(res=>{
+                this.dialogLoading = false
+                if(res.Ret!==200) {
+                    this.AllSalesArr = []
+                    this.sales=[]
+                    this.selectList=[]
+                    return 
+                }
+                this.AllSalesArr = res.Data?(res.Data.List||[]):[]
+                //有选择的指标,回显
+                if(this.selectedSalesArr.length){
+                    this.sales = this.selectedSalesArr.map(i=>(i.SellerId))
+                    this.$nextTick(()=>{
+                        this.changeSelect()
+                    })
+                }
+            })
+        },
+        changeSelect(){
+            const nodes = this.$refs.saleCascader.getCheckedNodes()
+            this.selectList = nodes.filter(i=>{
+                /* if(i.value<10000&&!i.children.length){
+                    return i
+                } */
+                if(!Number.isNaN(Number(i.value))&&!i.children.length){
+                    return i
+                }
+            })
+        },
+        cancelSelect(item){
+            const index = this.selectList.findIndex(i=>i.value==item.value)
+            index!==-1&&this.selectList.splice(index,1)
+            const saleIndex = this.sales.findIndex(i=>i==item.value)
+            saleIndex!==-1&&this.sales.splice(saleIndex,1)
+            this.saleCascaderKey++
+        },
+        //对比上次选择的销售,保存
+        choosedSales(){
+            let AddSellerIdArr = []
+            let DelSellerIdArr = []
+            const oldSales = this.selectedSalesArr.map(i=>(Number(i.SellerId)))
+            const tempSales = this.sales.map(i=>(Number(i)))
+            oldSales.forEach(i=>{
+                if(tempSales.includes(i)){
+                    AddSellerIdArr.push(i)
+                }else{
+                    DelSellerIdArr.push(i)
+                }
+            })
+            AddSellerIdArr = Array.from(new Set([...AddSellerIdArr,...tempSales]))
+            this.loadingText = '保存销售中,请勿关闭弹窗...'
+            this.dialogLoading = true
+            this.$emit('saveSales',{AddSellerIdArr,DelSellerIdArr,sales:this.selectList})
+        }
+    },
+};
+</script>
+
+<style lang="scss">
+.select-sale-dialog{
+    .el-cascader{
+        width:100%;
+        .el-input{
+            width:100% !important;
+        }
+    }
+    .selected-wrap{
+        margin:20px 0;
+        display: flex;
+        flex-wrap: wrap;
+        gap:10px;
+        .select-item{
+            cursor: pointer;
+            padding: 5px 10px;
+            background-color: #f0f2f5;
+            border-radius: 4px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            i{
+                margin-left: 5px;
+                color: #909399;
+                font-size: 14px;
+            }
+        }
+    }
+    .btn-wrap{
+        text-align: center;
+        padding-bottom: 20px;
+    }
+}
+</style>

+ 147 - 0
src/views/custom_manage/overseasList/components/totalClicksDialog.vue

@@ -0,0 +1,147 @@
+<template>
+    <el-dialog custom-class="total-click-dialog"
+        :title="`${customData.CompanyName}-点击量详情`"
+        :visible.sync="isTotalClickShow"
+        :close-on-click-modal="false"
+        :modal-append-to-body="false"
+        @close="$emit('close')"
+        width="842px"
+        v-dialogDrag
+        center
+    >
+        <div class="table-wrap" v-loading="tableLoading">
+            <el-table :data="dataList" border @sort-change="clickNumSortChange" v-loading="showLoading" element-loading-text="加载中">
+                <el-table-column  v-for="column in columns" :key="column.key" 
+                    :label="column.label" align="center" :prop="column.key"
+                    :sortable="column.sortable?'custom':false">
+                    <template slot-scope="{row}">
+                    {{row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+            <el-pagination 
+                layout="total,prev,pager,next,jumper" 
+                background 
+                :current-page="tableParams.CurrentIndex"
+                @current-change="handlePageChange"
+                :page-size="tableParams.PageSize"
+                :total="total"
+                style="text-align: right;margin-top:20px;margin-bottom:20px;"/>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+import { customInterence } from '@/api/api.js'
+export default {
+    props:{
+        customData:{
+            type:Object,
+            default:{}
+        },
+        isTotalClickShow:{
+            type:Boolean,
+            default:false
+        }
+    },
+    watch:{
+        isTotalClickShow(newVal){
+            if(newVal){
+                this.tableParams = {
+                    CurrentIndex:1,
+                    PageSize:5,
+                    SortParam:'',
+                    SortType:'',
+                }
+                this.getTableData()
+            }else{
+                this.dataList = []
+            }
+        }
+    },
+    data() {
+        return {
+            dataList:[],
+            columns:[{
+                label:"联系人姓名",
+                key:"UserName"
+            },{
+                label:"手机号/邮箱",
+                key:"Email"
+            },{
+                label:"点击次数",
+                key:"ViewTotal",
+                sortable:true
+            },{
+                label:"最近点击时间",
+                key:"LastViewTime",
+                sortable:true
+            }],
+            tableParams:{
+                CurrentIndex:1,
+                PageSize:5,
+                SortParam:'',
+                SortType:'',
+            },
+            total:0,
+            tableLoading:false,
+        };
+    },
+    methods: {
+        getTableData(){
+            this.tableLoading = true
+            if(this.customData.Source===1){
+                customInterence.customEnHitNumber({
+                    ...this.tableParams,
+                    CompanyId:this.customData.CompanyId - 10000000,
+                    EmailId:this.customData.CompanyId - 10000000,
+                }).then(res=>{
+                    this.tableLoading = false
+                    if(res.Ret!==200) return 
+                    this.dataList = res.Data.List || []
+                    this.total = res.Data.Paging.Totals
+                    this.dataList = this.dataList.map(i=>{
+                        return {
+                            ...i,
+                            Email:(i.Mobile?i.Mobile:i.Email)||''
+                        }
+                    })
+                })
+            }else{
+                customInterence.getZNCustomClickList({
+                    ...this.tableParams,
+                    CompanyId:this.customData.CompanyId
+                }).then(res=>{
+                    this.tableLoading = false
+                    if(res.Ret!==200) return 
+                    this.dataList = res.Data.List||[]
+                    this.total = res.Data.Paging.Totals
+                    this.dataList = this.dataList.map(i=>{
+                        return {
+                            ...i,
+                            Email:(i.Mobile?i.Mobile:i.Email)||''
+                        }
+                    })
+                })
+            }
+        },
+        handlePageChange(page){
+            this.tableParams.CurrentIndex = page
+            this.getTableData()
+        },
+        clickNumSortChange({prop,order}){
+            const map = {
+                'ViewTotal':1,
+                'LastViewTime':2
+            }
+            this.tableParams.SortParam = order?map[prop]:''
+            this.tableParams.SortType = order=="ascending"?2:1
+            this.handlePageChange(1)
+        }
+    },
+};
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 594 - 0
src/views/custom_manage/overseasList/overseasCustomList.vue

@@ -0,0 +1,594 @@
+<template>
+    <div class="overseas-custom-list-wrap">
+        <div class="top-box" v-show="isDataSelectBtnShow">
+            <div class="switch-box">
+                <el-radio-group v-model="pageSelect" >
+                    <el-radio-button :label="1">海外客户</el-radio-button>
+                    <el-radio-button :label="2">已隐藏客户</el-radio-button>
+                </el-radio-group>
+            </div>
+            <div class="select-box">
+                <el-select placeholder="请选择销售" v-if="pageSelect===1"
+                    v-model="tableParams.SellerId" 
+                    @change="handlePageChange(1)"
+                    multiple collapse-tags clearable>
+                    <el-option
+                        v-for="item in salesArr"
+                        :key="item.SellerId"
+                        :label="item.RealName"
+                        :value="item.SellerId"
+                    />
+                </el-select>
+                <el-input 
+                    prefix-icon="el-icon-search" 
+                    placeholder="客户名称/社会信用码/手机号码/邮箱" 
+                    style="width:317px;" clearable
+                    v-model="tableParams.Keywords"
+                    @input="handlePageChange(1)"
+                />
+            </div>
+        </div>
+        <div class="data-box" v-loading="tableLoading">
+            <div class="data-select-box">
+                <div class="table-select-box">
+                    <ul class="status-box">
+                        <li v-for="item in tableTabs" :key="item.Status"
+                            :class="['tab',{'act':tableParams.CompanyStatus === item.CompanyStatus}]"
+                            @click="changeStatus(item)"
+                        >
+                            {{`${item.CompanyStatus}(${item.Total})`}}
+                        </li>
+                    </ul>
+                    <!-- 试用小分类 -->
+                    <ul class="try-status-box" v-if="tableParams.CompanyStatus==='试用'">
+                        <li v-for="item in tryTabs" :key="item.TryStatus"
+                            :class="['trial-item',{'act':tableParams.tagStatusSelect === item.TryStatus}]" 
+                            @click="changeTagStatus(item)"
+                        >
+                            {{item.TryStatus+'('+item.Total+')'}}
+                        </li>
+                    </ul>
+                </div>
+                <!-- 管理员-选择销售 -->
+                <div class="data-select" v-if="isDataSelectBtnShow&&this.salesArr.length">
+                    <el-button v-if="pageSelect===1" type="text" @click="isSelectSaleShow=true"><i class="el-icon-plus"  style="font-weight: bold;margin-right: 5px;"/>选择销售</el-button>
+                </div>
+                <!--非管理员 筛选-->
+                <div class="data-select" v-if="!isDataSelectBtnShow" style="flex:1;">
+                    <div class="select-box" style="display: flex;justify-content: flex-end;gap: 30px;">
+                        <el-select placeholder="请选择销售" v-if="pageSelect===1"
+                            v-model="tableParams.SellerId" 
+                            @change="handlePageChange(1)"
+                            multiple collapse-tags clearable>
+                            <el-option
+                                v-for="item in salesArr"
+                                :key="item.SellerId"
+                                :label="item.RealName"
+                                :value="item.SellerId"
+                            />
+                        </el-select>
+                        <el-input 
+                            prefix-icon="el-icon-search" 
+                            placeholder="客户名称/社会信用码/手机号码/邮箱" 
+                            style="width:317px;" clearable
+                            v-model="tableParams.Keywords"
+                            @input="handlePageChange(1)"
+                        />
+                    </div>
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table
+                    ref="overseasTable"
+                    :data="tableData"
+                    border
+                    @sort-change="handleSortChange"
+                >
+                    <el-table-column 
+                        align="center"
+                        v-for="item in columns" :key="item.key"
+                        :prop="item.key" :label="item.label"
+                        :min-width="item.minWidth"
+                        :sortable="item.sortable?'custom':false"
+                    >
+                        <template slot-scope="{row}">
+                            <!-- 客户名称 -->
+                            <div v-if="item.key==='CompanyName'" class="editor" @click="toCustomDetail(row)">{{row[item.key]}}</div>
+                            <!-- 状态 -->
+                            <div  v-else-if="item.key==='OverseasStatus'" class="status-box">
+                                    <span>{{row[item.key]}}</span>
+                                    <div class="select" v-if="row[item.key]==='试用'">
+                                        <el-select 
+                                            v-model="row.OverseasLabel"
+                                            size="mini" 
+                                            style="width: 50px" 
+                                            placeholder=""
+                                            @change="handleChangeTryStatus(row)"
+                                        >
+                                            <el-option
+                                                v-for="item in trialTags"
+                                                :key="item.value"
+                                                :label="item.label"
+                                                :value="item.value">
+                                            </el-option>
+                                        </el-select>
+                                    </div>
+                            </div>
+                            <span v-else-if="item.key==='ViewTotal'" :class="{'editor':row[item.key]>0}" @click="handleDialogShow('click',row)">{{row[item.key]}}</span>
+                            <span v-else-if="item.key==='RoadShowTotal'" :class="{'editor':row[item.key]>0}" @click="handleDialogShow('road',row)">{{row[item.key]}}</span>
+                            <span v-else-if="['LastViewTime','CreateTime'].includes(item.key)">
+                                {{
+                                    row[item.key].slice(0,10)==='0000-00-00'?'':row[item.key].slice(0,10)
+                                }}
+                            </span>
+                            <span v-else>{{row[item.key]}}</span>
+                        </template>
+                    </el-table-column>
+                    <!-- 操作列 -->
+                    <el-table-column label="操作" align="center">
+                        <template slot-scope="{row}">
+                            <el-button type="text" v-if="pageSelect===1&&row.IsHide===0" @click="handleSetCustomHide(row)">隐藏</el-button>
+                            <el-button type="text" v-if="pageSelect===2&&row.IsHide===1" @click="handleSetCustomHide(row)">取消隐藏</el-button>
+                            <!--英文客户且状态为试用-->
+                            <el-button type="text" v-if="pageSelect===1&&row.Source===1&&row.OverseasStatus==='试用'" @click="handleSetCustomStatus(row,'change')">转正式</el-button>
+                            <!--英文客户且状态为正式且可以重置-->
+                            <el-button type="text" v-if="pageSelect===1&&row.Source===1&&row.OverseasStatus==='正式'&&row.ResetBtn===2" @click="handleSetCustomStatus(row,'reset')">重置</el-button>
+                            
+                            <el-button type="text" @click="handleShowShareRecode(row)">沟通记录</el-button>
+                        </template>
+                    </el-table-column>
+                    <template slot="empty">
+                        <!-- 管理员展示按钮 -->
+                        <div class="data-select" v-if="isDataSelectBtnShow&&!salesArr.length">
+                            <el-button type="text" @click="isSelectSaleShow=true"><i class="el-icon-plus"  style="font-weight: bold;margin-right: 5px;" />选择销售</el-button>
+                        </div>
+                        <!-- 非管理员显示暂无数据 -->
+                        <div v-else>暂无数据</div>
+                    </template>
+                    
+                </el-table>
+                <el-pagination 
+                    layout="total,prev,pager,next,jumper" 
+                    background 
+                    :current-page="currentPage"
+                    @current-change="(page)=>handlePageChange(page,'sort')"
+                    :page-size="pageSize"
+                    :total="total"
+                    style="text-align: right;margin-top:20px"/>
+            </div>
+        </div>
+        <!-- 选择销售弹窗 -->
+        <SelectSaleDialog 
+            ref="selectDialog"
+            :isSelectSaleShow="isSelectSaleShow"
+            :selectedSalesArr="salesArr"
+            @close="isSelectSaleShow=false"
+            @saveSales="saveSales"
+        />
+        <!-- 累计点击量弹窗 -->
+        <TotalClicksDialog 
+            :isTotalClickShow="isTotalClickShow"
+            :customData="customData"
+            @close="isTotalClickShow = false"
+        />
+        <!-- 路演数量弹窗 -->
+        <RoadShowsDialog 
+            :isRoadDetailShow="isRoadDetailShow"
+            :customData="customData"
+            @close="isRoadDetailShow = false"
+        />
+
+         <!-- 服务记录弹窗 -->
+        <ShareListDialog
+            :isShareRecodeDialogShow.sync="isShareRecodeDialogShow"
+            :customInfo="customInfo"
+            :allowEdit="allowEdit"
+            @close="()=>{isShareRecodeDialogShow=false;}"
+        />
+    </div>
+</template>
+
+<script>
+import { overseasCustomInterence} from '@/api/modules/overseasCustom.js'
+import SelectSaleDialog from './components/selectSaleDialog';
+import TotalClicksDialog from './components/totalClicksDialog';
+import RoadShowsDialog from './components/roadShowsDialog';
+import ShareListDialog from '../customList/components/shareListDialog.vue';
+import mixin from '../customList/mixins/customlistMixin';
+const tryArr = ['','未分类','推进','跟踪','预备']
+export default {
+    mixins: [ mixin ],
+    components: { SelectSaleDialog, TotalClicksDialog, RoadShowsDialog,ShareListDialog },
+    data() {
+        return {
+            pageSelect: 1,
+            salesArr: [],
+            tableTabs: [],
+            tryTabs: [],
+            trialTags: [{ label: '推进', value: 2 },
+                { label: '跟踪', value: 3 },
+                { label: '预备', value: 4 },
+                { label: '未分类', value: 1 },
+            ],
+            columns: [{
+                    label: "客户名称",
+                    key: 'CompanyName'
+                }, {
+                    label: "国家",
+                    key: 'Nation'
+                }, {
+                    label: "销售",
+                    key: 'SellerName'
+                }, {
+                    label: "状态",
+                    key: 'OverseasStatus'
+                }, {
+                    label: "累计点击量",
+                    key: 'ViewTotal',
+                    sortable: true
+                }, {
+                    label: "路演数量",
+                    key: 'RoadShowTotal',
+                    sortable: true
+                }, {
+                    label: "最近阅读时间",
+                    key: 'LastViewTime',
+                    sortable: true
+                }, {
+                    label: "创建时间",
+                    key: 'CreateTime',
+                    sortable: true
+                }],
+            tableParams:{
+                Keywords:'',
+                SortField:'ViewTotal',//排序字段
+                SortDesc:1,//排序方式
+                SellerId:'',//选择的销售
+                CompanyStatus:'全部',//客户状态
+                tagStatusSelect:'全部',//客户的试用状态
+                tryStatusSelect:0,//客户试用状态对应的OverseasLabel
+            },
+            tableData: [],
+            currentPage: 1,
+            pageSize: 10,
+            total: 0,
+            isSelectSaleShow: false, //选择销售弹窗
+            isTotalClickShow:false, //累计点击量弹窗
+            isRoadDetailShow:false, //路演详情弹窗
+            customData:{},//选择的客户信息
+
+            tableLoading:false,
+
+        };
+    },
+    computed: {
+        Role() {
+            return localStorage.Role || '';
+        },
+        isDataSelectBtnShow() {
+            return (this.Role === 'admin' || this.Role === 'ficc_admin');
+        }
+    },
+    watch:{
+        pageSelect(newval){
+            //清空筛选项
+            this.tableParams={
+                Keywords:'',
+                SortField:'ViewTotal',
+                SortDesc:1,
+                SellerId:'',
+                CompanyStatus:'全部',
+                tagStatusSelect:'全部',
+                tryStatusSelect:0,
+            }
+            this.$refs.overseasTable&&this.$refs.overseasTable.clearSort()
+            this.handlePageChange(1,'static')
+        }
+    },
+    methods: {
+        //获取已保存选择的销售
+        getSavedSales(){
+            overseasCustomInterence.getSavedSalesList().then(res=>{
+                if(res.Ret!==200) return 
+                this.salesArr = res.Data||[]
+            })
+        },
+        //保存选择的销售
+        saveSales({AddSellerIdArr,DelSellerIdArr,sales}){
+            overseasCustomInterence.saveSelectedSales({
+                AddSellerIdArr,DelSellerIdArr
+            }).then(res=>{
+                this.$refs.selectDialog&&(this.$refs.selectDialog.dialogLoading = false)
+                if(res.Ret!==200) return
+                this.$message.success("选择销售成功")
+                this.tableParams = {
+                    Keywords:'',
+                    SortField:'ViewTotal',
+                    SortDesc:1,
+                    SellerId:'',
+                    CompanyStatus:'全部',
+                    tagStatusSelect:'全部',
+                    tryStatusSelect:0,
+                }
+                this.salesArr = sales.map(i=>({SellerId:i.value,RealName:i.label}))
+                this.handlePageChange(1)
+                this.isSelectSaleShow = false
+            })
+        },
+        //客户列表
+        async getTableData(type) {
+            this.tableLoading = true
+            const {Keywords,SortField,SortDesc,SellerId,CompanyStatus,tryStatusSelect} = this.tableParams
+            //重新请求统计数据
+            if(type!=='sort'){
+                await this.getStatisticData()
+                if(CompanyStatus==='试用'){
+                    await this.getTryStatisticData()
+                }
+            }
+            overseasCustomInterence.getCustomList({
+                PageSize: this.pageSize,
+                CurrentIndex: this.currentPage,
+                Keywords,CompanyStatus,
+                SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+                OverseasLabel:tryStatusSelect,
+                CustomType:this.pageSelect,
+                SortField,SortDesc,
+            }).then(res=>{
+                this.tableLoading = false
+                if(res.Ret!==200) return 
+                if(!res.Data) return 
+                /* //客户状态
+                this.tableTabs = res.Data.StatisticsData||[]
+                //手动添加一个全部
+                let total = this.tableTabs.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+                this.tableTabs.unshift({CompanyStatus:'全部',Total:total})
+                //客户试用状态
+                this.tryTabs = res.Data.OverseasLabelData||[]
+                this.tryTabs = this.tryTabs.map(tab=>({
+                    TryStatus:tryArr[tab.OverseasLabel],
+                    Total:tab.Total,
+                    OverseasLabel:tab.OverseasLabel}))
+                //手动添加一个全部
+                let tryTotal = this.tryTabs.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+                this.tryTabs.unshift({TryStatus:'全部',Total:tryTotal,OverseasLabel:0}) */
+                //客户列表
+                this.tableData = res.Data.List||[]
+                this.total = res.Data.Paging.Totals||0
+            })
+        },
+        //获取客户统计数据
+        async getStatisticData(){
+            const {Keywords,SellerId,CompanyStatus} = this.tableParams
+            const statisticRes = await overseasCustomInterence.getStatisticData({
+                CustomType:this.pageSelect,
+                SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+                Keywords
+            })
+            if(statisticRes.Ret!==200) return 
+            //客户状态
+            this.tableTabs = statisticRes.Data||[]
+            //手动添加一个全部
+            let total = this.tableTabs.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+            this.tableTabs.unshift({CompanyStatus:'全部',Total:total})
+        },
+        //客户试用状态统计数据
+        async getTryStatisticData(){
+            const {Keywords,SellerId} = this.tableParams
+            const statisticTryRes = await overseasCustomInterence.overseasCustomInterence({
+                CustomType:this.pageSelect,
+                SellerId:(Array.isArray(SellerId)?SellerId.join(','):'')+'',
+                Keywords
+            })
+            if(statisticTryRes.Ret!==200) return 
+            //客户试用状态
+            this.tryTabs = statisticTryRes.Data||[]
+            this.tryTabs = this.tryTabs.map(tab=>({
+                TryStatus:tryArr[tab.OverseasLabel],
+                Total:tab.Total,
+                OverseasLabel:tab.OverseasLabel}))
+            //手动添加一个全部
+            let tryTotal = this.tryTabs.map(i=>(i.Total)).reduce((acc,curr)=>acc+curr,0)
+            this.tryTabs.unshift({TryStatus:'全部',Total:tryTotal,OverseasLabel:0})
+        },
+        //切换客户状态
+        changeStatus(item) {
+            this.tableParams.CompanyStatus = item.CompanyStatus;
+            if(item.CompanyStatus!=='试用'){
+                this.tableParams.tagStatusSelect = '全部';
+                this.tableParams.tryStatusSelect = 0
+            }
+            this.handlePageChange(1);
+        },
+        //切换客户试用状态
+        changeTagStatus(item) {
+            this.tableParams.tagStatusSelect = item.TryStatus;
+            this.tableParams.tryStatusSelect = item.OverseasLabel
+            this.handlePageChange(1);
+        },
+        //列表排序
+        handleSortChange({prop,order}) {
+            this.tableParams.SortDesc = order==='ascending'?2:1
+            this.tableParams.SortField = order?prop:'ViewTotal'
+            this.handlePageChange(1,'sort')
+         },
+        //切换页码
+        handlePageChange(page,type) {
+            this.currentPage = page;
+            this.getTableData(type);
+        },
+        //跳转至客户详情
+        toCustomDetail(data) { 
+            const path = data.Source===1?'/detailCustomEn':'/customDetail'
+            const query = {
+                ...data.Source===1?{
+                    companyId:data.CompanyId - 10000000
+                }:{
+                    id:data.CompanyId
+                },
+                from:'overseas'
+            }
+            const href = this.$router.resolve({path,query}).href
+            window.open(href,"_blank")
+        },
+        //设置客户的试用状态
+        handleChangeTryStatus(data) {
+            const { OverseasLabel, CompanyId } = data;
+            overseasCustomInterence.setCustomTryStatus({
+                CompanyId,OverseasLabel
+            }).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success("设置成功")
+                this.getTableData()
+            })
+        },
+        //打开累计点击量/路演数量弹窗
+        handleDialogShow(type,data){
+            this.customData = data
+            if(type==='click'){
+                if(!data.ViewTotal>0) return
+                this.isTotalClickShow = true
+            }else{
+                if(!data.RoadShowTotal>0) return
+                this.isRoadDetailShow = true
+            }
+        },
+        //设置客户隐藏/取消隐藏
+        handleSetCustomHide({CompanyId}){
+            overseasCustomInterence.setCustomHide({CompanyId}).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success(`设置${this.pageSelect===1?'隐藏':'取消隐藏'}成功`)
+                this.handlePageChange(1)
+            })
+        },
+        handleSetCustomStatus({CompanyId},type){
+            overseasCustomInterence.setCustomStatus({CompanyId}).then(res=>{
+                if(res.Ret!==200) return 
+                this.$message.success(`${type==='reset'?'重置':'转正式'}成功`)
+                this.handlePageChange(1)
+            })
+        },
+    },
+    mounted() {
+        this.getSavedSales()
+        this.getTableData('static');
+    },
+};
+</script>
+
+<style lang="scss">
+.overseas-custom-list-wrap{
+    .el-input--mini {
+        .el-input__inner{
+            padding: 0 6px !important;
+            height: 24px;
+            line-height: 24px;
+            color: #409EFF;
+            background: #ECF5FF;
+            border-color: #409EFF;
+            text-align: center;
+        }
+        .el-input__inner {
+            border-color: #E4E7ED;
+        }
+        .el-input__suffix {
+            display: none;
+        }
+    }
+}
+</style>
+<style scoped lang="scss">
+.overseas-custom-list-wrap{
+    box-sizing: border-box;
+    .top-box,.data-box{
+        box-sizing: border-box;
+        padding:30px;
+        background-color: #fff;
+    }
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 20px;
+    }
+    .data-box{
+        .data-select-box{
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            ul{
+                display: flex;
+                align-items: center;
+            }
+            .status-box{
+                .tab {
+                    width: 129px;
+                    height: 22px;
+                    line-height: 22px;
+                    text-align: center;
+                    font-size: 14px;
+                    border-right:1px solid #707070;
+                    cursor: pointer;
+                    transition-delay: 0.05s;
+                    &:hover {
+                        color: #409EFF;
+                    }
+                    &.act {
+                        // padding: 9px 24px;
+                        height: 40px;
+                        line-height: 40px;
+                        background: #409EFF;
+                        border-radius: 4px;
+                        color: #fff;
+                        border-color: #409EFF;
+                        transform: scale(1.014);
+                    }
+                    &:last-child {
+                        border: none;
+                    }
+                }
+            }
+            .try-status-box{
+                padding: 20px 0 0 30px;
+                .trial-item {
+                    cursor: pointer;
+                    margin-right: 30px;
+                    &:hover {
+                        color: #409EFF;
+                    }
+                    &.act {
+                        color: #409EFF;
+                        position: relative;
+                        &::after {
+                            content: "";
+                            width: 100%;
+                            height: 2px;
+                            position: absolute;
+                            bottom: -10px;
+                            left: 50%;
+                            transform: translateX(-50%);
+                            background: #409EFF;
+                        }
+                    }
+                }
+            }
+        }
+        .table-box{
+            margin-top:20px;
+            .status-box{
+                display: flex;
+                justify-content: center;
+                .el-select{
+                    margin-left: 10px;
+                }
+            }
+            .editor{
+                color:#409EFF;
+                cursor: pointer;
+                &:hover{
+                    text-decoration: underline;
+                }
+            }
+        }
+    }
+}
+</style>

+ 680 - 0
src/views/custom_manage/overseasList/overseasCustomRoadshow.vue

@@ -0,0 +1,680 @@
+<template>
+  <div class="overseas-custom-roadshow-box">
+    <div class="tab-box">
+      <el-button type="primary" :plain="roadshowTab==1?false:true" class="tab-item" @click="tabChange(1)">客户维度</el-button>
+      <el-button type="primary" :plain="roadshowTab==2?false:true" class="tab-item" @click="tabChange(2)">销售维度</el-button>
+      <el-button type="primary" :plain="roadshowTab==3?false:true" class="tab-item" @click="tabChange(3)">研究员维度</el-button>
+    </div>
+    <template v-if="roadshowTab==1">
+      <div class="top-wrapper">
+        <div class="left-select">
+        <el-cascader
+            v-model="sales"
+            :options="salesOptions"
+            :show-all-levels="false"
+            :props="{
+                expandTrigger: 'hover',
+                children: 'ChildrenList',
+                emitPath: false,
+                label:'RealName',
+                value:'AdminId',
+                multiple:true
+            }"
+            collapse-tags
+            filterable
+            clearable
+            placeholder="请选择销售"
+            @change="pageChange(1)"
+        />
+        <el-cascader
+            v-model="researchers"
+            :options="researchersOptions"
+            :show-all-levels="false"
+            :props="{
+                expandTrigger: 'hover',
+                children: 'ResearcherList',
+                emitPath: false,
+                label:'RealName',
+                value:'AdminId',
+                multiple:true
+            }"
+            collapse-tags
+            filterable
+            clearable
+            placeholder="请选择研究员"
+            @change="pageChange(1)"
+        />
+
+        <el-select 
+          v-model="status" 
+          placeholder="请选择客户状态"
+          @change="pageChange(1)"
+          multiple 
+          collapse-tags 
+          clearable
+        >
+            <el-option
+                v-for="item in statusOptions"
+                :key="item.val"
+                :label="item.label"
+                :value="item.val"
+            />
+        </el-select>
+
+        <date-picker 
+						v-model="date" 
+						type="date" 
+						range
+						value-type="format"
+						placeholder="请选择路演日期" 
+						@change="pageChange(1)" 
+						style="width:200px;margin-right:10px;margin-bottom:8px;"
+        />
+
+        </div>
+        <el-input 
+            prefix-icon="el-icon-search" 
+            placeholder="客户名称" 
+            style="width:317px;" clearable
+            v-model="searchWord"
+            @input="pageChange(1)"
+        />
+      </div>
+      <div class="cont-wrapper">
+        <el-table
+          ref="tableRef"
+          :data="tableData"
+          :loading="tabeLoading"
+          border
+          @sort-change="handleSortChange"
+        >
+          <el-table-column 
+              align="center"
+              v-for="item in columns" :key="item.key"
+              :prop="item.key" :label="item.label"
+              :min-width="item.minWidth"
+              :sortable="item.sortable?'custom':false"
+          >
+            <template slot-scope="{row}">
+                <!-- 客户名称 -->
+                <div v-if="item.key==='CompanyName'" class="editor" @click="toCustomDetail(row)">{{row[item.key]}}</div>
+
+                <span v-else>{{row[item.key]}}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <!-- 页数选择器 -->
+        <m-page
+          :page_no="currentIndex"
+          :pageSize="pageSize"
+          :total="total"
+          style="position: absolute;right: 50px;bottom: 50px;"
+          @handleCurrentChange="pageChange"
+        />
+      </div>
+    </template>
+    <template v-else-if="roadshowTab==2">
+      <ul class="date-tab-box">
+				<li :class="['date-tab-item',{'act':tab === salesDimension.dateTab}]" v-for="tab in staticTabs" :key="tab" @click="changeTabHandle(tab)">
+					{{tab}}
+				</li>
+        <date-picker
+          v-model="salesDimension.selectDate"
+          type="date" 
+          range
+          value-type="format"
+          :clearable="false"
+          @change="dateChange"
+          placeholder="请选择统计时间"/>
+			</ul>
+      <div class="table-body-wrapper" v-show="dataLoading">
+				<table>
+					<thead>
+						<tr>
+							<td rowspan="2" class="thead-rs" style="width: 100px;">销售</td>
+							<td
+								:colspan="['周度统计表','月度统计表'].includes(salesDimension.dateTab) ? 3 : 1"
+								v-for="item in salesDimension.tableTheadColumns" 
+								:key="item" 
+								class="head-column"
+							>
+								{{item}}
+							</td>	
+						</tr>
+						<tr v-if="['月度统计表','周度统计表'].includes(salesDimension.dateTab)">
+							<template v-for="(item,index) in new Array(6)">
+								<td :key="index+'_0'">试用</td>
+								<td :key="index+'_1'">正式</td>
+								<td :key="index+'_2'">关闭</td>
+							</template>
+						</tr>
+					</thead>
+					<tbody>
+            <tr v-for="item in salesDimension.datalist" :key="item.AdminId">
+              <td class="thead-rs">{{item.Name}}</td>
+              <td class="data-cell" v-for="(data,data_key) in item.dataArr" :key="data_key" @click="openDiaHandle(data)">
+                {{ data.value !== 0 ? data.value : '' }}
+              </td>
+            </tr>
+					</tbody>
+					<tfoot>
+						<tr>
+							<td>合计</td>
+							<td v-for="(total_data,total_data_key) in salesDimension.totalGroupArr" :key="total_data_key" 
+              class="data-cell" @click="openDiaHandle(total_data)">
+								{{ total_data.value !== 0 ? total_data.value : '' }}
+							</td>
+						</tr>
+					</tfoot>
+				</table>
+			</div>	
+    </template>
+    <template v-if="roadshowTab==3">
+      <ul class="date-tab-box">
+				<li :class="['date-tab-item',{'act':tab === researchersDimension.dateTab}]" v-for="tab in staticTabs" :key="tab" @click="changeTabHandle(tab)">
+					{{tab}}
+				</li>
+        <date-picker
+          v-model="researchersDimension.selectDate"
+          type="date" 
+          range
+          value-type="format"
+          :clearable="false"
+          @change="dateChange"
+          placeholder="请选择统计时间"/>
+			</ul>
+      <div class="table-body-wrapper" v-show="dataLoading">
+				<table>
+					<thead>
+						<tr>
+							<td rowspan="2" class="thead-rs" style="width: 100px;">研究员</td>
+							<td
+								:colspan="['周度统计表','月度统计表'].includes(researchersDimension.dateTab) ? 3 : 1"
+								v-for="item in researchersDimension.tableTheadColumns" 
+								:key="item" 
+								class="head-column"
+							>
+								{{item}}
+							</td>	
+						</tr>
+            <tr v-if="['月度统计表'].includes(researchersDimension.dateTab)">
+              <template v-for="(item,index) in new Array(4)">
+								<td :key="index+'_0'">试用</td>
+								<td :key="index+'_1'">正式</td>
+								<td :key="index+'_2'">关闭</td>
+              </template>
+            </tr>
+            <tr v-if="['周度统计表'].includes(researchersDimension.dateTab)">
+              <template v-for="(item,index) in new Array(3)">
+								<td :key="index+'_0'">试用</td>
+								<td :key="index+'_1'">正式</td>
+								<td :key="index+'_2'">关闭</td>
+              </template>
+            </tr>
+					</thead>
+					<tbody>
+            <tr v-for="item in researchersDimension.datalist" :key="item.AdminId">
+              <td class="thead-rs">{{item.Name}}</td>
+              <td class="data-cell" v-for="(data,data_key) in item.dataArr" :key="data_key" @click="openDiaHandle(data)">
+                {{ data.value !== 0 ? data.value : '' }}
+              </td>
+            </tr>
+					</tbody>
+					<tfoot>
+						<tr>
+							<td>合计</td>
+							<td v-for="(total_data,total_data_key) in researchersDimension.totalGroupArr" :key="total_data_key" 
+              class="data-cell" @click="openDiaHandle(total_data)">
+								{{ total_data.value !== 0 ? total_data.value : '' }}
+							</td>
+						</tr>
+					</tfoot>
+				</table>
+			</div>	
+    </template>
+
+    <!-- 详情弹窗 -->
+		<actiyityDetailDia
+			:isShow.sync="isShowDia"
+			:title="diaTitle"
+			:form="dialogForm"
+			:fromType="roadshowTab==2?'seller':'researcher'"
+      region="oversea"
+		/>
+  </div>
+</template>
+<script>
+import { overseasCustomInterence } from '@/api/modules/overseasCustom.js'
+import mPage from '@/components/mPage.vue'
+import actiyityDetailDia from '@/views/roadshow_manage/compononts/activityDetailDia';
+export default {
+  components: { mPage,actiyityDetailDia },
+  data() {
+    return {
+      tabeLoading: false,
+      tableData: [],
+      total: 0,
+      currentIndex: 1,
+      pageSize: 10,
+      columns: [
+        {  label: "客户名称",key: 'CompanyName',minWidth:200 },
+        {  label: "状态",key: 'CompanyStatus' },
+        {  label: "路演日期",key: 'StartDate',sortable:true },
+        {  label: "路演形式",key: 'RoadshowType' },
+        {  label: "路演平台/路演城市",key: 'RoadshowPlatform' },
+        {  label: "研究员",key: 'ResearcherName' },
+        {  label: "对接销售",key: 'SellerName' },
+      ],
+
+      sales: [],
+      researchers: [],
+      date:[],
+      searchWord: '',
+      status:[],
+      sortParams: {
+        SortField: '',
+        SortDesc: 1,
+      },
+
+      salesOptions: [],
+      researchersOptions: [],
+      statusOptions: [
+        { label: '正式', val: '正式' },
+        { label: '试用', val: '试用' },
+        { label: '关闭', val: '关闭' },
+      ],
+      roadshowTab:1,
+      staticTabs: [ '周度统计表','月度统计表','近1个月','近3个月','近6个月' ],
+      dataLoading:false,
+      // 销售维度
+      salesDimension:{
+        dateTab:"周度统计表",
+        selectDate:"",
+        tableTheadColumns:[],
+        datalist:[],//表格数据
+        totalGroupArr:[] //合计数据
+      },
+      // 研究员维度
+      researchersDimension:{
+        dateTab:"周度统计表",
+        selectDate:"",
+        tableTheadColumns:[],
+        datalist:[],//表格数据
+        totalGroupArr:[] //合计数据
+      },
+      // 详情弹窗
+      isShowDia:false,
+      diaTitle:'路演详情',
+      dialogForm:{}
+    }
+  },
+  mounted(){
+    this.getSellerList()
+    this.getResearchersList()
+    this.getTableData()
+  },
+  methods:{
+    //获取销售列表
+    async getSellerList() {
+      const res = await overseasCustomInterence.getOverseasRoadShowUsers({AdminType:'seller'})
+
+      if (res.Ret === 200) {
+        this.salesOptions = res.Data || [];
+      }
+    },
+
+    //获取研究员列表
+    async getResearchersList() {
+      // 发送请求
+      const res = await overseasCustomInterence.getOverseasRoadShowUsers({AdminType:'researcher'});
+      if (res.Ret === 200) {
+        this.researchersOptions = res.Data || [];
+      }
+    },
+
+    async getTableData() {
+      this.tabeLoading = true;
+      let params = {
+        ResearcherId: this.researchers.join(','),
+        SellerId: this.sales.join(','),
+        StartDate: this.date[0]||'',
+        EndDate: this.date[1]||'',
+        CompanyStatus: this.status.join(','),
+        CurrentIndex: this.currentIndex,
+        PageSize: this.pageSize,
+        Keyword: this.searchWord,
+        ...this.sortParams
+      }
+      const res = await overseasCustomInterence.getOverseasRoadShowList(params)
+
+      this.tabeLoading = false;
+
+      if(res.Ret!==200) return
+
+      this.tableData = res.Data.List || [];
+
+      this.total = res.Data.Paging.Totals;
+    },
+
+    handleSortChange({prop,order}) {
+      console.log(prop,order)
+      this.sortParams = {
+        SortField: order?prop:'',
+        SortDesc: order==='ascending'?2:1
+      }
+
+      this.pageChange(1)
+    },
+
+    pageChange(page) {
+      this.currentIndex = page;
+      this.getTableData()
+    },
+
+    toCustomDetail(data) {
+      const path = data.Source===1?'/detailCustomEn':'/customDetail'
+      const query = {
+          ...data.Source===1?{
+            companyId:data.CompanyId - 10000000
+          }:{
+              id:data.CompanyId
+          },
+          from:'overseas'
+      }
+      const href = this.$router.resolve({path,query}).href
+      window.open(href,"_blank")
+    },
+    /* 切换筛选 */
+    changeSelectOpts() {
+      
+    },
+    tabChange(tab){
+      if(this.roadshowTab==tab) return 
+      this.roadshowTab=tab
+      this.changeTabHandle('周度统计表')
+    },
+    /* 	获取几周前 周一周日日期 或前几月月份*/
+		getWeekOrMonthDate(weeknum,type='week') {
+			if(type === 'week') {
+				const weekStart = this.$moment().subtract(weeknum, 'week').startOf('isoWeek').format('YYYY.MM.DD'); //周一
+				const weekEnd = this.$moment().subtract(weeknum, 'week').endOf('isoWeek').format('YYYY.MM.DD'); //周日
+	
+				// console.log(weekStart,weekEnd)
+				return `${weekStart}~${weekEnd}`;
+			} else {
+				const month = this.$moment().subtract(weeknum,'M').format('YYYY.MM');
+				return month;
+			}
+		},
+    changeTabHandle(tab){
+      if(this.roadshowTab == 1){
+        return
+      }else if(this.roadshowTab == 2){
+        this.salesDimension.dateTab = tab;
+        switch(tab) {
+          case '周度统计表':
+            this.salesDimension.tableTheadColumns = [
+                `本周(${this.getWeekOrMonthDate(0)})`,
+                `上一周(${this.getWeekOrMonthDate(1)})`,
+                `上两周(${this.getWeekOrMonthDate(2)})`,
+                `上三周(${this.getWeekOrMonthDate(3)})`,
+                `上四周(${this.getWeekOrMonthDate(4)})`,
+                `上五周(${this.getWeekOrMonthDate(5)})`]
+            break;
+          case '月度统计表':
+            this.salesDimension.tableTheadColumns = [
+                this.getWeekOrMonthDate(0,'month'),
+                this.getWeekOrMonthDate(1,'month'),
+                this.getWeekOrMonthDate(2,'month'),
+                this.getWeekOrMonthDate(3,'month'),
+                this.getWeekOrMonthDate(4,'month'),
+                this.getWeekOrMonthDate(5,'month')]
+            break;
+          default:
+          this.salesDimension.tableTheadColumns = ['试用','正式','关闭']
+
+          break;
+        }
+      }else{
+        this.researchersDimension.dateTab = tab;
+        switch(tab) {
+          case '周度统计表':
+            this.researchersDimension.tableTheadColumns =  ['上一周','本周','下一周']
+            break;
+          case '月度统计表':
+            this.researchersDimension.tableTheadColumns = [
+              this.getWeekOrMonthDate(0,'month'),
+              this.getWeekOrMonthDate(1,'month'),
+              this.getWeekOrMonthDate(2,'month'),
+              this.getWeekOrMonthDate(3,'month'),
+            ]
+            break;
+          default:
+          this.researchersDimension.tableTheadColumns = ['试用','正式','关闭']
+          break;
+        }
+      }
+      this.$nextTick(()=>{
+        $('.table-body-wrapper')[0].scrollTop = 0;
+      })
+      let typeObj = {
+        '近1个月': 1,
+        '近3个月': 3,
+        '近6个月': 6,
+      };
+      typeObj[tab] ? this.filterDate(typeObj[tab]) : this.filterDate(0);
+
+      this.getData();
+    },
+    dateChange(){
+      if(this.roadshowTab==2){
+        this.salesDimension.dateTab = '';
+        this.salesDimension.tableTheadColumns = ['试用','正式','关闭'];
+      }else{
+        this.researchersDimension.dateTab = '';
+			  this.researchersDimension.tableTheadColumns = ['试用','正式','关闭'];
+      }
+
+			this.getData();
+    },
+    filterDate(month){
+      if(month) {
+				let date_before = this.$moment().subtract(month,'M').format("YYYY-MM-DD");
+				let date_now = this.$moment().format("YYYY-MM-DD");
+				let date = [date_before,date_now]
+				this.roadshowTab==2?(this.salesDimension.selectDate = date):(this.researchersDimension.selectDate = date);
+			}else {
+        this.roadshowTab==2?(this.salesDimension.selectDate = ''):(this.researchersDimension.selectDate = '');
+			}
+    },
+    // 销售维度、研究员维度
+    getData(){
+      let apiName=this.roadshowTab==2?"getOverseasSellerRoadShowList":"getOverseasResearcherRoadShowList"
+      let params=this.roadshowTab==2?{
+        DataType: this.salesDimension.dateTab === '周度统计表' ? 'week' : this.salesDimension.dateTab === '月度统计表' ? 'month' : 'time_interval',
+        StartDate: this.salesDimension.selectDate ? this.salesDimension.selectDate[0] : '',
+        EndDate: this.salesDimension.selectDate ? this.salesDimension.selectDate[1] : '',
+      }:{
+        DataType: this.researchersDimension.dateTab === '周度统计表' ? 'week' : this.researchersDimension.dateTab === '月度统计表' ? 'month' : 'time_interval',
+        StartDate: this.researchersDimension.selectDate ? this.researchersDimension.selectDate[0] : '',
+        EndDate: this.researchersDimension.selectDate ? this.researchersDimension.selectDate[1] : '',
+      }
+      this.dataLoading=false
+      overseasCustomInterence[apiName](params).then(res=>{
+        if(res.Ret == 200){
+          // console.log(res,'res');
+          const dataList=res.Data.List||[]
+          const totalGroupArr=res.Data.RsReportRecordNumList || []
+          dataList.forEach((da)=>{
+            da.dataArr = this.filterTableData(da.RsReportRecordNumList,[da.AdminId])
+          })
+          if(this.roadshowTab==2){
+            this.salesDimension.datalist=dataList
+            this.salesDimension.totalGroupArr=this.filterTableData(totalGroupArr,dataList.map(it => it.AdminId))
+          }else{
+            this.researchersDimension.datalist=dataList
+            this.researchersDimension.totalGroupArr=this.filterTableData(totalGroupArr,dataList.map(it => it.AdminId))
+          }
+          this.dataLoading=true
+        }
+      })
+
+    },
+    /* 处理数据结构 便于页面渲染 userid 时间用于弹窗获取列表*/
+		filterTableData(data,userid=[]) {
+			let list = data.map(item => ([
+        {
+					key: '试用',
+					value: item.TryOutNum,
+					startDate: item.StartDate,
+					endDate: item.EndDate,
+					userid
+				},
+        {
+					key: '正式',
+					value: item.FormalNum,
+					startDate: item.StartDate,
+					endDate: item.EndDate,
+					userid
+				},
+				{
+					key: '关闭',
+					value: item.CloseNum,
+					startDate: item.StartDate,
+					endDate: item.EndDate,
+					userid
+				}
+			]))
+			
+			return list.flat(Infinity);
+		},
+    openDiaHandle({ startDate,endDate,userid,value,key }){
+      if(value === 0) return;
+
+      this.dialogForm = {
+        startDate,
+        endDate,
+        userid,
+        key
+      }
+      this.isShowDia = true;
+    }
+  },
+}
+</script>
+<style scoped lang="scss">
+.overseas-custom-roadshow-box {
+    min-height: calc(100vh - 110px);
+    background-color: white;
+    border: 1px solid #ECECEC;
+    border-radius: 2px;
+    box-sizing: border-box;
+    padding: 20px 30px 30px 30px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    .tab-box{
+      margin-bottom: 20px;
+      display: flex;
+      align-items: center;
+      gap: 15px;
+      .tab-item{
+        min-width: 120px;
+        margin: 0;
+      }
+    }
+    .top-wrapper {
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: space-between;
+    }
+    .cont-wrapper {
+      margin-top: 10px;
+      padding-bottom: 40px;
+    }
+    .editor{
+        color:#409EFF;
+        cursor: pointer;
+        &:hover{
+            text-decoration: underline;
+        }
+    }
+    .date-tab-box{
+      display: flex;
+			align-items: center;
+			color: #333;
+			margin-bottom: 30px;
+      gap: 20px;
+      .date-tab-item{
+        cursor: pointer;
+        &:hover {
+					color: #409EFF;
+				}
+				&.act {
+					color: #409EFF;
+					position: relative;
+					&::after {
+						content: "";
+						width: 100%;
+						height: 2px;
+						position: absolute;
+						bottom: -10px;
+						left: 50%;
+						transform: translateX(-50%);
+						background: #409EFF;
+					}
+				}
+      }
+    }
+    .table-body-wrapper {
+			max-height: calc(100vh - 300px);
+			margin-right: -6px;
+			overflow-y: scroll;
+			overflow-x: auto;
+			border-bottom: 1px solid #dcdfe6;
+			border-top: 1px solid #dcdfe6;
+		}
+
+		table {
+			width: 100%;
+			font-size: 14px;
+			color: #666;
+			thead{
+				position: sticky;
+				top: 0;
+				left: 0;
+				border-left: 1px solid #dcdfe6;
+				border-right: 1px solid #dcdfe6;
+				td{
+					border: none;
+					outline-color: #dcdfe6;
+					outline-style: solid;
+					outline-width: 0.5px;
+				}
+			}
+			td,
+			th {
+				min-width: 35px;
+				// word-break: break-all;
+				border: 1px solid #dcdfe6;
+				height: 45px;
+				text-align: center;
+				background-color: #fff;
+			}
+	
+			.head-column {
+				background-color: #F0F2F5;
+			}
+	
+			.data-cell{
+				color: #409EFF;
+				cursor: pointer;
+			}
+
+			.thead-sticky {
+				position: sticky;
+				top: 0;
+			}
+		}
+}
+</style>
+

+ 437 - 0
src/views/custom_manage/points/AddNewEntries.vue

@@ -0,0 +1,437 @@
+<template>
+  <div class="container add-new-entries">
+    <div class="container-top">
+      <span>客户名称</span>
+      <el-autocomplete v-model="companyName" :fetch-suggestions="querySearchAsync" style="width: 220px; margin: 0 20px" @select="selectCompanyChange" placeholder="请输入客户名称"></el-autocomplete>
+
+      <div class="quarters-content">
+        <el-checkbox-group v-model="selectedQuarters">
+          <el-checkbox v-for="quarter in quarters" :key="quarter.value" :label="quarter.label" :disabled="isDisabled(quarter)">
+            {{ quarter.label }}
+          </el-checkbox>
+        </el-checkbox-group>
+      </div>
+    </div>
+    <div v-if="Object.keys(EnterScoreObj).length > 0">
+      <div class="tabs-box">
+        <span v-for="item in listTitle" :key="item.value" @click="tabsBoxBtn(item)" :class="item.value == tabsPitchon ? 'pitch' : ''">{{ item.lable }}</span>
+      </div>
+      <template>
+        <p class="class-text">
+          权益研究员 <span style="font-weight: 600">{{ allPerCentNumble(raiDataHandler(), "rai") }}</span>
+          <span v-if="tabsPitchon == 2 && allPerCentNumble(raiDataHandler(), 'rai')">%</span>
+        </p>
+        <div class="content-box">
+          <div v-for="item in raiDataHandler()" :key="item.EnterScoreId">
+            <div :class="['industry-ul']">
+              <span :class="['industry-name']">{{ item.ChartPermissionName }}</span>
+              <span style="margin: 0 5px 0 8px; font-weight: 600">{{ allPerCentHandlerRai(item) }}</span>
+              <span v-if="tabsPitchon == 2 && item.Proportion">%</span>
+            </div>
+            <div v-for="study in item.List" :key="study.RealName" :class="['industry-ul']">
+              <span :class="['study-name']">{{ study.RealName }}</span>
+              <template>
+                <el-input :min="-100" :max="100" type="number" v-model="study.Proportion" size="small" @input="formatDecimal(study)" style="width: 76px; margin: 0 5px 0 8px"> </el-input>
+              </template>
+              <span v-if="tabsPitchon == 2">%</span>
+            </div>
+          </div>
+        </div>
+      </template>
+      <template>
+        <p class="class-text">
+          FICC研究员 <span style="font-weight: 600">{{ allPerCentNumble(FICCDataHandler(), "ficc") }}</span>
+          <span v-if="tabsPitchon == 2 && allPerCentNumble(FICCDataHandler(), 'ficc')">%</span>
+        </p>
+        <div class="content-box">
+          <div v-for="item in FICCDataHandler()" :key="item.EnterScoreId">
+            <div :class="['industry-ul']">
+              <span :class="['industry-name']">{{ item.ChartPermissionName }}</span>
+              <span style="margin: 0 5px 0 8px; font-weight: 600">{{ allPerCentHandlerFICC(item) }}</span>
+              <span v-if="tabsPitchon == 2 && item.Proportion">%</span>
+            </div>
+            <div v-for="study in item.List" :key="study.RealName" :class="['industry-ul']">
+              <span :class="['study-name']">{{ study.RealName }}</span>
+              <template>
+                <el-input :min="-100" :max="100" type="number" v-model="study.Proportion" size="small" @input="formatDecimal(study)" style="width: 76px; margin: 0 5px 0 8px"> </el-input>
+              </template>
+              <span v-if="tabsPitchon == 2">%</span>
+            </div>
+          </div>
+        </div>
+      </template>
+      <div class="division-line"></div>
+      <div class="content-box">
+        <div v-for="item in ProuDataHandler()" :key="item.GroupName">
+          <div :class="['industry-ul']">
+            <span :class="['industry-name']">{{ item.GroupName }}</span>
+            <el-input :min="-100" :max="100" type="number" v-model="item.Proportion" @input="formatDecimal(item)" size="small" style="width: 76px; margin: 0 5px 0 8px"> </el-input>
+            <span v-if="tabsPitchon == 2">%</span>
+          </div>
+        </div>
+      </div>
+      <div class="division-line"></div>
+      <div class="bottom-box">
+        排名
+        <el-input type="text" v-model="rankingValue" style="width: 110px; margin: 0 50px 0 8px" placeholder="请输入排名"> </el-input>
+        合并打分
+        <el-radio-group v-model="radioScoring" style="margin: 0 60px 0 8px">
+          <el-radio :label="0">否</el-radio>
+          <el-radio :label="1">是</el-radio>
+        </el-radio-group>
+        <template v-if="radioScoring == 1">
+          券商名称
+          <el-input type="text" v-model="brokerName" placeholder="请输入合并打分的券商名称" style="width: 230px; margin: 0 50px 0 8px"> </el-input>
+          合并占比
+          <el-input type="text" v-model="mergeProportion" placeholder="占比值" style="width: 76px; margin: 0 5px 0 8px"> </el-input>%
+        </template>
+      </div>
+      <p class="total-num" v-if="Object.keys(EnterScoreObj).length > 0">
+        当前合计总分:{{ TotalScoreHandler(ProuDataHandler()) }}
+        <span v-if="tabsPitchon == 2">%</span>
+      </p>
+      <div style="display: flex; justify-content: center">
+        <el-button type="primary" style="margin-right: 20px" @click="preserveHandler">{{ $route.query.id ? "修改并保存" : "保存" }}</el-button>
+        <el-button type="primary" plain @click="goBackHandler">取消</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import quartersMixin from "../customList/mixins/quartersMixin";
+import { xClassCustomApi, raiInterface } from "@/api/api.js";
+
+export default {
+  name: "",
+  components: {},
+  mixins: [quartersMixin],
+  props: {},
+  data() {
+    return {
+      listTitle: [
+        {
+          lable: "按评分录入",
+          value: 1,
+        },
+        {
+          lable: "按比例录入",
+          value: 2,
+        },
+      ],
+      tabsPitchon: 1, //tabs 默认选中
+      tmeplateObj: {},
+      EnterScoreObj: {},
+      PercentageObj: {},
+      rankingValue: "", // 排名
+      radioScoring: 0, // 合并打分
+      brokerName: "", //券商名称
+      mergeProportion: "",
+      querySearchList: [],
+      companyName: "",
+      companyId: 0,
+      totalScoreNumber: 0,
+    };
+  },
+  computed: {},
+  watch: {
+    companyName: {
+      handler(newVal) {
+        if (!this.companyName) {
+          this.companyId = 0;
+        }
+      },
+    },
+  },
+  created() {},
+  mounted() {
+    this.$route.query.id ? this.getCompanyDetail() : this.getDataTemplate();
+  },
+  methods: {
+    // 头部的点击事件
+    tabsBoxBtn(item) {
+      if (this.tabsPitchon == item.value) return;
+      this.tabsPitchon = item.value;
+      this.raiDataHandler();
+      this.FICCDataHandler();
+      this.ProuDataHandler();
+    },
+
+    /** */
+    /** */
+    allPerCentHandlerRai(item) {
+      return this.allPerCentHandler(item);
+    },
+    allPerCentHandlerFICC(item) {
+      return this.allPerCentHandler(item);
+    },
+    //数量的总和
+    allPerCentHandler(item) {
+      let num = 0;
+      item && item.List.forEach((key) => (num = num + +key.Proportion));
+      item.Proportion = Number(num.toFixed(2));
+      return num == 0 ? "" : num.toFixed(2);
+    },
+    /** */
+    /** */
+
+    // 处理小数点
+    formatDecimal(key) {
+      let value = key.Proportion;
+      if (value === "") return; // 如果为空则不处理
+      // 先清除非数字和多余的小数点
+      value = value
+        .replace(/[^\d.]/g, "")
+        .replace(/\.{2,}/g, ".")
+        .replace(".", "$#$")
+        .replace(/\./g, "")
+        .replace("$#$", ".");
+
+      // 限制只能输入两位小数
+      const decimalRegex = /^(\d+\.?\d{0,2})/;
+      const match = value.match(decimalRegex);
+
+      if (match) {
+        key.Proportion = match[1];
+        this.restrictInput(key);
+      } else {
+        key.Proportion = 0; // 如果不匹配正则,则清空输入框
+      }
+    },
+    // 输入框的限制
+    restrictInput(item) {
+      if (item.Proportion) if (item.Proportion > 100) return (item.Proportion = 100);
+      if (item.Proportion < -100) return (item.Proportion = -100);
+    },
+    // 切换了录入 权益
+    raiDataHandler() {
+      return this.tabsPitchon == 1 ? this.EnterScoreObj.ListRai : this.PercentageObj.ListRai;
+    },
+    // 切换了录入 FICC
+    FICCDataHandler() {
+      return this.tabsPitchon == 1 ? this.EnterScoreObj.ListFicc : this.PercentageObj.ListFicc;
+    },
+    // 切换了录入 分组
+    ProuDataHandler() {
+      return this.tabsPitchon == 1 ? this.EnterScoreObj.ListGroup : this.PercentageObj.ListGroup;
+    },
+
+    /** */
+    /** */
+    // 总和
+    allPerCentNumble(item, type) {
+      let num = 0;
+      item.forEach((item) => (num += item.Proportion));
+      type === "rai" ? (this.tmeplateObj.RaiProportionTotal = Number(num.toFixed(2))) : (this.tmeplateObj.FiccProportionTotal = Number(num.toFixed(2)));
+      return num == 0 ? "" : num.toFixed(2);
+    },
+    TotalScoreHandler(item) {
+      let num = 0;
+      item && item.forEach((item) => (num += Number(item.Proportion)));
+      this.totalScoreNumber = Number((num + this.tmeplateObj.RaiProportionTotal + this.tmeplateObj.FiccProportionTotal).toFixed(2));
+      return this.totalScoreNumber;
+    },
+    /** */
+    /** */
+
+    // 获取模板
+    async getDataTemplate() {
+      const res = await xClassCustomApi.enterScoreDetail();
+      if (res.Ret === 200) {
+        this.tmeplateObj = res.Data;
+        this.EnterScoreObj = res.Data.EnterScoreObj;
+        this.PercentageObj = res.Data.PercentageObj;
+      }
+    },
+
+    // 保存
+    async preserveHandler() {
+      let StartDate = this.selectedDateRange ? this.selectedDateRange.split(" ~ ")[0] : "";
+      let EndDate = this.selectedDateRange ? this.selectedDateRange.split(" ~ ")[1] : "";
+      let ListGroup = this.ProuDataHandler().map((item) => {
+        return {
+          ...item,
+          Proportion: Number(item.Proportion),
+        };
+      });
+      let ListRai = this.raiDataHandler().map((item) => ({
+        ...item,
+        List: item.List.map((subItem) => ({
+          ...subItem,
+          Proportion: Number(subItem.Proportion),
+        })),
+      }));
+      let ListFicc = this.FICCDataHandler().map((item) => ({
+        ...item,
+        List: item.List.map((subItem) => ({
+          ...subItem,
+          Proportion: Number(subItem.Proportion),
+        })),
+      }));
+      let params = {
+        EnterScoreId: this.$route.query.id ? +this.$route.query.id : 0, //录分ID,等于0新增,大于0 修改
+        CompanyId: this.companyId,
+        CompanyName: this.companyName,
+        Quarter: this.selectedQuarters,
+        StartDate,
+        EndDate,
+        EnterScoreType: this.tabsPitchon,
+        RaiProportionTotal: this.tmeplateObj.RaiProportionTotal,
+        FiccProportionTotal: this.tmeplateObj.FiccProportionTotal,
+        ListRai,
+        ListFicc,
+        ListGroup,
+        Ranking: this.rankingValue,
+        IsMergeScoring: this.radioScoring,
+        SecuritiesFirmsName: this.brokerName,
+        MergeProportion: this.mergeProportion ? +this.mergeProportion : 0,
+        ProportionTotal: this.totalScoreNumber,
+      };
+      if (!params.CompanyName || !params.CompanyId) return this.$message.error("请输入客户名称");
+      if (!params.Quarter.length) return this.$message.error("请选择季度");
+      const res = await xClassCustomApi.enterScoreUpdate(params);
+      if (res.Ret === 200) {
+        this.$message.success(res.Msg);
+        this.$router.back();
+      }
+    },
+    //  获取详情
+    async getCompanyDetail() {
+      const res = await xClassCustomApi.enterScoreDetail({
+        EnterScoreId: +this.$route.query.id,
+      });
+      if (res.Ret === 200) {
+        this.tmeplateObj = res.Data;
+        this.EnterScoreObj = res.Data.EnterScoreObj;
+        this.PercentageObj = res.Data.PercentageObj;
+        this.rankingValue = res.Data.Ranking;
+        this.radioScoring = res.Data.IsMergeScoring;
+        this.brokerName = res.Data.SecuritiesFirmsName;
+        this.mergeProportion = res.Data.MergeProportion;
+        this.selectedQuarters = res.Data.Quarter;
+        this.companyId = res.Data.CompanyId;
+        this.companyName = res.Data.CompanyName;
+        this.tabsPitchon = res.Data.EnterScoreType;
+      }
+    },
+    //
+    async querySearchAsync(query, cb) {
+      cb([]);
+      if (query) {
+        const res = await xClassCustomApi.enterScoreSearchlist({ KeyWord: query });
+        if (res.Ret === 200) {
+          this.querySearchList = res.Data.List.map((_) => {
+            return {
+              ..._,
+              value: _.CompanyName,
+            };
+          });
+          cb(this.querySearchList);
+        }
+      }
+    },
+    // 选择后客户名称的id
+    selectCompanyChange(value) {
+      this.companyId = value.CompanyId;
+    },
+    // 返回事件
+    goBackHandler() {
+      this.$router.back();
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.add-new-entries {
+  .container-top {
+    display: flex;
+    align-items: center;
+  }
+  .class-text {
+    margin-top: 20px;
+    width: 100%;
+    height: 38px;
+    line-height: 32px;
+    padding-left: 20px;
+    background-color: #ebeef5;
+  }
+  .tabs-box {
+    margin-top: 20px;
+    span {
+      display: inline-block;
+      padding: 9px 24px;
+      background-color: #e9f4ff;
+      border: 1px solid #b3d8ff;
+      border-radius: 4px;
+      margin-right: 30px;
+      color: #409eff;
+      cursor: pointer;
+    }
+    .pitch {
+      background-color: #409eff;
+      border: none;
+      color: #fff;
+    }
+  }
+  .content-box {
+    width: 100%;
+    overflow: hidden;
+    overflow-x: auto;
+    display: flex;
+    .industry-ul {
+      display: flex;
+      align-items: center;
+      margin: 10px 0;
+      width: 188px;
+      color: #333;
+      margin-right: 25px;
+      .per_cent_ {
+        line-height: 32px;
+      }
+      .industry-name {
+        flex-shrink: 0;
+        font-weight: 800;
+        font-size: 16px;
+        line-height: 22px;
+      }
+      .study-name {
+        width: 58px;
+        flex-shrink: 0;
+        font-size: 14px;
+        line-height: 22px;
+      }
+      p {
+        color: #9999;
+        font-size: 14px;
+      }
+    }
+  }
+  .division-line {
+    width: 100%;
+    border: 1px dashed #dcdfe6;
+    margin: 30px 0 20px;
+  }
+  .bottom-box {
+    display: flex;
+    align-items: center;
+  }
+
+  .total-num {
+    margin: 30px 0 20px 0;
+    padding-left: 460px;
+  }
+}
+</style>
+<style>
+/* 针对于 Chrome、Safari 等 Webkit 内核浏览器 */
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  -webkit-appearance: none;
+  margin: 0;
+}
+
+/* 针对 Firefox 浏览器 */
+input[type="number"] {
+  -moz-appearance: textfield;
+}
+</style>

+ 231 - 0
src/views/custom_manage/points/EntryRecords.vue

@@ -0,0 +1,231 @@
+<template>
+  <div class="container entry-records-points">
+    <div>
+      <el-autocomplete
+        v-model="companyName"
+        :fetch-suggestions="querySearchAsync"
+        style="width: 220px; margin-right: 20px"
+        @select="selectCompanyChange"
+        clearable
+        placeholder="请输入公司名称"
+        @clear="clearCompanyHandleSearch"
+      >
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-autocomplete>
+      <el-cascader
+        v-model="sales"
+        placeholder="请选择销售"
+        style="width: 200px; margin-right: 20px"
+        :options="salesArr"
+        :props="defaultSalesProps"
+        :show-all-levels="false"
+        collapse-tags
+        clearable
+        filterable
+        @change="companyHandleSearch"
+      >
+      </el-cascader>
+      <el-button type="primary" @click="$router.push('AddNewEntries')"> 新增</el-button>
+      <a :href="exportUser" download>
+        <el-button type="primary" style="width: 80px;margin-left:15px">导出</el-button>
+      </a>
+    </div>
+
+    <div style="margin-top: 20px">
+      <el-table :data="tableData" style="width: 100%" border>
+        <el-table-column align="center" prop="CompanyName" label="客户名称"> </el-table-column>
+        <el-table-column align="center" prop="SellerName" label="销售" width="100"> </el-table-column>
+        <el-table-column align="center" prop="Quarter" label="季度" width="180">
+          <template slot-scope="{ row }">
+            <span>{{ row.Quarter.join(",") }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="ProportionTotal" label="总分" width="100">
+          <template slot-scope="{ row }">
+            <span>{{ row.ProportionTotal }}{{ row.EnterScoreType == 2 ? "%" : "" }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="Ranking" label="排名" width="100"> </el-table-column>
+        <el-table-column align="center" prop="IsMergeScoring" label="合并打分" width="80">
+          <template slot-scope="{ row }">
+            <span>{{ row.IsMergeScoring == 1 ? "是" : "否" }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="SecuritiesFirmsName" label="券商名称"> </el-table-column>
+        <el-table-column align="center" prop="CreateTime" label="首次录入时间" width="180"> </el-table-column>
+        <el-table-column align="center" prop="ModifyTime" label="最近更新时间" width="180"> </el-table-column>
+        <el-table-column align="center" prop="name" label="操作" width="180">
+          <template slot-scope="{ row }">
+            <span class="editsty" @click="lookHandler(row)">查看明细</span>
+            <span class="deletesty" @click="deleteHandle(row)">删除</span>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { customInterence, xClassCustomApi } from "@/api/api.js";
+export default {
+  name: "EntryRecords",
+  props: {
+    searchVal: {
+      type: String,
+      default: "",
+    },
+  },
+  computed: {
+    exportUser() {
+      let baseUrl = process.env.API_ROOT + "/cygx/enterScore/list";
+      let token = localStorage.getItem("auth") || "";
+      let salesArr = [];
+      if (this.sales.length) {
+        salesArr = this.sales.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let paramStr = "";
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page_no,
+        KeyWord: this.companyName,
+        AdminId: salesArr.join(","),
+        IsExport: true,
+      };
+      for (let key in params) {
+        paramStr = `${paramStr}&${key}=${params[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+  },
+  data() {
+    return {
+      page_no: 1,
+      pageSize: 10,
+      total: 1,
+      tableData: [],
+      companyName: "",
+      sales: "",
+      salesArr: [], //销售
+      defaultSalesProps: {
+        multiple: true,
+        label: "RealName",
+        children: "ChildrenList",
+        value: "AdminId",
+      }, //销售级联配置
+    };
+  },
+  watch: {
+    searchVal() {
+      this.getDataList();
+    },
+  },
+  mounted() {
+    this.getSale();
+    this.getDataList();
+  },
+  methods: {
+    // 公司名称
+    companyHandleSearch(value) {
+      this.page_no = 1;
+      this.getDataList();
+    },
+    /* 获取销售 */
+    getSale() {
+      let status = 0;
+      if (this.act_status == "流失") {
+        status = 1;
+      }
+      customInterence.getSale({ Status: status }).then((res) => {
+        if (res.Ret === 200) {
+          this.salesArr = res.Data.List;
+        }
+      });
+    },
+    // 获取列表信息
+    async getDataList() {
+      let salesArr = [];
+      if (this.sales.length) {
+        salesArr = this.sales.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      const res = await xClassCustomApi.enterScoreList({
+        PageSize: this.pageSize,
+        CurrentIndex: this.page_no,
+        KeyWord: this.companyName,
+        AdminId: salesArr.join(","),
+      });
+      if (res.Ret === 200) {
+        this.total = res.Data.Paging.Totals;
+        this.tableData = res.Data.List;
+      }
+    },
+    // 删除
+    deleteHandle(item) {
+      this.$confirm("是否删除?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(async () => {
+          const res = await xClassCustomApi.enterScoreDelete({
+            EnterScoreId: item.EnterScoreId,
+          });
+          if (res.Ret === 200) {
+            this.$message({
+              type: "success",
+              message: "删除成功!",
+            });
+            this.getDataList();
+          }
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "已取消删除",
+          });
+        });
+    },
+    // 查看
+    lookHandler(item) {
+      this.$router.push({
+        path: "/EditNewEntries",
+        query: { id: item.EnterScoreId },
+      });
+    },
+    //
+    async querySearchAsync(query, cb) {
+      cb([]);
+      if (query) {
+        const res = await xClassCustomApi.enterScoreSearchlist({ KeyWord: query });
+        if (res.Ret === 200) {
+          this.querySearchList = res.Data.List.map((_) => {
+            return {
+              ..._,
+              value: _.CompanyName,
+            };
+          });
+          cb(this.querySearchList);
+        }
+      }
+    },
+    // 选择后客户名称的id
+    selectCompanyChange(value) {
+      this.companyId = value.CompanyId;
+      this.page_no = 1;
+      this.getDataList();
+    },
+    clearCompanyHandleSearch() {
+      this.companyId = "";
+      this.page_no = 1;
+      this.getDataList();
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+// .entry-records-points {
+// }
+</style>

+ 211 - 0
src/views/custom_manage/points/RankingOverview.vue

@@ -0,0 +1,211 @@
+<template>
+  <div class="container ranking-overview-content">
+    <div class="select-box">
+      <el-cascader
+        v-model="sales"
+        placeholder="请选择销售"
+        style="width: 220px"
+        :options="salesArr"
+        :props="defaultSalesProps"
+        :show-all-levels="false"
+        collapse-tags
+        clearable
+        filterable
+        @change="changeHandle"
+      >
+      </el-cascader>
+      <el-select style="width: 220px; margin: 0 20px" v-model="valueLocation" multiple placeholder="请选择城市" @change="changeHandle">
+        <el-option v-for="item in locationOptions" :key="item.name" :label="item.name" :value="item.name"> </el-option>
+      </el-select>
+      <a :href="exportUser" download>
+        <el-button type="primary" style="width: 80px">导出</el-button>
+      </a>
+    </div>
+    <div class="table-cont">
+      <template v-if="tableTheadColumns.length">
+        <table class="thead-sticky thead-box">
+          <thead>
+            <tr>
+              <td class="'head-column'"></td>
+              <td v-for="item in tableTheadColumns" :key="item" :class="['head-column']">
+                {{ item.CompanyName }}
+              </td>
+            </tr>
+          </thead>
+          <tbody v-for="(item, index) in datalist" :key="index">
+            <tr>
+              <td class="thead-rs">{{ item.Quarter }}</td>
+              <td v-for="key in item.ProportionListText" :key="key">{{ key }}</td>
+            </tr>
+          </tbody>
+        </table>
+        <template v-if="!datalist.length"> <div class="not-text">暂无数据</div> </template>
+      </template>
+      <template v-else> <div class="not-text">暂无数据</div> </template>
+    </div>
+  </div>
+</template>
+
+<script>
+import { customInterence, xClassCustomApi } from "@/api/api.js";
+
+export default {
+  name: "",
+  components: {},
+  props: {},
+  data() {
+    return {
+      sales: "",
+      salesArr: [], //销售
+      defaultSalesProps: {
+        multiple: true,
+        label: "RealName",
+        children: "ChildrenList",
+        value: "AdminId",
+      }, //销售级联配置
+      valueLocation: [], //地址
+      tableTheadColumns: [],
+      datalist: [],
+      listGroup: [],
+      locationOptions: [{ name: "北京市" }, { name: "上海市" }, { name: "深圳市" }],
+    };
+  },
+  computed: {
+    exportUser() {
+      let baseUrl = process.env.API_ROOT + "/cygx/enterScore/rankingOverview";
+      let token = localStorage.getItem("auth") || "";
+      let paramStr = "";
+      let params = this.paramsHandler();
+      params.IsExport = true;
+      for (let key in params) {
+        paramStr = `${paramStr}&${key}=${params[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+  },
+  watch: {},
+  created() {},
+  mounted() {
+    this.getSale();
+    this.getDataList();
+  },
+  methods: {
+    /* 获取销售 */
+    getSale() {
+      let status = 0;
+      if (this.act_status == "流失") {
+        status = 1;
+      }
+      customInterence.getSale({ Status: status }).then((res) => {
+        if (res.Ret === 200) {
+          this.salesArr = res.Data.List;
+        }
+      });
+    },
+    async getDataList() {
+      let params = this.paramsHandler();
+      const res = await xClassCustomApi.enterScoreRankingOverview(params);
+      if (res.Ret === 200) {
+        this.tableTheadColumns = res.Data.ListCompany || [];
+        this.datalist = res.Data.ListQuarterDate || [];
+      }
+    },
+    // 处理数据, 获取数据
+    paramsHandler() {
+      let salesArr = [];
+      if (this.sales.length) {
+        salesArr = this.sales.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let params = {
+        City: this.valueLocation.join(","),
+        AdminId: salesArr.join(","),
+      };
+      return params;
+    },
+    changeHandle() {
+      this.getDataList();
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.ranking-overview-content {
+  .select-box {
+    display: flex;
+  }
+
+  .top-select {
+    display: flex;
+    justify-content: space-between;
+  }
+  .select-box {
+    display: flex;
+    margin-bottom: 30px;
+  }
+  .table-cont {
+    overflow: auto;
+    max-height: calc(100vh - 400px);
+    table {
+      font-size: 14px;
+      color: #666;
+      thead {
+        position: sticky;
+        top: 0;
+        left: 0;
+        border-left: 1px solid #dcdfe6;
+        border-right: 1px solid #dcdfe6;
+        td,
+        th {
+          min-width: 100px;
+          word-break: break-all;
+          border: 1px solid #dcdfe6;
+          outline-color: #dcdfe6;
+          outline-style: solid;
+          outline-width: 0.5px;
+        }
+      }
+      td,
+      th {
+        min-width: 100px;
+        word-break: break-all;
+        border: 1px solid #dcdfe6;
+        height: 45px;
+        text-align: center;
+        background-color: #fff;
+      }
+
+      .head-column {
+        background-color: #f0f2f5;
+      }
+
+      .data-cell {
+        color: #409eff;
+        cursor: pointer;
+      }
+
+      .thead-sticky {
+        position: sticky;
+        top: 0;
+      }
+    }
+    .content-ul {
+      .association {
+        color: #409eff;
+        cursor: pointer;
+      }
+    }
+  }
+  .not-text {
+    height: 300px;
+    line-height: 300px;
+    text-align: center;
+  }
+  .thead-box {
+    position: sticky;
+    top: 0;
+    z-index: 9;
+  }
+}
+</style>

+ 258 - 0
src/views/custom_manage/points/RatingOverview.vue

@@ -0,0 +1,258 @@
+<template>
+  <div class="container rating-overview-content">
+    <div class="top-select">
+      <div class="select-box">
+        <el-date-picker style="width: 220px" v-model="yearValue" value-format="yyyy" type="year" placeholder="请选择年份" :clearable="false" @change="changeHandle"> </el-date-picker>
+        <el-select style="width: 220px; margin: 0 20px" v-model="selectedQuarter" placeholder="请选择季度" @change="changeHandle">
+          <el-option v-for="item in quarterOptions" :key="item.label" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+        <el-input style="width: 220px" placeholder="请输入券商名称" prefix-icon="el-icon-search" v-model="brokerName" @input="inputHandle"> </el-input>
+        <el-select style="width: 220px; margin: 0 20px" v-model="valueLocation" multiple placeholder="请选择城市" @change="changeHandle">
+          <el-option v-for="item in locationOptions" :key="item.name" :label="item.name" :value="item.name"> </el-option>
+        </el-select>
+        <a :href="exportUser" download>
+          <el-button type="primary" style="width: 80px">导出</el-button>
+        </a>
+      </div>
+      <div>
+        <el-button @click="enterScoreType = !enterScoreType" type="primary">{{ enterScoreType ? "原始值显示" : "百分比显示" }} </el-button>
+      </div>
+    </div>
+
+    <div class="table-cont">
+      <template v-if="tableTheadColumns.length">
+        <table class="thead-sticky thead-box">
+          <thead>
+            <tr>
+              <td class="'head-column'"></td>
+              <td v-for="item in tableTheadColumns" :key="item" :class="['head-column']">
+                {{ item.CompanyName }}
+              </td>
+            </tr>
+          </thead>
+          <tbody v-for="(item, index) in datalist" :key="index">
+            <tr>
+              <td class="thead-rs">{{ item.ChartPermissionName }}</td>
+              <td v-for="key in item.ProportionListText" :key="key">{{ key }}</td>
+            </tr>
+            <tr v-for="rs in item.List" :key="rs.RealName" class="content-ul">
+              <td>{{ rs.RealName }}</td>
+              <td v-for="pr in rs.ProportionListText" :key="pr">{{ pr }}</td>
+            </tr>
+          </tbody>
+          <tbody v-for="(item, index) in listGroup" :key="index">
+            <tr>
+              <td class="thead-rs">{{ item.GroupName }}</td>
+              <td v-for="key in item.ProportionListText" :key="key">{{ key }}</td>
+            </tr>
+          </tbody>
+        </table>
+        <template v-if="!datalist.length && !listGroup.length"> <div class="not-text">暂无数据</div> </template>
+      </template>
+      <template v-else> <div class="not-text">暂无数据</div> </template>
+    </div>
+  </div>
+</template>
+
+<script>
+import { customInterence, xClassCustomApi } from "@/api/api.js";
+
+export default {
+  name: "",
+  components: {},
+  props: {},
+  data() {
+    return {
+      yearValue: new Date().getFullYear().toString(), // 年份
+      selectedQuarter: [], // 季度
+      quarterOptions: [
+        {
+          label: "Q1",
+          value: ["01-01", "03-31"],
+        },
+        {
+          label: "Q2",
+          value: ["04-01", "06-30"],
+        },
+        {
+          label: "Q3",
+          value: ["07-01", "09-30"],
+        },
+        {
+          label: "Q4",
+          value: ["10-01", "12-31"],
+        },
+      ],
+      brokerName: "", // 券商名
+      valueLocation: [], //地址
+      tableTheadColumns: [],
+      datalist: [],
+      listGroup: [],
+      enterScoreType: false,
+      locationOptions: [{ name: "北京市" }, { name: "上海市" }, { name: "深圳市" }],
+    };
+  },
+  computed: {
+    exportUser() {
+      let baseUrl = process.env.API_ROOT + "/cygx/enterScore/scoreOverview";
+      let token = localStorage.getItem("auth") || "";
+      const cityArr = [];
+      let paramStr = "";
+      let params = this.paramsHandler();
+      params.IsExport = true;
+      for (let key in params) {
+        paramStr = `${paramStr}&${key}=${params[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+  },
+  watch: {
+    enterScoreType: {
+      handler() {
+        this.getDataList();
+      },
+    },
+  },
+  mounted() {
+    this.setDefaultQuarter();
+
+    this.getDataList();
+  },
+  methods: {
+    setDefaultQuarter() {
+      const currentDate = new Date();
+      const month = currentDate.getMonth() + 1; // 获取当前月份(0-11,所以加1)
+
+      let currentQuarterIndex;
+      if (month >= 1 && month <= 3) {
+        // Q1
+        currentQuarterIndex = 0;
+      } else if (month >= 4 && month <= 6) {
+        // Q2
+        currentQuarterIndex = 1;
+      } else if (month >= 7 && month <= 9) {
+        // Q3
+        currentQuarterIndex = 2;
+      } else if (month >= 10 && month <= 12) {
+        // Q4
+        currentQuarterIndex = 3;
+      }
+
+      // 获取上一个季度索引
+      const previousQuarterIndex = currentQuarterIndex === 0 ? this.quarterOptions.length - 1 : currentQuarterIndex - 1;
+
+      // 设置v-model绑定的值为上一个季度的value数组
+      this.selectedQuarter = this.quarterOptions[previousQuarterIndex].value;
+    },
+
+    getPreviousYear(currentYear, currentQuarter) {
+      // 如果当前季度是第一个季度,则上个季度应该是去年的最后一个季度
+      return currentQuarter === "Q1" ? currentYear - 1 : currentYear;
+    },
+    changeHandle() {
+      this.getDataList();
+    },
+    inputHandle: _.debounce(async function () {
+      this.getDataList();
+    }, 500),
+    async getDataList() {
+      this.tableTheadColumns = [];
+      this.datalist = [];
+      this.listGroup = [];
+      let params = this.paramsHandler();
+      const res = await xClassCustomApi.enterScoreScoreOverview(params);
+      if (res.Ret === 200) {
+        this.tableTheadColumns = res.Data.ListCompany || [];
+        this.datalist = res.Data.ListPermission || [];
+        this.listGroup = res.Data.ListGroup || [];
+      }
+    },
+    // 处理数据, 获取数据
+    paramsHandler() {
+      let params = {
+        StartDate: this.yearValue + "-" + this.selectedQuarter[0],
+        EndDate: this.yearValue + "-" + this.selectedQuarter[1],
+        KeyWord: this.brokerName,
+        City: this.valueLocation.join(","),
+        EnterScoreType: this.enterScoreType ? 2 : 1,
+      };
+      return params;
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.rating-overview-content {
+  .top-select {
+    display: flex;
+    justify-content: space-between;
+  }
+  .select-box {
+    display: flex;
+    margin-bottom: 30px;
+  }
+  .table-cont {
+    max-height: calc(100vh - 400px);
+    overflow: auto;
+    table {
+      font-size: 14px;
+      color: #666;
+      thead {
+        position: sticky;
+        top: 0;
+        left: 0;
+        border-left: 1px solid #dcdfe6;
+        border-right: 1px solid #dcdfe6;
+        td,
+        th {
+          min-width: 100px;
+          word-break: break-all;
+          border: 1px solid #dcdfe6;
+          outline-color: #dcdfe6;
+          outline-style: solid;
+          outline-width: 0.5px;
+        }
+      }
+      td,
+      th {
+        min-width: 100px;
+        word-break: break-all;
+        border: 1px solid #dcdfe6;
+        height: 45px;
+        text-align: center;
+        background-color: #fff;
+      }
+
+      .head-column {
+        background-color: #f0f2f5;
+      }
+
+      .data-cell {
+        color: #409eff;
+        cursor: pointer;
+      }
+
+      .thead-sticky {
+        position: sticky;
+        top: 0;
+      }
+    }
+    .content-ul {
+      .association {
+        color: #409eff;
+        cursor: pointer;
+      }
+    }
+  }
+  .not-text {
+    height: 300px;
+    line-height: 300px;
+    text-align: center;
+  }
+  .thead-box {
+    position: sticky;
+    top: 0;
+    z-index: 9;
+  }
+}
+</style>

+ 85 - 0
src/views/custom_manage/points/XClassCustom.vue

@@ -0,0 +1,85 @@
+<template>
+  <div class="container x-class-custom-content">
+    <el-card>
+      <div class="top-card-box">
+        <div class="tabs-box">
+          <span v-for="item in listTitle" :key="item.value" @click="tabsBoxBtn(item)" :class="item.value == tabsPitchon ? 'pitch' : ''">{{ item.lable }}</span>
+        </div>
+      </div>
+    </el-card>
+    <el-card style="margin-top: 20px">
+      <EntryRecords v-if="tabsPitchon == 1" />
+      <RatingOverview v-if="tabsPitchon == 2" />
+      <RankingOverview v-if="tabsPitchon == 3" />
+    </el-card>
+  </div>
+</template>
+
+<script>
+import EntryRecords from "./EntryRecords.vue"; // 录分
+import RatingOverview from "./RatingOverview.vue"; // 评分
+import RankingOverview from "./RankingOverview.vue"; // 排名
+export default {
+  name: "",
+  components: { EntryRecords, RatingOverview, RankingOverview },
+  props: {},
+  data() {
+    return {
+      listTitle: [
+        {
+          lable: "录分记录",
+          value: "1",
+        },
+        {
+          lable: "评分总览",
+          value: "2",
+        },
+        {
+          lable: "排名总览",
+          value: "3",
+        },
+      ],
+      tabsPitchon: 1, //tabs 默认选中
+    };
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {
+    // 头部的点击事件
+    tabsBoxBtn(item) {
+      this.tabsPitchon = item.value;
+    },
+    // 输入框搜索事件
+    handleSearch() {
+      // this.$refs.recordRefs
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.x-class-custom-content {
+  .top-card-box {
+    display: flex;
+    justify-content: space-between;
+    .tabs-box {
+      span {
+        display: inline-block;
+        padding: 9px 24px;
+        background-color: #e9f4ff;
+        border: 1px solid #b3d8ff;
+        border-radius: 4px;
+        margin-right: 30px;
+        color: #409eff;
+        cursor: pointer;
+      }
+      .pitch {
+        background-color: #409eff;
+        border: none;
+        color: #fff;
+      }
+    }
+  }
+}
+</style>

+ 213 - 0
src/views/dataReport_manage/components/RenewalRateDetail.vue

@@ -0,0 +1,213 @@
+<template>
+  <div class="renewal-rate-detail-content">
+    <el-dialog
+      :visible.sync="showRenewalRateDetailDlg"
+      title="不续约率详情"
+      top="5vh"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      :append-to-body="true"
+      @close="cancelHandle"
+      width="1000px"
+      v-dialogDrag
+      center
+      custom-class="renewal-rate-detail-content-dlg"
+    >
+      <div>
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="确认不续约合同" name="确认不续约合同"></el-tab-pane>
+          <el-tab-pane label="到期合同" name="到期合同"></el-tab-pane>
+        </el-tabs>
+      </div>
+      <p v-if="activeName === '确认不续约合同'">共有确认不续约合同 {{ RenewalDataFormSon.RenewalContractTotal }} 份,不续约总金额 {{ RenewalDataFormSon.RenewalContractMoney }} 元</p>
+      <p v-if="activeName === '到期合同'">共有到期合同 {{ RenewalDataFormSon.ExpireRenewalContractTotal }} 份,到期总金额 {{ RenewalDataFormSon.ExpireRenewalContractMoney }} 元</p>
+      <div class="table-wrap">
+        <el-table :data="RenewalDataFormSon.List" max-height="600" border style="width: 100%; margin-bottom: 20px">
+          <el-table-column label="公司名称" prop="CompanyName" align="center">
+            <template slot-scope="{ row }">
+              <span class="editsty" @click="goCompanyHandle(row)">{{ row.CompanyName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="SellerName" label="所属销售" width="100"> </el-table-column>
+          <el-table-column align="center" prop="Money" label="合同金额" width="130"> </el-table-column>
+          <el-table-column label="合同期限" prop="StartDate" align="center">
+            <template slot-scope="{ row }">
+              <span>{{ row.StartDate }} ~ {{ row.EndDate }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="签约套餐" prop="PermissionName" align="center">
+            <template slot-scope="{ row }">
+              <template v-if="row.PermissionName.length">
+                <el-tag size="mini" style="margin: 0 10px 10px 0" v-for="key in row.PermissionName.split(',')" :key="key">{{ key }}</el-tag>
+              </template>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" prop="Money" label="不续约归因" width="130">
+            <template slot-scope="{ row }">
+              <span style="color: #409eff; cursor: pointer" @click="editReasonLabel(row)">
+                {{ row.AscribeContent }}
+              </span>
+            </template></el-table-column
+          >
+        </el-table>
+        <el-pagination
+          layout="total,prev,pager,next"
+          background
+          :current-page="pageNo"
+          @current-change="handleCurrentChange"
+          :page-size="pageSize"
+          :total="total"
+          style="text-align: right; padding: 20px 0"
+        >
+        </el-pagination>
+      </div>
+    </el-dialog>
+    <el-dialog
+      :visible.sync="isConfirmNoRenewalShowSon"
+      title="确认不续约"
+      top="5vh"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      :append-to-body="true"
+      @close="cancelHandleSon"
+      width="652px"
+      v-dialogDrag
+      center
+      custom-class="custom-class-confirm-no-renewal-show-dlg"
+    >
+      <div class="user-title">{{ confirmNoRenewalFormSon.AscribeContent }}</div>
+      <div class="content-reason">{{ confirmNoRenewalFormSon.Content }}</div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { dataMainInterface } from "@/api/api.js";
+import confirmedNoRenewal from "./noRenewalReasonDia/confirmedNoRenewal.vue";
+
+export default {
+  props: {
+    showRenewalRateDetailDlg: {
+      default: false,
+      type: Boolean,
+    },
+    renewalRateDetailForm: {
+      default: "",
+      type: String,
+    },
+  },
+  data() {
+    return {
+      pageNo: 1,
+      pageSize: 10,
+      total: 0,
+      tableData: [],
+      activeName: "确认不续约合同",
+      RenewalDataFormSon: {},
+      confirmNoRenewalFormSon: {},
+      isConfirmNoRenewalShowSon: false,
+    };
+  },
+  components: {
+    confirmedNoRenewal,
+  },
+  watch: {
+    showRenewalRateDetailDlg: {
+      handler(val) {
+        if (val) {
+          this.getTableData();
+        }
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    cancelHandle() {
+      this.pageNo = 1;
+      this.activeName = "确认不续约合同";
+      this.tableData = [];
+      this.pageNo = 1;
+      this.pageSize = 10;
+      this.total = 0;
+      this.$emit("update:showRenewalRateDetailDlg", false);
+      this.$emit("update:renewalRateDetailForm", {});
+    },
+    async getTableData() {
+      let params = {
+        ...this.renewalRateDetailForm,
+        PageSize: this.pageSize,
+        CurrentIndex: this.pageNo,
+        ContractDataType: this.activeName,
+      };
+      const res = await dataMainInterface.incrementalCompanyContractPercentageListV2(params);
+      if (res.Ret === 200) {
+        this.RenewalDataFormSon = res.Data;
+        this.total = res.Data.Paging.Totals;
+      }
+    },
+    // 分页
+    handleCurrentChange(page) {
+      this.pageNo = page;
+      this.getTableData();
+    },
+    // 去往公司详情
+    goCompanyHandle(row) {
+      let { href } = this.$router.resolve({
+        path: "/customDetail",
+        query: {
+          id: row.CompanyId,
+        },
+      });
+      window.open(href, "_blank");
+    },
+    // 头部的点击事件
+    handleClick() {
+      this.pageNo = 1;
+      this.getTableData();
+    },
+    cancelHandleSon() {
+      this.confirmNoRenewalFormSon = {};
+      this.isConfirmNoRenewalShowSon = false;
+    },
+    editReasonLabel(row) {
+      dataMainInterface.contractInfoNoRenewedAscribe({ CompanyContractId: row.CompanyContractId }).then((res) => {
+        if (res.Ret == 200) {
+          this.confirmNoRenewalFormSon = res.Data.Detail;
+          this.isConfirmNoRenewalShowSon = true;
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.renewal-rate-detail-content-dlg {
+  .table-wrap {
+    margin-top: 20px;
+  }
+  .el-tabs__nav-wrap::after {
+    background-color: #fff;
+  }
+}
+
+.custom-class-confirm-no-renewal-show-dlg {
+  div {
+    box-sizing: border-box;
+  }
+  .user-title {
+    width: 100%;
+    height: 40px;
+    padding-left: 20px;
+    line-height: 40px;
+    border: 1px solid #dcdfe6;
+  }
+  .content-reason {
+    padding: 20px;
+    margin: 20px 0;
+    width: 100%;
+    height: 201px;
+    border: 1px solid #dcdfe6;
+  }
+}
+</style>

+ 162 - 0
src/views/dataReport_manage/components/abnormalRenewalChart.vue

@@ -0,0 +1,162 @@
+<template>
+    <div class="abnormal-renewal-chart-wrap">
+        <div class="top-wrap">
+            <el-date-picker
+                v-model="date"
+                type="monthrange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                :clearable="false"
+                value-format="yyyy-MM"
+                @change="handleDateChange"
+            />
+            <div style="color:#409EFF;cursor: pointer;" @click="handleClose">
+                <img src="~@/assets/img/icons/changeLang.png" alt="">
+                <span style="display:inline-block;position: relative;top:-3px;left:3px">数据表</span>
+            </div>
+        </div>
+        <div class="chart-main-wrap">
+            <h2 style="text-align:center;font-size:30px;margin:30px 0;">续约异常客户统计图</h2>
+            <div class="chart-box" ref="chartBox"></div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { dataMainInterface } from '@/api/api.js';
+import { nextTick } from 'vue';
+export default {
+    data() {
+        return {
+            date:'',
+            myChart:null
+        }
+    },
+    created() {
+        this.date=[this.$moment().format('2023-01'),this.$moment().format('YYYY-MM')]
+    },
+    mounted() {
+        this.getData()
+    },
+    methods: {
+        async getData(){
+            const res=await dataMainInterface.unusualRenewalCustomStatisticChartData({
+                StartDate:this.date[0],
+                EndDate:this.date[1]
+            })
+            if(res.Ret===200){
+                this.$nextTick(()=>{
+                    this.renderChart(res.Data)
+                })
+            }
+        },
+        handleDateChange(){
+            this.getData()
+        },
+        handleClose(){
+            this.$emit('close')
+        },
+        renderChart(data){
+            const arr=data.List||[]
+
+            const options={
+				legend: {
+					name: [],
+                    icon:'circle',
+					left: 'center',
+				},
+				tooltip: {
+                    formatter:function(params){
+                        let str=`${params.name}<br>
+                        <span style='display:inline-block;width:15px;height:15px;background:#FDB863;border-radius:100%'></span>
+                        ${params.seriesName}&nbsp;&nbsp;${params.value}`
+
+                        return str
+                    }
+                },
+				title: {
+					text: '',
+				},
+				color: ['#FDB863'],
+				textStyle: {
+					fontSize: 12,
+				},
+				xAxis: {
+					type: '',
+					data: [],
+					// /* x轴文字 */
+					axisLabel: {
+						show: true,
+						rotate: '40', //字体倾斜
+						textStyle: {
+							color: '#999', //更改坐标轴文字颜色
+							fontSize: 12, //更改坐标轴文字大小
+						},
+					},
+				},
+				yAxis: {
+					type: 'value',
+					minInterval:1,
+                    position: 'left',
+                    name:'家',
+                    splitLine:{
+                        lineStyle:{
+                            type:'dotted'
+                        }
+                    }
+				},
+				series: [
+                    {
+                        data:[],
+                        name:'续约异常客户合计',
+                        type:'bar',
+                        yAxisIndex: 0,
+                    }
+                ],
+			}
+
+            arr.forEach(item => {
+                options.xAxis.data.push(item.Date)
+                options.series[0].data.push(item.CompanyNum)
+            });
+
+            console.log(options);
+
+            const chart = this.$refs.chartBox;
+            if(chart){
+                this.$nextTick(()=>{
+                    if(!this.myChart){
+                        this.myChart = echarts.init(chart);
+                        this.myChart.setOption(options);
+                    }else{
+                        this.myChart.setOption(options,true);
+                    }
+                    
+                })
+            }
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.abnormal-renewal-chart-wrap{
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: #fff;
+    padding: 30px;
+    .top-wrap{
+        display: flex;
+        justify-content: space-between;
+    }
+    .chart-box{
+        margin: 0 auto;
+        width: 80%;
+        height: 500px;
+    }
+}
+</style>

+ 142 - 42
src/views/dataReport_manage/equityCustomStatistics.vue

@@ -30,38 +30,72 @@
         </el-cascader>
       </div>
       <div class="main-section">
-        <el-row :gutter="36">
-          <el-col :span="8" v-for="item in data_typeArr" :key="item.label">
-            <el-card :class="['base-card', { 'main-card': filterObj.data_type === item.label }]" shadow="hover" @click.native="toggleType(item.label)">
-              <div slot="header" class="clearfix">
-                <span>
-                  {{ lableTextDisplay(item.label) }}数
-                  <el-tooltip
-                    class="item"
-                    effect="dark"
-                    :content="
-                      item.label === '新签客户' ? '起始时间在所选时间段内的新签合同' : item.label === '续约客户' ? '起始时间在所选时间段内的续约合同' : '合同截止时间在所选时间段内的非正式、非永续客户'
-                    "
-                    placement="top"
-                  >
-                    <i class="el-icon-info"></i>
-                  </el-tooltip>
-                </span>
-              </div>
-              <div class="card-cont">
-                {{
-                  item.label === "新签客户"
-                    ? NewCompanyTotal
-                    : item.label === "续约客户"
-                    ? RenewalCompanyTotal
-                    : item.label === "未续约客户"
-                    ? NotRenewalCompanyTotal + " / " + NotRenewalCompanyToBeConfirmTotal
-                    : ""
-                }}
-              </div>
-            </el-card>
-          </el-col>
-        </el-row>
+        <div v-for="item in data_typeArr" :key="item.label">
+          <el-card style="margin-right: 50px" :class="['base-card', { 'main-card': filterObj.data_type === item.label }]" shadow="hover" @click.native="toggleType(item.label)">
+            <div slot="header" class="clearfix">
+              <span>
+                {{ lableTextDisplay(item.label) }}数
+                <el-tooltip class="item" effect="dark" :content="item.label === '新签客户' ? '<br />' : item.label === '续约客户' ? '起始时间在所选时间段内的续约合同' : ''" placement="top">
+                  <template slot="content">
+                    <div v-if="item.label === '新签客户'">
+                      <p>起始时间在所选时间段内的新签合同</p>
+                      <p>(第一份合同起始时间一年内的再次签约仍属于新签合同)</p>
+                    </div>
+                    <div v-else-if="item.label === '续约客户'">
+                      <p>起始时间在所选时间段内的续约合同</p>
+                      <p>(第一份合同起始时间一年以后的再次签约均属于续约合同)</p>
+                    </div>
+                    <p v-else>合同截止时间在所选时间段内的非正式、非永续客户</p>
+                  </template>
+                  <i class="el-icon-info"></i>
+                </el-tooltip>
+              </span>
+            </div>
+            <div class="card-cont">
+              {{
+                item.label === "新签客户"
+                  ? NewCompanyTotal
+                  : item.label === "续约客户"
+                  ? RenewalCompanyTotal
+                  : item.label === "未续约客户"
+                  ? NotRenewalCompanyTotal + " / " + NotRenewalCompanyToBeConfirmTotal
+                  : ""
+              }}
+            </div>
+          </el-card>
+        </div>
+        <div class="annual-select-content">
+          <div class="select-content">
+            <div class="lable-text">
+              不续约率
+              <el-tooltip style="margin-right: 16px" class="item" effect="dark" content="所选年度的续约合同/所选年度的到期合同" placement="top-start">
+                <template slot="content">
+                  <div>
+                    <p>所选时间段的已确认不续约的合同金额/所选时间段的到期的合同金额</p>
+                    <p>(剔除非业务不续约的金额)</p>
+                  </div>
+                </template>
+                <i class="el-icon-info" style="color: #999"></i>
+              </el-tooltip>
+            </div>
+            <el-date-picker
+              v-model="yearValue"
+              type="daterange"
+              format="yyyy-MM-dd"
+              value-format="yyyy-MM-dd"
+              :clearable="false"
+              @change="getIncrementalCompanyContractPercentageList"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+            >
+            </el-date-picker>
+          </div>
+          <div class="select-content">
+            <span class="editsty" v-if="RenewalDataForm.RenewalRateMoney" @click="renewalRateLableHandler">&nbsp;&nbsp;{{ RenewalDataForm.RenewalRateMoney }}&nbsp;&nbsp;</span>
+            {{ RenewalDataForm.RenewalRateTotalContent ? `(${RenewalDataForm.RenewalRateTotalContent})` : " -  -" }}
+          </div>
+        </div>
       </div>
       <div class="tabs-box" v-if="filterObj.data_type == '续约客户'">
         <div class="tabs-box-confirm">
@@ -81,9 +115,6 @@
           <el-select v-model="noRenewalReasonId" placeholder="请选择不续约归因" clearable @change="getTableData" style="width: 240px; margin-right: 50px">
             <el-option :label="item.AscribeContent" :value="item.CompanyAscribeId" v-for="item in noRenewalReasonList" :key="item.reasonId"></el-option>
           </el-select>
-          <!-- <span @click="tabsHandler(item)" :class="tabsActiveName === item.value ? 'active' : ''" v-for="item in tabsList" :key="item">
-            {{ item.name }}({{ item.name === "试用" ? NotRenewalTryOut : NotRenewalNotTryOut }})
-          </span> -->
           <el-select v-model="tabsActiveName" placeholder="当前状态" clearable @change="getTableData" style="width: 240px; margin-right: 50px">
             <el-option :label="item.name" :value="item.value" v-for="item in tabsList" :key="item.value"></el-option>
           </el-select>
@@ -168,8 +199,10 @@
       :noRenewalReasonList="noRenewalReasonList"
       @refreshReasonList="getNORenewalReasonList"
       @saveLabel="saveLabel"
+      equityType="权益客户统计"
     />
     <previous-detail :previousDetailDlg.sync="previousDetailDlg" :rowInfo="rowInfo" />
+    <RenewalRateDetail :showRenewalRateDetailDlg.sync="showRenewalRateDetailDlg" :renewalRateDetailForm.sync="renewalRateDetailForm" :noRenewalReasonListSon="noRenewalReasonList" />
   </div>
 </template>
 
@@ -182,12 +215,12 @@ import addRemark from "./components/noRenewalReasonDia/addRemark.vue";
 import viewRemark from "./components/noRenewalReasonDia/viewRemark.vue";
 import confirmedNoRenewal from "./components/noRenewalReasonDia/confirmedNoRenewal.vue";
 import PreviousDetail from "./components/previousDetail.vue";
-
+import RenewalRateDetail from "./components/renewalRateDetail.vue";
 var moment = require("moment");
 moment().format();
 export default {
   name: "",
-  components: { mPage, renewalListDia, addRemark, viewRemark, confirmedNoRenewal, PreviousDetail },
+  components: { mPage, renewalListDia, addRemark, viewRemark, confirmedNoRenewal, PreviousDetail, RenewalRateDetail },
   computed: {
     exportExcel() {
       let baseUrl = process.env.API_ROOT + "/statistic_report/merge_company_list";
@@ -306,6 +339,10 @@ export default {
       PackageDifference: "",
       previousDetailDlg: false,
       packageTypeList: ["增加套餐", "减少套餐", "维持套餐"],
+      yearValue: "",
+      showRenewalRateDetailDlg: false,
+      renewalRateDetailForm: {},
+      RenewalDataForm: {},
     };
   },
   /* 页面跳转前记录参数 */
@@ -461,6 +498,9 @@ export default {
       this.page_no = 1;
       this.searchVal = "";
       this.getTableData();
+      if (this.yearValue.length > 0) {
+        this.getIncrementalCompanyContractPercentageList();
+      }
     },
     /* 切换页码 */
     handleCurrentChange(page) {
@@ -546,7 +586,7 @@ export default {
       this.isConfirmNoRenewalShow = true;
     },
     editReasonLabel(row) {
-      dataMainInterface.infoNoRenewedAscribe({ CompanyId: row.CompanyId, ProductId: row.ProductId }).then((res) => {
+      dataMainInterface.contractInfoNoRenewedAscribe({ CompanyContractId: row.CompanyContractId }).then((res) => {
         if (res.Ret == 200) {
           this.confirmNoRenewalForm.reason = res.Data.Detail ? res.Data.Detail.CompanyAscribeId || "" : "";
           this.confirmNoRenewalForm.detailReason = res.Data.Detail ? res.Data.Detail.Content || "" : "";
@@ -557,12 +597,11 @@ export default {
     },
     saveLabel(item) {
       let params = {
-        CompanyId: this.selectItemRow.CompanyId,
-        ProductId: this.selectItemRow.ProductId,
+        CompanyContractId: this.selectItemRow.CompanyContractId,
         CompanyAscribeId: item.CompanyAscribeId,
         Content: item.Content,
       };
-      dataMainInterface.addNoRenewedAscribe(params).then((res) => {
+      dataMainInterface.addAscribContract(params).then((res) => {
         if (res.Ret == 200) {
           this.$message.success("确认成功");
           this.isConfirmNoRenewalShow = false;
@@ -572,7 +611,6 @@ export default {
       });
     },
     previousDetailHadler(row) {
-      console.log(123);
       this.rowInfo = row;
       this.previousDetailDlg = true;
     },
@@ -580,6 +618,39 @@ export default {
       let str = text == "新签客户" ? "新签合同" : text == "续约客户" ? "续约合同" : "未续约客户";
       return str;
     },
+    // 年度续约的标签点击事件
+    annualSelectHandler(item) {
+      this.annualSelectActivue = item.name;
+      this.getIncrementalCompanyContractPercentageList();
+    },
+    // 点击了续约率
+    renewalRateLableHandler() {
+      this.showRenewalRateDetailDlg = true;
+      this.renewalRateDetailForm = this.initCompanyContractPercentageList();
+    },
+    // 获取年度续约的数据
+    async getIncrementalCompanyContractPercentageList() {
+      let params = this.initCompanyContractPercentageList();
+      const res = await dataMainInterface.incrementalCompanyContractPercentageListV2(params);
+      if (res.Ret === 200) {
+        this.RenewalDataForm = res.Data;
+      }
+    },
+    // 处理年度续约的数据
+    initCompanyContractPercentageList() {
+      let salesArr = [];
+      if (this.filterObj.sale.length) {
+        salesArr = this.filterObj.sale.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let params = {
+        EndDate: this.yearValue.length > 0 ? this.yearValue[1] : "",
+        StartDate: this.yearValue.length > 0 ? this.yearValue[0] : "",
+        AdminId: salesArr.join(","),
+      };
+      return params;
+    },
   },
   created() {},
   mounted() {
@@ -659,6 +730,35 @@ export default {
 .package-difference {
   cursor: pointer;
 }
+.annual-select-content {
+  .select-content {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15px;
+    .lable-text {
+      flex-shrink: 0;
+    }
+    .select-lable {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      box-sizing: border-box;
+      margin-left: 10px;
+      width: 92px;
+      height: 40px;
+      color: #409eff;
+      background-color: #ecf5ff;
+      border: 1px solid #b3d8ff;
+      border-radius: 4px;
+      cursor: pointer;
+    }
+    .act-select-lable {
+      color: #fff;
+      background-color: #409eff;
+      border: none;
+    }
+  }
+}
 </style>
 <style lang="scss">
 #dataReport-container {

+ 466 - 0
src/views/dataReport_manage/equityPackageStatistics.vue

@@ -0,0 +1,466 @@
+<template>
+  <div class="dataReport-container" id="dataReport-container">
+    <div class="dataReport-top">
+      <a :href="exportExcel" download>
+        <button class="button-sty act">导出EXCEL</button>
+      </a>
+      <button :class="['button-sty', { act: filterObj.month === item.label }]" v-for="item in monthLabel" @click="toggleMonth(item.label)" :key="item.label">
+        {{ item.label }}
+      </button>
+      <date-picker v-model="filterObj.date" type="date" range value-type="format" placeholder="自定义时间段" :clearable="false" :editable="false" @change="dateChange" />
+      <el-input placeholder="请输入客户名称" v-model="searchVal" style="width: 400px; margin-left: auto" @input="handleSearch" clearable>
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </div>
+    <div class="dataReport-main">
+      <div class="main-top">
+        <el-cascader
+          v-if="Role == 'finance' || Role == 'admin' || Role == 'ficc_admin' || Role == 'rai_admin' || ManageType != 0"
+          v-model="filterObj.sale"
+          placeholder="请选择销售"
+          style="min-width: 250px; margin-right: 10px; margin-bottom: 8px"
+          :options="salesArr"
+          :props="defaultSalesProps"
+          :show-all-levels="false"
+          collapse-tags
+          clearable
+          filterable
+          @change="changeFilter"
+        >
+        </el-cascader>
+      </div>
+      <div class="main-section">
+        <el-row :gutter="36">
+          <el-col :span="8" v-for="item in data_typeArr" :key="item.label">
+            <el-card :class="['base-card', { 'main-card': filterObj.data_type === item.label }]" shadow="hover" @click.native="toggleType(item.label)">
+              <div slot="header" class="clearfix">
+                <span>
+                  {{ item.label }}
+                  <el-tooltip
+                    class="item"
+                    effect="dark"
+                    :content="
+                      item.label === '行业新签'
+                        ? '行业合同开始时间在查询时间段内,且该行业在历史上没有转正记录'
+                        : item.label === '行业续约'
+                        ? '行业合同开始时间在查询时间段内,且该行业历史上有过正式到期记录'
+                        : '行业合同到期时间在查询时间段内,且该行业当前状态是非正式状态'
+                    "
+                    placement="top"
+                  >
+                    <i class="el-icon-info"></i>
+                  </el-tooltip>
+                </span>
+              </div>
+              <div class="card-cont">
+                {{ item.label === "行业新签" ? NewCompanyTotal : item.label === "行业续约" ? RenewalCompanyTotal : item.label === "行业未续约" ? NotRenewalCompanyTotal : "" }}
+              </div>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+      <div class="tabs-content-box">
+        <span v-for="item in listPermissionName" :key="item.ChartPermissionId" @click="tabsBoxBtn(item)" :class="item.PermissionName == tabsPitchon ? 'pitch' : ''">
+          {{ item.PermissionName }} ({{ item.Total }})
+        </span>
+      </div>
+      <el-table :data="tableData" border style="margin-top: 20px; min-height: 400px" v-loading="isShowloadding" element-loading-text="数据加载中...">
+        <el-table-column label="公司名称" prop="CompanyName" align="center">
+          <template slot-scope="{ row }">
+            <span class="editsty" @click="goCompanyHandle(row)">{{ row.CompanyName }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column width="100" label="所属销售" prop="SellerName" align="center"> </el-table-column>
+        <el-table-column label="合同金额" prop="Money" align="center"> </el-table-column>
+        <el-table-column label="合同期限" prop="StartDate" align="center">
+          <template slot-scope="{ row }">
+            <span>{{ row.StartDate }} ~ {{ row.EndDate }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="签约套餐" prop="PermissionName" align="center">
+          <template slot-scope="{ row }">
+            <template v-if="row.PermissionName.length">
+              <el-tag size="mini" style="margin: 0 10px 10px 0" v-for="key in row.PermissionName.split(',')" :key="key">{{ key }}</el-tag>
+            </template>
+          </template>
+        </el-table-column>
+        <template v-if="filterObj.data_type == '行业未续约'">
+          <el-table-column width="118" label="当前行业状态" prop="PermissionNameStatus" align="center"> </el-table-column>
+          <el-table-column width="118" label="当前客户状态" prop="CompanyProductStatus" align="center"> </el-table-column>
+        </template>
+      </el-table>
+      <el-col :span="24" class="toolbar" v-if="total">
+        <m-page :total="total" :page_no="page_no" @handleCurrentChange="handleCurrentChange" />
+      </el-col>
+    </div>
+  </div>
+</template>
+
+<script>
+import { equityTableColums } from "./configdata.js";
+import { dataMainInterface, customInterence } from "@/api/api.js";
+import mPage from "@/components/mPage.vue";
+var moment = require("moment");
+moment().format();
+export default {
+  name: "",
+  components: { mPage },
+  computed: {
+    exportExcel() {
+      let baseUrl = process.env.API_ROOT + "/statistic_report/merge_company/company_contract_permission/list";
+      let token = localStorage.getItem("auth") || "";
+      let paramStr = "";
+      // 处理销售筛选
+      let salesArr = [];
+      if (this.filterObj.sale.length) {
+        salesArr = this.filterObj.sale.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let obj = {
+        IsExport: true,
+        Keyword: this.searchVal,
+        AdminId: salesArr.join(","),
+        EndDate: this.end_date,
+        StartDate: this.start_date,
+        DataType: this.filterObj.data_type,
+        PermissionName: this.tabsPitchon,
+      };
+      for (let key in obj) {
+        paramStr = `${paramStr}&${key}=${obj[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+    Role() {
+      let role = localStorage.getItem("Role") || "";
+      return role;
+    },
+    //管理权限
+    ManageType() {
+      return localStorage.getItem("ManageType") || "";
+    },
+    //确认未续约权限
+    canConfirmNotRenewed() {
+      return ["admin", "rai_admin"].includes(this.Role);
+    },
+  },
+  data() {
+    return {
+      searchVal: sessionStorage.getItem("incrementBack") ? JSON.parse(sessionStorage.getItem("incrementBack")).searchVal : "",
+      tableData: [],
+      isShowloadding: false,
+      start_date: "",
+      end_date: "",
+      /* 筛选条件 */
+      filterObj: {
+        month: "近1个月",
+        date: [],
+        sale: "",
+        data_type: "行业新签",
+      },
+      monthLabel: [
+        {
+          label: "近1个月",
+        },
+        {
+          label: "近2个月",
+        },
+        {
+          label: "近3个月",
+        },
+      ],
+      salesArr: [], //销售列表
+      defaultSalesProps: {
+        multiple: true,
+        label: "RealName",
+        children: "ChildrenList",
+        value: "AdminId",
+      }, //销售级联配置
+      pageSize: 10,
+      page_no: sessionStorage.getItem("incrementBack") ? JSON.parse(sessionStorage.getItem("incrementBack")).page_no : 1,
+      total: 0,
+      data_typeArr: [
+        {
+          label: "行业新签",
+        },
+        {
+          label: "行业续约",
+        },
+        {
+          label: "行业未续约",
+        },
+      ], //数据类型
+      NewCompanyTotal: 0, //行业新签数
+      NotRenewalCompanyTotal: 0, //行业未续约数
+      RenewalCompanyTotal: 0, //行业续约数
+      listPermissionName: [],
+      tabsPitchon: "医药",
+    };
+  },
+  /* 页面跳转前记录参数 */
+  beforeRouteLeave(to, form, next) {
+    let backData = {
+      page_no: this.page_no,
+      end_date: this.end_date,
+      start_date: this.start_date,
+      filterObj: this.filterObj,
+    };
+    sessionStorage.setItem("incrementBack", JSON.stringify(backData));
+    next();
+  },
+  /* 页面进入前是否清除参数 */
+  beforeRouteEnter(to, from, next) {
+    if (from.path != "/customDetail") {
+      sessionStorage.removeItem("incrementBack");
+    }
+    next();
+  },
+  methods: {
+    // 搜索
+    handleSearch() {
+      if (!this.searchVal) {
+        this.page_no = 1;
+        this.filterObj = {
+          month: "近1个月",
+          date: [],
+          sale: "",
+          data_type: this.filterObj.data_type,
+        };
+        let date_before = moment().subtract(1, "M").format("YYYY-MM-DD");
+        let date_now = moment().format("YYYY-MM-DD");
+        let date = [date_before, date_now];
+        this.start_date = date_before;
+        this.end_date = date_now;
+        this.filterObj.date = date;
+        this.getTableData();
+        return;
+      }
+      this.page_no = 1;
+      this.filterObj = {
+        month: "",
+        date: [],
+        sale: "",
+        data_type: this.filterObj.data_type,
+      };
+      this.start_date = "";
+      this.end_date = "";
+      this.getTableData();
+    },
+    /* 获取表格 */
+    getTableData() {
+      this.isShowloadding = true;
+      // 处理销售筛选
+      let salesArr = [];
+      if (this.filterObj.sale.length) {
+        salesArr = this.filterObj.sale.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let params = {
+        Keyword: this.searchVal,
+        PageSize: this.pageSize,
+        CurrentIndex: this.page_no,
+        AdminId: salesArr.join(","),
+        EndDate: this.end_date,
+        StartDate: this.start_date,
+        DataType: this.filterObj.data_type,
+        PermissionName: this.tabsPitchon,
+      };
+      dataMainInterface.incrementalCompanyContractPermissionList(params).then((res) => {
+        if (res.Ret === 200) {
+          this.tableData = res.Data.List || [];
+          this.total = res.Data.Paging.Totals;
+          this.NewCompanyTotal = res.Data.NewCompanyTotal;
+          this.RenewalCompanyTotal = res.Data.RenewalCompanyTotal;
+          this.NotRenewalCompanyTotal = res.Data.NotRenewalCompanyTotal;
+          this.isShowloadding = false;
+          this.listPermissionName = res.Data.ListPermissionName;
+        }
+      });
+    },
+    /* 获取销售 */
+    getSale() {
+      customInterence.getSalesRaiData().then((res) => {
+        if (res.Ret === 200) {
+          this.salesArr = res.Data.List;
+        }
+      });
+    },
+    /* 切换月份 */
+    toggleMonth(label) {
+      this.filterObj.month = label;
+      let days = label == "近1个月" ? 1 : label == "近2个月" ? 2 : label == "近3个月" ? 3 : 0;
+      this.filterDate(days);
+    },
+    /* 选择服务日期 */
+    dateChange(e) {
+      if (e[0]) {
+        this.start_date = e[0];
+        this.end_date = e[1];
+      } else {
+        this.start_date = "";
+        this.end_date = "";
+      }
+      this.filterObj.month = "";
+      this.page_no = 1;
+      this.searchVal = "";
+      this.getTableData();
+    },
+    /* 切换数据类型 */
+    toggleType(label) {
+      this.tabsPitchon = "医药";
+      this.filterObj.data_type = label;
+      this.page_no = 1;
+      this.getTableData();
+    },
+    /* 筛选改变时 */
+    changeFilter() {
+      this.page_no = 1;
+      this.searchVal = "";
+      this.getTableData();
+    },
+    /* 切换页码 */
+    handleCurrentChange(page) {
+      this.page_no = page;
+      this.getTableData();
+    },
+    /* 获取近几个月的日期范围 */
+    filterDate(month) {
+      if (month) {
+        let date_before = moment().subtract(month, "M").format("YYYY-MM-DD");
+        let date_now = moment().format("YYYY-MM-DD");
+        let date = [date_before, date_now];
+        this.start_date = date_before;
+        this.end_date = date_now;
+        this.filterObj.date = date;
+        this.page_no = 1;
+        this.searchVal = "";
+        this.getTableData();
+      }
+    },
+    tabsBoxBtn(item) {
+      this.tabsPitchon = item.PermissionName;
+      this.changeFilter();
+    },
+    // 去往公司详情
+    goCompanyHandle(row) {
+      let { href } = this.$router.resolve({
+        path: "/customDetail",
+        query: {
+          id: row.CompanyId,
+        },
+      });
+      window.open(href, "_blank");
+    },
+  },
+  created() {},
+  mounted() {
+    this.getSale();
+    if (sessionStorage.getItem("incrementBack")) {
+      let backData = JSON.parse(sessionStorage.getItem("incrementBack"));
+      this.page_no = backData.page_no;
+      this.end_date = backData.end_date;
+      this.start_date = backData.start_date;
+      this.filterObj = backData.filterObj;
+      this.searchVal = backData.searchVal;
+    }
+    /* 默认选中近1个月 */
+    this.filterDate(this.filterObj.month === "近1个月" ? 1 : this.filterObj.month === "近2个月" ? 2 : this.filterObj.month === "近3个月" ? 3 : 0);
+  },
+};
+</script>
+<style lang="scss" scoped>
+@import "./index.scss";
+.tabs-box {
+  flex-direction: column;
+  .tabs-box-confirm {
+    display: flex;
+    align-items: center;
+    margin-bottom: 20px;
+    .center-line {
+      width: 1px;
+      height: 21px;
+      background-color: #333333;
+      margin: 0 20px;
+    }
+    .confirm-box-li {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      cursor: pointer;
+      width: 120px;
+      height: 40px;
+      border-radius: 4px;
+    }
+    .active {
+      background-color: #409eff;
+      color: #fff;
+    }
+  }
+}
+.operation-button {
+  color: #409eff;
+  cursor: pointer;
+  font-size: 14px;
+  margin-right: 10px;
+}
+.remark-row {
+  display: flex;
+  justify-content: center;
+  .remark-text {
+    width: 18px;
+    height: 18px;
+    margin-right: 8px;
+    font-size: 18px;
+    color: #409eff;
+    cursor: pointer;
+  }
+}
+.operation-row {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-wrap: wrap;
+  .operation-button {
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+}
+.package-difference {
+  cursor: pointer;
+}
+.tabs-content-box {
+  margin-top: 20px;
+  span {
+    display: inline-block;
+    padding: 9px 24px;
+    background-color: #e9f4ff;
+    border: 1px solid #b3d8ff;
+    border-radius: 4px;
+    margin-right: 30px;
+    color: #409eff;
+    cursor: pointer;
+  }
+  .pitch {
+    background-color: #409eff;
+    border: none;
+    color: #fff;
+  }
+}
+</style>
+<style lang="scss">
+#dataReport-container {
+  .tabs-box {
+    .el-radio-button {
+      margin-right: 0;
+    }
+    .el-radio-button .el-radio-button__inner {
+      border: none;
+      width: 120px;
+      height: 40px;
+      border-radius: 4px;
+    }
+  }
+}
+</style>

+ 1 - 0
src/views/dataReport_manage/index.scss

@@ -18,6 +18,7 @@
 			color: #2D8CF0;
 			cursor: pointer;
 			border-radius:4px;
+			flex-shrink: 0;
 			&.act {
 				background: #409EFF;
 				color: #fff;

+ 197 - 0
src/views/dataReport_manage/statistic/abnormalRenewal.vue

@@ -0,0 +1,197 @@
+<template>
+    <div class="statistic-container" ref="reference">
+        <div style="margin-bottom:20px;">
+
+            <el-radio-group v-model="actFilterDay" @input="val => { actFilterDay=val;getTableData() }">
+                <el-radio-button 
+                    :label="item.value" 
+                    v-for="item in filterDaysOptions" 
+                    :key="item.value"
+                >{{item.label}}</el-radio-button>
+            </el-radio-group>
+        </div>
+
+        <div class="frequency-cont" style="position: relative;">
+            <el-tabs v-model="default_tab" @tab-click="item =>{changeTabHandle(item.name)}" style="margin-right:20px">
+                <el-tab-pane 
+                    v-for="tab in staticTabs" 
+                    :key="tab" 
+                    :label="tab" 
+                    :name="tab"
+                />
+            </el-tabs>
+			<date-picker
+                v-model="select_date"
+                type="date" 
+                range
+                value-type="format"
+                :clearable="false"
+                @change="dateChange"
+                placeholder="请选择统计时间"
+            />
+            <span style="color:#A3A3A3;display:inline-block;margin-left:20px">续约异常:{{filterDaysOptions.find(_=>_.value===actFilterDay).msg}}</span>
+
+            <div style="color:#409EFF;position: absolute;top:10px;right:10px;cursor: pointer;" @click="showChart=true" v-if="actFilterDay===1">
+                <img src="~@/assets/img/icons/changeLang.png" alt="">
+                <span style="display:inline-block;position: relative;top:-3px;left:3px">统计图</span>
+            </div>
+        </div>
+        <div class="table-cont" v-show="dataLoading">
+            <div class="table-body-wrapper">
+                <table>
+                    <thead>
+						<tr>
+							<td class="thead-rs">销售</td>
+                            <td 
+                                v-for="item in tableThead"
+								:key="item" 
+								class="head-column"
+                            >{{item}}</td>
+						</tr>
+					</thead>
+                    <tbody>
+                        <tr v-for="rs in sellerList" :key="rs.SellerId">
+                            <td class="thead-rs">{{rs.SellerName}}</td>
+                            <td 
+								:class="['data-cell',{link: data.UnusualRenewNum}]" 
+								v-for="data,index in rs.CompanyRenewRecordNumList" 
+								:key="data.UnusualRenewIds"
+							>		
+								<span 
+									@click="goList(data,index,rs)"
+								>
+									{{ data.UnusualRenewNum !== 0 ? data.UnusualRenewNum : '' }}
+								</span>
+							</td>
+                        </tr>
+                    </tbody>
+                    <tfoot>
+                        <tr>
+                            <td>合计</td>
+                            <td 
+                                :class="['data-cell',{link: item.UnusualRenewNum}]" 
+                                v-for="item,index in summaryList" 
+                                :key="item.UnusualRenewIds"
+                            >
+                                <span
+                                    @click="goList(item,index,{SellerName:'合计'})"
+                                >
+                                    {{item.UnusualRenewNum||''}}
+                                </span>
+                            </td>
+                        </tr>
+                        <tr v-if="actFilterDay===1">
+                            <td>
+                                <span>异常率</span>
+                                <el-tooltip 
+									effect="dark" 
+									placement="top-start" 
+									content="异常率=当期续约异常客户总数/截止当期系统中存量客户总数"
+								>
+									<i class="el-icon-info"/>
+								</el-tooltip>
+                            </td>
+                            <td v-for="item in summaryList" :key="item.UnusualRenewIds">{{item.UnusualRate||''}}</td>
+                        </tr>
+                    </tfoot>
+                </table>
+            </div>
+        </div>
+        <abnormalRenewalChart v-if="showChart" @close="showChart=false"/>
+    </div>
+</template>
+
+<script>
+import { dataMainInterface } from '@/api/api.js';
+import mixin from './mixin';
+import abnormalRenewalChart from '../components/abnormalRenewalChart.vue';
+export default {
+    name:'abnormalRenewal',
+    mixins: [ mixin ],
+    components:{abnormalRenewalChart},
+    computed:{
+        tableThead:function(){
+            if(['周度统计表','月度统计表'].includes(this.default_tab)){
+                return this.tableTheadColumns
+            }
+            return ['续约异常']
+        }
+    },
+
+    data() {
+        return {
+            sellerList:[],
+            summaryList:[],
+            showChart:false,
+        }
+    },
+    created() {
+        this.getTableData()
+    },
+    methods:{
+
+        getTableData(){
+            this.dataLoading=true
+            this.sellerList=[]
+            this.summaryList=[]
+            dataMainInterface.unusualRenewalCustomStatistic({
+                DataType: this.default_tab === '周度统计表' ? 'week' : this.default_tab === '月度统计表' ? 'month' : 'time_interval',
+				StartDate: this.select_date ? this.select_date[0] : '',
+				EndDate: this.select_date ? this.select_date[1] : '',
+                Source: this.actFilterDay
+            }).then(res=>{
+                const { Data,Ret } = res;
+				if(Ret !== 200) return
+                this.sellerList=Data.List||[]
+                this.summaryList=Data.SummaryList||[]
+            })
+        },
+
+        /* 进入列表 */
+        goList({UnusualRenewNum,UnusualRenewIds},index,parent) {
+            // if(!value) return
+            let column_title = this.getColumnTitle(index);
+            let filterDay = this.filterDaysOptions.find(_=>_.value===this.actFilterDay) ? `${this.filterDaysOptions.find(_=>_.value===this.actFilterDay).label}/` : ''
+            let title=encodeURIComponent(`${filterDay}${column_title}/${parent.SellerName}`);
+                    
+            sessionStorage.setItem('renewalTab',this.activeTab.tabName)
+            const{href}=this.$router.resolve({
+                path: '/abnormalRenewalCustomlist',
+                query: {
+                    ids: encodeURIComponent(UnusualRenewIds),
+                    title
+                }
+            })
+            window.open(href,'_blank')
+        },
+
+        /* 获取数据对应表头 */
+        getColumnTitle(index) {
+			let title = '';
+
+			if(['周度统计表','月度统计表'].includes(this.default_tab)) {
+				title=this.tableTheadColumns[index] 
+			} else {
+				title = this.default_tab || `${this.select_date[0]}~${this.select_date[1]}`;
+			}
+			
+			return title
+		}
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+@import './index.scss';
+.statistic-container{
+    height: calc(100vh - 180px);
+    position: relative;
+}
+</style>
+<style lang="scss">
+.statistic-container{
+    .el-tabs__header {
+        margin-bottom: 0 !important;
+    }
+}    
+</style>

+ 106 - 28
src/views/dataReport_manage/statistic/contractCustom.vue

@@ -99,34 +99,40 @@
 							<td rowspan="2" class="thead-rs">组别</td>
 							<td rowspan="2" class="thead-rs">销售</td>
 							<td rowspan="2" class="thead-rs-typeTwo">
-				未续约
-				<el-tooltip 
+								未续约
+								<el-tooltip 
 									effect="dark" 
 									placement="top-start" 
 									:content="tipMap.get('未续约')"
-					v-if="['周度统计表'].includes(default_tab)"
 								>
-					<i class="el-icon-info"/>
+									<i class="el-icon-info"/>
 								</el-tooltip>
-				</td>
+							</td>
 							<td rowspan="2" class="thead-rs-typeTwo">
-				续约跟进
-				<el-tooltip 
+								续约跟进
+								<el-tooltip 
 									effect="dark" 
 									placement="top-start" 
 									:content="tipMap.get('续约跟进')"
-					v-if="['周度统计表'].includes(default_tab)"
 								>
-					<i class="el-icon-info"/>
+									<i class="el-icon-info"/>
 								</el-tooltip>
-				</td>
+							</td>
 							<td
-								:colspan="['周度统计表','月度统计表'].includes(default_tab) ? 2 : 1"
+								:colspan="['周度统计表','月度统计表'].includes(default_tab) ? activeTab.tabName !== 'QY'? 3:2 : 1"
 								v-for="item in contractTableThead"
 								:key="item" 
 								class="head-column"
 							>
 								{{item}}
+								<el-tooltip 
+									effect="dark" 
+									placement="top-start"
+									v-if="!['周度统计表','月度统计表'].includes(default_tab)"
+									:content="tipMap.get(item)"
+								>
+									<i class="el-icon-info"/>
+								</el-tooltip>
 							</td>	
 						</tr>
 						<tr v-if="['周度统计表'].includes(default_tab)">
@@ -153,12 +159,54 @@
 										<i class="el-icon-info"/>
 									</el-tooltip>
 								</td>
+								<td :key="index+'_2'" v-if="activeTab.tabName !== 'QY'">
+									续约异常
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('续约异常')"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
 							</template>
 						</tr>
 						<tr v-else-if="['月度统计表'].includes(default_tab)">
 							<template v-for="(item,index) in new Array(6).fill('')">
-								<td :key="index+'_0'">到期</td>
-								<td :key="index+'_1'">续约</td>
+								<td :key="index+'_0'">
+									到期
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('到期')"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
+								<td :key="index+'_1'">
+									续约
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('续约')"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
+								<td :key="index+'_2'" v-if="activeTab.tabName !== 'QY'">
+									续约异常
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('续约异常')"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
 							</template>
 						</tr>
 					</thead>
@@ -222,6 +270,30 @@
 								</span>
 							</td>
 						</tr>
+						<tr v-if="activeTab.tabName !== 'QY'">
+							<td colspan="2">
+								<span>异常率</span>
+								<el-tooltip 
+									effect="dark" 
+									placement="top-start" 
+									:content="tipMap.get('异常率')"
+								>
+									<i class="el-icon-info"/>
+								</el-tooltip>
+							</td>
+							<td>
+								<span></span>
+							</td>
+							<td>
+								<span></span>
+							</td>
+							<template v-if="['周度统计表','月度统计表'].includes(default_tab)">
+								<td v-for="(item,index) in UnusualRateArr" :key="index" colspan="3">{{item.UnusualRate}}</td>
+							</template>
+							<template v-else>
+								<td colspan="3">{{UnusualRateArr[0].UnusualRate}}</td>
+							</template>
+						</tr>
 					</tfoot>
 				</table>
 			</div>	
@@ -238,14 +310,18 @@ export default {
   mixins: [ mixin ],
   data() {
     return {
-      tipMap:new Map([
-        ['未续约','之前是正式客户,现在是冻结或流失状态的客户'],
-        ['续约跟进','之前是正式客户,现在是试用状态且未经历过冻结或流失状态的客户'],
-        ['到期','合同到期时间在统计时间段内的客户'],
-        ['续约','续约申请审批通过时间在所选时间段内的客户']
-      ]),
-			notRenewNumAll:0, // 未续约总合计
-			renewFollowNumAll:0, // 续约跟进总合计
+      	tipMap:new Map([
+			['未续约','之前是正式客户,现在是冻结或流失状态的客户'],
+			['续约跟进','之前是正式客户,现在是试用状态且未经历过冻结或流失状态的客户'],
+			['到期','合同到期时间在统计时间段内的客户'],
+			['续约','续约申请审批通过时间在所选时间段内的客户'],
+			['续约异常','合同到期后两个月内未签约 '],
+			['异常率','异常率=当期续约异常客户总数/截止当期系统中存量客户总数']
+
+		]),
+		notRenewNumAll:0, // 未续约总合计
+		renewFollowNumAll:0, // 续约跟进总合计
+		UnusualRateArr:[],
     }
   },
   computed:{
@@ -253,7 +329,7 @@ export default {
       if(['周度统计表','月度统计表'].includes(this.default_tab)){
         return this.tableTheadColumns
       }
-      return  ['到期','续约']
+      return this.activeTab.tabName !== 'QY'?['到期','续约','续约异常']:['到期','续约']
     }
   },
   created(){
@@ -281,6 +357,8 @@ export default {
 				this.totalGroupArr = this.filterTableData(Data.CompanyRenewRecordNumList,{},'renew');
 				this.notRenewNumAll = Data.CompanyRenewRecordNumList[0].NotRenewNum
 				this.renewFollowNumAll = Data.CompanyRenewRecordNumList[0].RenewFollowNum
+				// 异常率处理
+				this.UnusualRateArr= Data.CompanyRenewRecordNumList||[]
 				//处理数据结构
 				let data = []
 				if(this.activeTab.productionId ==1){
@@ -377,17 +455,17 @@ export default {
 			let title = '';
 
 			if(['周度统计表','月度统计表'].includes(this.default_tab)) {
-				title = [2,3].includes(index) 
+				title = [2,3,4].includes(index) 
 				? this.tableTheadColumns[0] 
-				: [4,5].includes(index) 
+				: [5,6,7].includes(index) 
 				? this.tableTheadColumns[1] 
-				: [6,7].includes(index) 
+				: [8,9,10].includes(index) 
 				? this.tableTheadColumns[2] 
-				: [8,9].includes(index) 
+				: [11,12,13].includes(index) 
 				? this.tableTheadColumns[3]
-				: [10,11].includes(index) 
+				: [14,15,16].includes(index) 
 				? this.tableTheadColumns[4]
-				: [12,13].includes(index) 
+				: [17,18,19].includes(index) 
 				? this.tableTheadColumns[5] 
 				: '';
 			} else {

+ 63 - 14
src/views/dataReport_manage/statistic/mixin.js

@@ -21,6 +21,17 @@ export default {
 			// 	tabSummationName:'ficc总合计',
 			// 	productionId:1, // 1 FICC 2 权益
 			// }
+
+			filterDaysOptions: [
+				{ label:'+60D',value: 1,msg:'合同到期后两个月内未签约' },
+				{ label:'+30D',value: 4,msg:'合同到期后一个月内未签约' },
+				{ label:'到期',value: 5,msg:'合同到期未签约' },
+				{ label:'-30D',value: 6,msg:'合同到期前一个月' },
+				{ label:'-60D',value: 7,msg:'合同到期前两个月' },
+				{ label:'-90D',value: 8,msg:'合同到期前三个月' },
+				{ label:'-120D',value: 9,msg:'合同到期前四个月' },
+			],
+			actFilterDay: 1
 		}
 	},
 	computed: {
@@ -53,7 +64,6 @@ export default {
     },
 		/* 切换顶部tab */
 		changeTabHandle(tab) {
-			if(tab === this.default_tab) return
 			$('.table-body-wrapper')[0].scrollTop = 0;
 			this.default_tab = tab;
 
@@ -133,20 +143,59 @@ export default {
 					}
 				]))
 			}else if(type == 'renew'){
-				list = data.map(item => ([
-					{
-						key: '到期',
-						value: item.ExpireNum,
-						ids: item.ExpireIds,
-						...other_param
-					},
-					{
-						key: '续约',
-						value:item.RenewNum,
-						ids: item.RenewIds,
-						...other_param
+				list=data.map(item=>{
+					if(this.activeTab.tabName !== 'QY'){
+						return [
+							{
+								key: '到期',
+								value: item.ExpireNum,
+								ids: item.ExpireIds,
+								...other_param
+							},
+							{
+								key: '续约',
+								value:item.RenewNum,
+								ids: item.RenewIds,
+								...other_param
+							},
+							{
+								key: '续约异常',
+								value:item.UnusualRenewNum,
+								ids: item.UnusualRenewIds,
+								...other_param
+							}
+						]
+					}else{
+						return [
+							{
+								key: '到期',
+								value: item.ExpireNum,
+								ids: item.ExpireIds,
+								...other_param
+							},
+							{
+								key: '续约',
+								value:item.RenewNum,
+								ids: item.RenewIds,
+								...other_param
+							},
+						]
 					}
-				]))
+				})
+				// list = data.map(item => ([
+				// 	{
+				// 		key: '到期',
+				// 		value: item.ExpireNum,
+				// 		ids: item.ExpireIds,
+				// 		...other_param
+				// 	},
+				// 	{
+				// 		key: '续约',
+				// 		value:item.RenewNum,
+				// 		ids: item.RenewIds,
+				// 		...other_param
+				// 	}
+				// ]))
 			}else if(type==='ficcproduct'){
 				list = data.map(item => ([
 					{

+ 42 - 3
src/views/dataReport_manage/statistic/newCustom.vue

@@ -96,13 +96,52 @@
 								class="head-column"
 							>
 								{{item}}
+								<el-tooltip 
+									effect="dark" 
+									placement="top-start"
+									v-if="!['周度统计表','月度统计表'].includes(default_tab)"
+								>
+									<i class="el-icon-info"/>
+									<div slot="content" v-html="tipMap.get(item==='试用'?item:`${item}${activeTab.productionId}`)"></div>
+								</el-tooltip>
 							</td>	
 						</tr>
 						<tr v-if="['月度统计表'].includes(default_tab)">
 							<template v-for="(item,index) in new Array(6).fill('')">
-								<td :key="index+'_0'">试用</td>
-								<td :key="index+'_1'">活跃</td>
-								<td :key="index+'_2'">正式</td>
+								<td :key="index+'_0'">
+									试用
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('试用')"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
+								<td :key="index+'_1'">
+									活跃
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('活跃'+activeTab.productionId)"
+									>
+										<i class="el-icon-info"/>
+										<div slot="content" v-html="tipMap.get('活跃'+activeTab.productionId)"></div>
+									</el-tooltip>
+								</td>
+								<td :key="index+'_2'">
+									正式
+									<el-tooltip 
+										effect="dark" 
+										placement="top-start" 
+										v-if="index === 0"
+										:content="tipMap.get('正式'+activeTab.productionId)"
+									>
+										<i class="el-icon-info"/>
+									</el-tooltip>
+								</td>
 							</template>
 						</tr>
 						<tr v-else-if="['周度统计表'].includes(default_tab)">

+ 74 - 4
src/views/dataReport_manage/statistic/newCustomlist.vue

@@ -8,14 +8,14 @@
 			class="table-cont"
 		>
 			<el-table-column
-				v-for="item in tableColumns"
+				v-for="item in tableColumnsComputed"
 				:key="item.label"
 				:label="item.label"
 				:width="item.widthsty"
 				:min-width="item.minwidthsty"
 				:prop="item.key"
 				align="center"
-				:sortable="['viewTotal','RoadShowTotal','LastViewTime','ExpireDay','createTime'].includes(item.key) ? 'custom' : false"
+				:sortable="sortableCheck(item.key)"
 			>
 				<template slot-scope="{row}">
 
@@ -80,6 +80,7 @@
 				sortable="custom"
 				align="center" 
 				min-width="120"
+				v-if="!isRenewalException"
 			>
 				<template slot-scope="scope">
 					<span>
@@ -92,6 +93,31 @@
 					</span> 
 				</template>
 			</el-table-column>
+			<el-table-column
+				prop="ServiceYears"
+				sortable="custom"
+				align="center" 
+				min-width="120"
+				v-else
+			>
+				<template slot="header" slot-scope="scope">
+					<el-tooltip content="客户年限=(当前年月日-首签合同开始年月日)/365,结果进行四舍五入,保存一位小数" placement="top">
+						<div style="display: inline-flex;align-items: center;">
+							<span style="margin-right: 4px;">客户年限</span>
+							<i class="el-icon-info" style="color: #333333;"/>
+						</div>
+					</el-tooltip>
+				</template>
+				<template slot-scope="scope">
+					<span>{{scope.row.ServiceYears}}</span> 
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" align="center" prop="LatestServiceRecord" :sortable="isRenewalException?'custom':false">
+				<span slot-scope="scope">
+					<el-button type="text" @click="handleShowShareRecode(scope.row,'list')">沟通记录</el-button>
+					<span style="white-space: nowrap;" v-if="isRenewalException">{{ scope.row.LatestServiceRecord }}</span>
+				</span>
+			</el-table-column>
 			<div slot="empty" style="lineHeight:44px;margin:60px 0;color:#999;">
 				<img src="~@/assets/img/cus_m/nodata.png" alt="" style="display:block;width:160px;height:128px;margin: auto;">
 				<span>暂无数据</span>
@@ -101,19 +127,31 @@
 			<m-page
 				:total="total"
 				:page_no="page_no"
+				:pageSize="pageSize"
 				@handleCurrentChange="handleCurrentChange"
 			/>
 		</div>
+
+		<!-- 服务记录弹窗 -->
+		<ShareListDialog
+				:isShareRecodeDialogShow.sync="isShareRecodeDialogShow"
+				:customInfo="customInfo"
+				:allowEdit="false"
+				@close="()=>{isShareRecodeDialogShow=false;}"
+		/>
 	</div>
 </template>
 
 <script>
 import { dataMainInterface } from '@/api/api.js';
 import mPage from '@/components/mPage.vue';
+import ShareListDialog from '@/views/custom_manage/customList/components/shareListDialog.vue';
+import customMixin from '@/views/custom_manage/customList/mixins/customlistMixin.js';
 
 export default {
 	name: '',
-	components: { mPage },
+	mixins:[customMixin],
+	components: { mPage,ShareListDialog },
 	data() {
 		return {
 			title: '',
@@ -143,6 +181,10 @@ export default {
 					label: '所属销售',
 					key: 'SellerName',
 				},
+				{
+					label: '分配销售',
+					key: 'ShareSeller',
+				},
 				{
 					label: '客户状态',
 					key: 'Status',
@@ -181,6 +223,25 @@ export default {
 			pageSize: 10,
 		}
 	},
+	computed:{
+		Role() {
+			return localStorage.getItem('Role');
+		},
+		// 是否是续约异常
+		isRenewalException(){
+			return this.$route.path=="/abnormalRenewalCustomlist"
+		},
+		tableColumnsComputed(){
+			// 分配销售 续约统计和续约异常统计需要显示
+			let hasDistributionSales = this.Role.indexOf('rai')==-1 && 
+																['/contractCustomlist','/abnormalRenewalCustomlist'].includes(this.$route.path)
+			if(hasDistributionSales){
+				return this.tableColumns
+			}else{
+				return this.tableColumns.filter(item => item.label!='分配销售')
+			}
+		}
+	},
 	methods: {
 
 		/* 获取数据	 */
@@ -209,6 +270,10 @@ export default {
 			this.getTableData();
 		},
 
+		sortableCheck(key){
+			return ( ['viewTotal','RoadShowTotal','LastViewTime','ExpireDay','createTime'].includes(key) ||
+							(['ShareSeller','SellerName','Status'].includes(key) && this.isRenewalException) ) ? 'custom' : false
+		},
 		/* 排序变化时 */
 		sortChangeHandle({ prop,order }) {
 			console.log(prop,order)
@@ -218,6 +283,11 @@ export default {
 				'RoadShowTotal': 'roadShowTotal',
 				'LastViewTime': 'viewTime',
 				'ExpireDay': 'expireDay',
+				'ShareSeller':'shareSellerName',
+				'SellerName':'sellerName',
+				'Status':'status',
+				'ServiceYears':'serviceYears',
+				'LatestServiceRecord':'latestServiceRecord'
 			}
 
 			this.sort_obj = {
@@ -287,7 +357,7 @@ export default {
       		this.title = title;
 			this.sort_obj = sort_obj
     	}
-
+		this.pageSize=this.isRenewalException?50:10
 		this.ids && this.getTableData();
 	},
 }

+ 0 - 3
src/views/dataReport_manage/statistic/todoTask.vue

@@ -106,7 +106,6 @@
 										effect="dark" 
 										placement="top-start"
 										content="截止日期小于等于今天的未完成To Do任务统计"
-										v-if="['周度统计表'].includes(default_tab)"
 									>
 										<i class="el-icon-info"/>
 									</el-tooltip>
@@ -119,7 +118,6 @@
 										effect="dark" 
 										placement="top-start"
 										content="进行中且未到截止日期的To Do任务统计"
-										v-if="['周度统计表'].includes(default_tab)"
 									>
 										<i class="el-icon-info"/>
 									</el-tooltip>
@@ -132,7 +130,6 @@
 										effect="dark" 
 										placement="top-start"
 										content="该销售累计完成To Do任务数量"
-										v-if="['周度统计表'].includes(default_tab)"
 									>
 										<i class="el-icon-info"/>
 									</el-tooltip>

+ 364 - 0
src/views/ficc_manage/chapterVariety.vue

@@ -0,0 +1,364 @@
+<template>
+  <div class="classify-page">
+    <div class="content-box">
+      <el-tree
+        :data="list"
+        node-key="ReportChapterTypeId"
+        :props="{
+          label: 'ReportChapterTypeName',
+          children: 'Child',
+        }"
+        check-strictly
+        empty-text="暂无数据"
+        draggable
+        :allow-drop="canDropHandle"
+        @node-drop="dropOverHandle"
+      >
+        <div class="classify-item-wrap" slot-scope="{ data }">
+          <div>
+            <span :class="['tag', data.Enabled == 1 ? 'open' : 'close']">{{
+              data.Enabled == 1 ? "启用" : "禁用"
+            }}</span>
+            <span>{{ data.ReportChapterTypeName }}</span>
+          </div>
+
+          <div class="opt-box">
+            <span
+              style="cursor: pointer; color: #409eff"
+              @click.stop="handleShowEdit(data)"
+              >小程序配置</span
+            >
+          </div>
+        </div>
+      </el-tree>
+    </div>
+
+    <!-- 分类弹窗 -->
+    <m-dialog title="小程序配置" :show.sync="aeForm.show" width="650px">
+      <div style="padding-left: 50px">
+        <el-form
+          :model="aeForm"
+          :rules="aerules"
+          ref="aeForm"
+          label-position="left"
+          hide-required-asterisk
+          label-width="100px"
+        >
+          <el-form-item
+            label="未选中icon"
+            prop="UnselectedIcon"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(1)"
+              id="file1"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.UnselectedIcon"
+              placeholder="上传icon"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(1)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="选中icon"
+            prop="selectedIcon"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(2)"
+              id="file2"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.selectedIcon"
+              placeholder="上传icon"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(2)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="带字icon"
+            prop="wordIcon"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file3"
+              @change="fileSelected(3)"
+              id="file6"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.wordIcon"
+              placeholder="上传icon"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(3)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="章节配图"
+            prop="bgImg"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file4"
+              @change="fileSelected(4)"
+              id="file6"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.bgImg"
+              placeholder="上传icon"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(4)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="小程序端隐藏"
+            prop="IsShow"
+          >
+            <el-switch
+              v-model="aeForm.IsShow"
+              inactive-color="#ededed"
+            ></el-switch>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div slot="footer" style="margin-top: 20px">
+        <el-button @click="aeForm.show=false" style="width: 132px; height: 40px"
+          >取消</el-button
+        >
+        <el-button
+          @click="setClassifyHandle"
+          type="primary"
+          style="width: 132px; height: 40px"
+          >保存</el-button
+        >
+      </div>
+    </m-dialog>
+  </div>
+</template>
+
+<script>
+import mDialog from '@/components/mDialog.vue';
+import { bannerupload, getchapterTypeList,editChapterType } from 'api/api.js';
+export default {
+    components: { mDialog },
+  beforeRouteEnter(to, from, next) {
+    if (to.query.reportType == 'day') {
+      to.matched[1].name = '晨报章节设置'
+    } else {
+      to.matched[1].name = '周报章节设置'
+    }
+    next()
+  },
+  data() {
+    return {
+      list: [],
+      aeForm: {
+        show: false,
+        id:0,
+        UnselectedIcon:'',
+        selectedIcon:'',
+        wordIcon:'',
+        bgImg:'',
+        IsShow:false
+      }
+    }
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      getchapterTypeList({ ReportType: this.$route.query.reportType == 'week' ? 'week' : 'day' }).then(res => {
+        if (res.Ret === 200) {
+          this.list = res.Data.List || []
+        }
+      })
+    },
+    handleShowEdit(data) {
+      this.aeForm = {
+        show: true,
+        id:data.ReportChapterTypeId,
+        UnselectedIcon:data.UnselectedImage,
+        selectedIcon:data.SelectedImage,
+        wordIcon:data.WordsImage,
+        bgImg:data.EditImgUrl,
+        IsShow:data.IsShow==0?true: false
+      }
+    },
+
+    setClassifyHandle(){
+        this.$refs.aeForm.validate((valid)=>{
+            if(valid){
+                let params={
+                    ReportChapterTypeId:this.aeForm.id,
+                    SelectedImage:this.aeForm.selectedIcon,
+                    UnselectedImage:this.aeForm.UnselectedIcon,
+                    WordsImage:this.aeForm.wordIcon,
+                    EditImgUrl:this.aeForm.bgImg,
+                    IsShow:this.aeForm.IsShow?0:1
+                }
+                editChapterType(params).then(res=>{
+                    if(res.Ret===200){
+                        this.$message.success( res.Msg );
+						this.getList();
+						this.aeForm.show=false;
+                    }
+                })
+            }
+        })
+    },
+
+    clickinput(type) {  //上传模拟点击
+      $(`#file${type}`).click();
+    },
+    fileSelected(type) {  //选择文件上传
+      const that = this;
+      if (document.getElementById('file' + type).files[0]) {
+        let hostfile = document.getElementById('file' + type).files[0];
+        let size = Math.floor(hostfile.size / 1024 / 1024);
+        if (size > 200) {
+          that.$message.error('上传文件大小不能大于200M!');
+          hostfile = {};
+          return false
+        }
+        if (hostfile.name.toLowerCase().includes('.png') || hostfile.name.toLowerCase().includes('.jpg') || hostfile.name.toLowerCase().includes('.jpeg')) {
+          let form = new FormData();
+          form.append('file', hostfile);  //hostfile.name
+          that.uploadloading = true;
+          bannerupload(form).then((res) => {
+            if (res.Ret === 200) {
+              if (type == 1) {
+                that.aeForm.UnselectedIcon = res.Data.ResourceUrl;
+              } else if (type == 2) {
+                that.aeForm.selectedIcon = res.Data.ResourceUrl;
+              } else if (type == 3) {
+                that.aeForm.wordIcon = res.Data.ResourceUrl
+              } else if (type == 4) {
+                that.aeForm.bgImg = res.Data.ResourceUrl
+              }
+            }
+            $("#file" + type).val('');
+            hostfile = {};
+          });
+        } else {
+          that.$message.error('上传文件格式不正确!');
+        }
+      }
+    },
+  },
+}
+</script>
+
+<style lang="scss">
+.el-cascader .el-input {
+  width: 100%;
+}
+.classify-page {
+  .content-box {
+    .el-tree-node__content {
+      padding-top: 10px;
+      padding-bottom: 10px;
+      border-bottom: 1px solid #c8cdd9;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.top-wrap {
+  display: flex;
+  justify-content: space-between;
+  background: #ffffff;
+  border-radius: 4px;
+  padding: 20px;
+}
+.content-box {
+  padding: 20px;
+  margin-top: 20px;
+  height: calc(100vh - 260px);
+  overflow-y: auto;
+  background-color: #ffffff;
+  .classify-item-wrap {
+    flex: 1;
+    padding-right: 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .tag {
+      display: inline-block;
+      min-width: 76px;
+      line-height: 30px;
+      text-align: center;
+      &.open {
+        background-color: #ecf2fe;
+        color: #0052d9;
+      }
+      &.close {
+        background-color: #0052d9;
+        color: #fff;
+      }
+    }
+    .opt-box {
+      .icon-drag,
+      .icon-set {
+        width: 16px;
+        height: 16px;
+        margin-left: 10px;
+      }
+    }
+  }
+}
+</style>

+ 807 - 0
src/views/ficc_manage/reportVariety.vue

@@ -0,0 +1,807 @@
+<template>
+  <div class="report-variety-page">
+    <div class="top-wrap">
+      <el-input
+        placeholder="分类名称"
+        v-model="searchVal"
+        style="max-width: 262px"
+        @change="getlist"
+        clearable
+      >
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </div>
+    <div class="content-box">
+      <el-tree
+        :data="list"
+        node-key="Id"
+        :props="{
+          label: 'ClassifyName',
+          children: 'Child',
+        }"
+        check-strictly
+        empty-text="暂无数据"
+        indent="76"
+      >
+        <div class="classify-item-wrap" slot-scope="{ node, data }">
+          <div>
+            <span :class="['tag', data.Enabled==1?'open':'close']">{{data.Enabled==1?'启用':'禁用'}}</span>
+            <span>{{ data.ClassifyName }}</span>
+          </div>
+
+          <div class="opt-box">
+            <span class="editsty" v-if="['晨报','周报'].includes(data.ClassifyName)" @click="chapterSetting(data)">章节设置</span>
+            <span
+              style="cursor: pointer; color: #409eff"
+              @click.stop="handleShowEdit(data)"
+              >小程序配置</span
+            >
+          </div>
+        </div>
+      </el-tree>
+    </div>
+
+    <!-- 分类弹窗 -->
+    <m-dialog title="小程序配置" :show.sync="aeForm.show" width="650px">
+      <div style="padding-left: 50px">
+        <el-form
+          :model="aeForm"
+          :rules="aerules"
+          ref="aeForm"
+          label-position="left"
+          hide-required-asterisk
+          label-width="100px"
+        >
+          <el-form-item
+            prop="showType"
+            label="展示形式"
+            v-if="aeForm.parent_id == 0"
+          >
+            <el-select
+              v-model="aeForm.showType"
+              placeholder="请选择"
+              style="width: 400px"
+            >
+              <el-option label="列表" :value="1"></el-option>
+              <!-- <el-option label="专栏" :value="2"></el-option>  -->
+              <el-option label="品种" :value="3"></el-option>
+            </el-select>
+          </el-form-item>
+          <!-- 一级目录子目录 -->
+          <el-form-item
+            label="子目录"
+            v-if="aeForm.parent_id == 0 && aeForm.showType == 1"
+          >
+            <draggable v-model="ClassifyMenuList" animation="300">
+              <div
+                style="display: inline-block; margin-right: 5px"
+                v-for="(item, index) in ClassifyMenuList"
+                :key="item"
+              >
+                <el-input
+                  v-if="item.inputVisible"
+                  v-model="item.MenuName"
+                  ref="itemINput"
+                  size="small"
+                  style="width: 90px"
+                  :autofocus="true"
+                  @keyup.enter.native="item.inputVisible = false"
+                  @blur="item.inputVisible = false"
+                ></el-input>
+                <el-tag
+                  v-else
+                  closable
+                  :disable-transitions="false"
+                  @click="showInput(index)"
+                  @close="handleClose(index)"
+                >
+                  {{ item.MenuName }}
+                </el-tag>
+              </div>
+            </draggable>
+            <div>
+              <el-input
+                v-if="inputVisible"
+                v-model="inputValue"
+                ref="saveTagInput"
+                size="small"
+                @keyup.enter.native="handleInputConfirm"
+                @blur="handleInputConfirm"
+                style="width: 90px"
+              >
+              </el-input>
+              <el-button v-else size="small" @click="showInput(-1)"
+                >+ 点击新增</el-button
+              >
+            </div>
+          </el-form-item>
+          <!-- 二级目录子目录 -->
+          <el-form-item label="子目录" v-if="aeForm.parent_id != 0&&selectMenuOpt.length>0">
+            <el-select
+              v-model="aeForm.ClassifyMenuId"
+              clearable
+              placeholder="请选择"
+              style="width: 400px"
+            >
+              <el-option
+                :label="item.MenuName"
+                :value="item.MenuId"
+                v-for="item in selectMenuOpt"
+                :key="item.MenuId"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+
+          <el-form-item
+            label="FICC页icon"
+            v-if="aeForm.parent_id == 0"
+            prop="YbFiccIcon"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(6)"
+              id="file6"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.YbFiccIcon"
+              placeholder="上传FICC页icon"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(6)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="报告合集配图"
+            v-if="aeForm.parent_id == 0 && aeForm.showType !== 2"
+            prop="YbRightBanner"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(11)"
+              id="file11"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.YbRightBanner"
+              placeholder="上传报告合集配图"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(11)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <el-form-item
+            label="分享链接配图"
+            prop="YbShareBgImg"
+            v-if="aeForm.parent_id == 0"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(10)"
+              id="file10"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.YbShareBgImg"
+              placeholder="上传分享链接配图"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(10)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          
+
+          <!-- 二级分类配置列表背景图 -->
+          <el-form-item
+            label="列表背景图"
+            v-if="aeForm.parent_id != 0 && (parentIsList || parentIsVariety)"
+            prop="YbListImg"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(9)"
+              id="file9"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.YbListImg"
+              placeholder="上传列表背景图"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(9)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+          <!-- 列表、品种的二级分类 展示分享链接配图 但是不是必填的 -->
+          <el-form-item
+            label="分享链接配图"
+            prop="YbShareBgImg_"
+            v-if="aeForm.parent_id != 0 && (parentIsList || parentIsVariety)"
+          >
+            <input
+              type="file"
+              size="small"
+              name="file"
+              @change="fileSelected(12)"
+              id="file12"
+              class="true-file"
+              style="display: none"
+            />
+            <el-input
+              readonly
+              type="text"
+              v-model="aeForm.YbShareBgImg_"
+              placeholder="上传分享链接配图"
+              size="medium"
+              style="width: 400px"
+            >
+              <el-button
+                slot="append"
+                type="primary"
+                size="mini"
+                @click.native="clickinput(12)"
+                >选择图片</el-button
+              >
+            </el-input>
+          </el-form-item>
+
+          <el-form-item
+            label="关联线上路演"
+            prop="RelateVideo"
+            v-if="aeForm.parent_id!=0"
+          >
+            <el-switch
+              v-model="aeForm.RelateVideo"
+              inactive-color="#ededed"
+            ></el-switch>
+          </el-form-item>
+
+          <el-form-item
+            label="小程序端隐藏"
+            prop="IsShow"
+          >
+            <el-switch
+              v-model="aeForm.IsShow"
+              inactive-color="#ededed"
+            ></el-switch>
+          </el-form-item>
+
+        </el-form>
+      </div>
+      <div slot="footer" style="margin-top: 20px">
+        <el-button @click="cancelClassify" style="width: 132px; height: 40px"
+          >取消</el-button
+        >
+        <el-button
+          @click="setClassifyHandle"
+          type="primary"
+          style="width: 132px; height: 40px"
+          >保存</el-button
+        >
+      </div>
+    </m-dialog>
+  </div>
+</template>
+
+<script>
+import mDialog from '@/components/mDialog.vue';
+import { bannerupload, classifylist,classifyedit } from 'api/api.js';
+export default {
+  components: { mDialog },
+  computed: {
+    parentIsList() {
+      //当前上级分类是否为列表
+      let flag = false
+      if (this.aeForm.show) {
+        this.list.forEach(item => {
+          if (item.Id == this.aeForm.parent_id) {
+            if (item.ShowType == 1) {
+              flag = true
+            }
+          }
+        })
+      }
+      return flag
+    },
+    parentIsVariety() {
+      //当前上级分类是否为品种
+      let flag = false
+      if (this.aeForm.show) {
+        this.list.forEach(item => {
+          if (item.Id == this.aeForm.parent_id) {
+            if (item.ShowType == 3) {
+              flag = true
+            }
+          }
+        })
+      }
+      return flag
+    },
+    selectMenuOpt() {
+      let arr = []
+      if (this.aeForm.show) {
+        this.list.forEach(item => {
+          if (item.Id == this.aeForm.parent_id) {
+            arr = item.ClassifyMenuList || []
+          }
+        })
+      }
+      return arr
+    },
+
+  },
+  data() {
+    return {
+      searchVal:'',
+      list: [],
+      inputVisible: false,
+      inputValue: '',
+      ClassifyMenuList: [],
+      YbFiccPcIconList: [
+        {
+          label: '蓝色',
+          val: 'https://hzstatic.hzinsights.com/static/yb_wx/ficc_classify_bg_blue.png'
+        },
+        {
+          label: '绿色',
+          val: 'https://hzstatic.hzinsights.com/static/yb_wx/ficc_classify_bg_green.png'
+        },
+        {
+          label: '红色',
+          val: 'https://hzstatic.hzinsights.com/static/yb_wx/ficc_classify_bg_orange.png'
+        },
+      ],
+      aeForm: {
+        show: false,
+        classify_name: '',
+        parent_id: 0,
+        abstract: '',
+        descript: '',
+        author: '',
+        authorDsec: '',
+        classifyDsec: '',
+        authorTag: '',
+        classifyImg: '',
+        reportImg: '',
+        columImg: '',
+        bannerImg: '',
+        avatar: '',
+        label: "",
+        hasTel: 0,//是否有电话会:0-否 1-是
+        showType: 1,//展示形式 1-列表 2-专栏 3-品种
+        Sort: '',
+        YbFiccSort: '',
+        YbFiccIcon: '',
+        YbIconUrl: '',
+        YbBgUrl: '',
+        YbFiccPcIcon: '',
+        IsShow: false,//是否在小程序端展示:0-隐藏 1-显示
+        YbListImg: '',//小程序研报列表封面图
+        YbShareBgImg: '',
+        ClassifyMenuId: '',
+        YbRightBanner: '',//报告合集配图
+        relate: [],
+        RelateVideo:false,//关联线上路演
+      },
+      aerules: {
+        abstract: [{
+          required: true,
+          message: '请输入分类简介',
+          trigger: 'blur'
+        }],
+        descript: [{
+          required: true,
+          message: '请输入分类描述',
+          trigger: 'blur'
+        }],
+        author: [{
+          required: true,
+          message: '请输入栏目作者',
+          trigger: 'blur'
+        }],
+        authorDsec: [{
+          required: true,
+          message: '请输入作者简介',
+          trigger: 'blur'
+        }],
+        classifyDsec: [{
+          required: true,
+          message: '请输入栏目简介',
+          trigger: 'blur'
+        }],
+        classifyImg: [{
+          required: true,
+          message: '请上传首页配图',
+          trigger: 'blur'
+        }],
+        reportImg: [{
+          required: true,
+          message: '请上传研报配图',
+          trigger: 'blur'
+        }],
+        bannerImg: [{
+          required: true,
+          message: '请上传头部banner',
+          trigger: 'blur'
+        }],
+        avatar: [{
+          required: true,
+          message: '请上传作者头像',
+          trigger: 'blur'
+        }],
+        columImg: [{
+          required: true,
+          message: '请上传专栏配图',
+          trigger: 'blur'
+        }],
+        label: [{
+          required: true,
+          message: '请输入分类标签',
+          trigger: 'blur'
+        }],
+        hasTel: [{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }],
+        showType: [{
+          required: true,
+          message: '请选择展示形式',
+          trigger: 'change'
+        }],
+        Sort: [{
+          required: true,
+          message: '请输入数字',
+          trigger: 'blur'
+        }],
+        YbFiccSort: [{
+          required: true,
+          message: '请输入数字',
+          trigger: 'blur'
+        }],
+        YbFiccIcon: [{
+          required: true,
+          message: '上传FICC页icon',
+          trigger: 'change'
+        }],
+        YbRightBanner: [{
+          required: true,
+          message: '上传报告合集配图',
+          trigger: 'change'
+        }],
+        YbFiccPcIcon: [{
+          required: true,
+          message: '选择背景颜色',
+          trigger: 'change'
+        }],
+        IsShow: [{
+          required: true,
+          message: '小程序端隐藏',
+          trigger: 'change'
+        }],
+        YbListImg: [{
+          required: true,
+          message: '上传列表背景图',
+          trigger: 'change'
+        }],
+        YbShareBgImg: [{
+          required: true,
+          message: '上传列表背景图',
+          trigger: 'change'
+        }],
+      },
+    }
+  },
+  created() {
+    this.getlist()
+  },
+  methods: {
+    chapterSetting(row){
+      let reportType;
+			if(row.ClassifyName=='周报'){
+				reportType='week'
+			}else{
+				reportType='day'
+			}
+			this.$router.push({path:'chapterVariety',query:{reportType}})
+    },
+    showInput(index){
+			if(index!=-1){
+				this.ClassifyMenuList[index].inputVisible=true
+				this.$nextTick(_ => {
+					this.$refs.itemINput[0].$refs.input.focus();
+				})
+				return
+			}
+			this.inputVisible = true;
+			this.$nextTick(_ => {
+				this.$refs.saveTagInput.$refs.input.focus();
+			});
+		},
+		handleInputConfirm() {
+			let inputValue = this.inputValue;
+			if (inputValue) {
+				this.ClassifyMenuList.push({MenuId:0,MenuName:inputValue,inputVisible:false});
+			}
+			this.inputVisible = false;
+			this.inputValue = '';
+		},
+		handleClose(index){
+			this.ClassifyMenuList.splice(index,1)
+		},
+    //保存
+    setClassifyHandle(){
+      this.$refs.aeForm.validate((valid)=>{
+        if(valid){
+          console.log(this.aeForm);
+          let params={
+            ClassifyId:this.aeForm.classify_id,
+            ClassifyLabel:this.aeForm.label,
+            ShowType:this.aeForm.showType,
+            IsShow:this.aeForm.IsShow?0:1,
+            YbFiccSort:this.aeForm.YbFiccSort?Number(this.aeForm.YbFiccSort):0,
+            YbFiccIcon:this.aeForm.YbFiccIcon,
+            YbFiccPcIcon:this.aeForm.YbFiccPcIcon,
+            YbIconUrl:this.aeForm.YbIconUrl,
+            YbBgUrl:this.aeForm.YbBgUrl,
+            YbListImg:this.aeForm.YbListImg,
+            YbShareBgImg:this.aeForm.parent_id!=0&&(this.parentIsList||this.parentIsVariety)?this.aeForm.YbShareBgImg_:this.aeForm.YbShareBgImg,
+            ClassifyMenuId:this.aeForm.ClassifyMenuId||0,
+            YbRightBanner:this.aeForm.YbRightBanner||'',
+            MenuList:[],
+            RelateTel:this.aeForm.relate.includes(1)?1:0,
+            RelateVideo:this.aeForm.RelateVideo?1:0,
+          }
+          params.MenuList=this.ClassifyMenuList.map(item=>{
+						return {
+							MenuId:item.MenuId,
+							MenuName:item.MenuName
+						}
+					})
+          classifyedit(params).then(res =>{
+							if( res.Ret==200 ){
+								this.$message.success( res.Msg );
+								this.getlist();
+								this.aeForm.show=false;
+							}
+					});
+
+        }
+      })
+    },
+    cancelClassify(){
+      this.aeForm.show=false
+    },
+    handleShowEdit(item) {
+      this.aeForm = {
+        show: true,
+        classify_id: parseInt(item.Id),
+        classify_name: item.ClassifyName,
+        parent_id: item.ParentId,
+        descript: item.Descript,
+        author: item.ReportAuthor,
+        authorDsec: item.AuthorDescript,
+        classifyDsec: item.Abstract,
+        authorTag: item.VipTitle,
+        classifyImg: item.ReportImgUrl,
+        reportImg: item.HomeImgUrl,
+        columImg: item.ColumnImgUrl,
+        bannerImg: item.HeadImgUrl,
+        avatar: item.AvatarImgUrl,
+        label: item.ClassifyLabel,
+        hasTel: item.HasTeleconference,
+        showType: item.ShowType,
+        Sort: item.Sort,
+        YbFiccSort: item.YbFiccSort,
+        YbFiccIcon: item.YbFiccIcon,
+        YbIconUrl: item.YbIconUrl,
+        YbBgUrl: item.YbBgUrl,
+        YbFiccPcIcon: item.YbFiccPcIcon,
+        IsShow: item.IsShow == 0 ? true : false,//是否在小程序端展示:0-隐藏 1-显示
+        YbListImg: item.YbListImg,
+        YbShareBgImg: item.YbShareBgImg,
+        ClassifyMenuId: item.ClassifyMenuId || '',
+        YbRightBanner: item.YbRightBanner || '',
+        relate: [item.RelateTel == 1 ? 1 : null, item.RelateVideo == 1 ? 2 : null],
+        RelateVideo:item.RelateVideo == 1?true:false
+      }
+      this.ClassifyMenuList = item.ClassifyMenuList ? item.ClassifyMenuList.map(item => {
+        return {
+          MenuId: item.MenuId,
+          MenuName: item.MenuName,
+          inputVisible: false
+        }
+      }) : []
+      //若编辑的为列表、品种下的二级分类 需要计算YbShareBgImg_
+      //已填写则获取已填写内容
+      if (item.YbShareBgImg) {
+        this.aeForm.YbShareBgImg_ = item.YbShareBgImg
+      } else {//若未填写则取一级分类的YbShareBgImg
+        this.aeForm.YbShareBgImg_ = this.getParentYbShareBgImg(item.ParentId)
+      }
+      this.$nextTick(() => {
+        this.$refs.aeForm.clearValidate();
+      })
+    },
+    //根据上级分类id获取YbShareBgImg
+    getParentYbShareBgImg(id) {
+      let YbShareBgImg = ''
+      let parent = this.list.find((item) => { return item.Id === id })
+      if (!parent) return
+      YbShareBgImg = parent.YbShareBgImg || ''
+      return YbShareBgImg
+    },
+    getlist() {  //获取列表
+      let params = { KeyWord: this.searchVal };
+      this.listLoading = true;
+      classifylist(params).then((res) => {
+        if (res.Ret == 200) {
+          this.list = res.Data.List || [];
+
+        }
+        this.listLoading = false;
+      });
+    },
+    clickinput(type) {  //上传模拟点击
+      $(`#file${type}`).click();
+    },
+    fileSelected(type) {  //选择文件上传
+      const that = this;
+      if (document.getElementById('file' + type).files[0]) {
+        let hostfile = document.getElementById('file' + type).files[0];
+        let size = Math.floor(hostfile.size / 1024 / 1024);
+        if (size > 200) {
+          that.$message.error('上传文件大小不能大于200M!');
+          hostfile = {};
+          return false
+        }
+        if (hostfile.name.toLowerCase().includes('.png') || hostfile.name.toLowerCase().includes('.jpg') || hostfile.name.toLowerCase().includes('.jpeg')) {
+          let form = new FormData();
+          form.append('file', hostfile);  //hostfile.name
+          that.uploadloading = true;
+          bannerupload(form).then((res) => {
+            if (res.Ret === 200) {
+              if (type == 1) {
+                that.aeForm.classifyImg = res.Data.ResourceUrl;
+              } else if (type == 2) {
+                that.aeForm.bannerImg = res.Data.ResourceUrl;
+              } else if (type == 3) {
+                that.aeForm.avatar = res.Data.ResourceUrl
+              } else if (type == 4) {
+                that.aeForm.columImg = res.Data.ResourceUrl
+              } else if (type == 5) {
+                that.aeForm.reportImg = res.Data.ResourceUrl
+              } else if (type == 6) {
+                that.aeForm.YbFiccIcon = res.Data.ResourceUrl
+              } else if (type == 7) {
+                that.aeForm.YbIconUrl = res.Data.ResourceUrl
+              } else if (type == 8) {
+                that.aeForm.YbBgUrl = res.Data.ResourceUrl
+              } else if (type == 9) {
+                this.aeForm.YbListImg = res.Data.ResourceUrl
+              } else if (type == 10) {
+                this.aeForm.YbShareBgImg = res.Data.ResourceUrl
+              } else if (type == 11) {
+                this.aeForm.YbRightBanner = res.Data.ResourceUrl
+              } else if (type == 12) {
+                this.aeForm.YbShareBgImg_ = res.Data.ResourceUrl
+              }
+            }
+            $("#file" + type).val('');
+            hostfile = {};
+          });
+        } else {
+          that.$message.error('上传文件格式不正确!');
+        }
+      }
+    },
+  },
+}
+</script>
+
+<style lang="scss">
+.el-cascader .el-input {
+  width: 100%;
+}
+.report-variety-page {
+  .content-box {
+    .el-tree-node__content {
+      padding-top: 10px;
+      padding-bottom: 10px;
+      border-bottom: 1px solid #c8cdd9;
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+.top-wrap {
+  display: flex;
+  justify-content: flex-end;
+  background: #ffffff;
+  border-radius: 4px;
+  padding: 10px 20px;
+}
+.content-box {
+  padding: 20px;
+  margin-top: 20px;
+  height: calc(100vh - 230px);
+  overflow-y: auto;
+  background-color: #ffffff;
+  .classify-item-wrap {
+    flex: 1;
+    padding-right: 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .tag {
+      display: inline-block;
+      min-width: 76px;
+      line-height: 30px;
+      text-align: center;
+      &.open {
+        background-color: #ecf2fe;
+        color: #0052d9;
+      }
+      &.close {
+        background-color: #0052d9;
+        color: #fff;
+      }
+    }
+    .opt-box {
+      .icon-drag,
+      .icon-set {
+        width: 16px;
+        height: 16px;
+        margin-left: 10px;
+      }
+    }
+  }
+}
+</style>

+ 4 - 0
src/views/ficc_manage/userTableColums.js

@@ -44,6 +44,10 @@ export const tableColums = (type) => {
           label: "来源",
           key: "SourceStr",
         },
+        {
+          label: "申请品种",
+          key: "Permission",
+        },
         {
           label: "申请类型",
           key: "ApplyStatus",

+ 110 - 0
src/views/interaction_manage/bannerStatistics.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="container-banner-statistics">
+    <div class="table-body-wrapper" style="max-height: calc(100vh - 180px); overflow: auto">
+      <table border>
+        <thead>
+          <td class="thead-rs">名称</td>
+          <td class="thead-rs">日期</td>
+          <td class="thead-rs">点击量合计</td>
+          <td class="thead-rs">点击量</td>
+          <td class="thead-rs">点击来源</td>
+          <td class="thead-rs">最近一次点击时间</td>
+        </thead>
+        <tbody v-for="item in tableData" :key="item.ViewHistoryID">
+          <tr v-for="(_item, index) in item.SourceList" :key="_item.LastUpdatedTime">
+            <!-- <td class="thead-rs" :rowspan="item.SourceList.length" v-if="index == 0"> <img :src="item.BannerUrl" class="table-img" alt="" /></td> -->
+            <td class="thead-rs" :rowspan="item.SourceList.length" v-if="index == 0">{{ item.Remark }}</td>
+            <td class="thead-rs" :rowspan="item.SourceList.length" v-if="index == 0">{{ item.StartDate }} -- {{ item.EndDate }}</td>
+            <td class="thead-rs" :rowspan="item.SourceList.length" v-if="index == 0">{{ item.Pv }}</td>
+            <td class="thead-rs">{{ _item.Pv }}</td>
+            <td class="thead-rs">
+              {{ _item.FirstSource == 1 ? "小程序移动端" : _item.FirstSource == 2 ? "小程序PC端" : _item.FirstSource == 3 ? "研报官网" : "" }}
+              {{ _item.SecondSource == 1 ? "/ 首页" : _item.SecondSource == 2 ? "/ 研报详情页" : "" }}
+            </td>
+            <td class="thead-rs">{{ _item.LastUpdatedTime }}</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { departInterence } from "@/api/api.js";
+export default {
+  name: "",
+  data() {
+    return {
+      tableData: [],
+    };
+  },
+  mounted() {
+    this.getDataList();
+  },
+  methods: {
+    async getDataList() {
+      const res = await departInterence.getBannerStatistic();
+      if (res.Ret === 200) {
+        this.tableData = res.Data || [];
+      }
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.container-banner-statistics {
+  .table-body-wrapper {
+    max-height: calc(100vh - 100px);
+    overflow-y: scroll;
+    overflow-x: auto;
+    border-bottom: 1px solid #dcdfe6;
+    border-top: 1px solid #dcdfe6;
+    .table-data-empty {
+      color: #666666;
+      height: 530px;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border-left: 1px solid #dcdfe6;
+      border-right: 1px solid #dcdfe6;
+    }
+  }
+  table {
+    width: 100%;
+    font-size: 14px;
+    color: #666;
+    thead {
+      position: sticky;
+      top: 0;
+      z-index: 1;
+      left: 0;
+      border-left: 1px solid #dcdfe6;
+      border-right: 1px solid #dcdfe6;
+      td {
+        border: none;
+        outline-color: #dcdfe6;
+        outline-style: solid;
+        outline-width: 0.5px;
+        background-color: #ebeef5 !important ;
+        color: #333333;
+        font-weight: 500;
+      }
+    }
+    td,
+    th {
+      min-width: 35px;
+      // word-break: break-all;
+      border: 1px solid #dcdfe6;
+      height: 45px;
+      text-align: center;
+      background-color: #fff;
+    }
+  }
+  .table-img {
+    padding: 20px 0;
+    width: 368px;
+    height: 107px;
+    box-sizing: border-box;
+  }
+}
+</style>

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

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

+ 5 - 1
src/views/login_manage/ForgetPassModel.vue

@@ -283,7 +283,8 @@ export default {
                 VerifyCode:code,
                 UserName:this.form.account,
                 Mobile:this.checkWay==='mobile'?this.userMobile:'',
-                Email:this.checkWay==='email'?this.userEmail:''
+                Email:this.checkWay==='email'?this.userEmail:'',
+                TelAreaCode:this.checkWay==='mobile'?this.TelAreaCode:''
             }).then(res=>{
                 if(res.Ret!==200) return
                 this.goSteps()
@@ -320,6 +321,9 @@ export default {
                     }).then(res=>{
                         if(res.Ret!==200) return
                         this.$message.success('重置密码成功,请登陆')
+                        localStorage.setItem('timeKey',Date.now())
+                        localStorage.setItem("account", new http.Base64().encode(this.form.account));
+                        localStorage.setItem("checkPass", new http.Base64().encode(this.passForm.pass1));
                         this.resetPassCountDown()
                         this.resetPassTimer = setInterval(()=>{
                             this.resetPassCountDown()

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

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

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

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

+ 11 - 6
src/views/operation_manage/AIQA/AIQA.vue

@@ -31,7 +31,7 @@
                     <span>{{activeWindowId<=0?'弘则AI助手使用说明':`${historyList.length||0} messages`}}</span>
                 </div>
                 <div class="select-box">
-                    <el-select v-model="model" :class="{'hint':showHint}" :disabled="isTyping||(windowContentLoading&&windowContentLoading.visible)" ref="modelSelect" 
+                    <!-- <el-select v-model="model" :class="{'hint':showHint}" :disabled="isTyping||(windowContentLoading&&windowContentLoading.visible)" ref="modelSelect" 
                         @click.native="selectClick"
                         @change="changeModel">
                         <el-option v-for="item in modelList" :key="item.label"
@@ -40,7 +40,7 @@
                             <span style="float:left">{{item.label}}</span>
                             <span style="float:right"><img :src="item.icon" style="margin-top:5px;width:24px;height:24px;"/></span>
                         </el-option>
-                    </el-select>
+                    </el-select> -->
                 </div>
             </div>
             <!-- 仅这一部分滚动 -->
@@ -86,7 +86,7 @@ export default {
             /* window-content*/
             historyList:[],//当前窗口历史记录
             inputText:'',
-            model:'',//当前选择的模型
+            model:'GPT-4 Turbo',//当前选择的模型
             modelOldValue:'',
             modelList:[
                 {
@@ -113,6 +113,7 @@ export default {
             showHint:false,//选择模型提示
             isTyping:false,//是否处于打字动画中
             windowContentLoading:null,
+            answerLoading:false,//回答中
         };
     },
     watch:{
@@ -161,7 +162,7 @@ export default {
                 this.historyList = List||[]
                 this.windowContentLoading&&this.windowContentLoading.close()
                 //使用模型
-                this.model = this.historyList.length?this.historyList[this.historyList.length-1].Model:''
+                this.model = this.historyList.length?this.historyList[this.historyList.length-1].Model:'GPT-4 Turbo'
                 //如果有历史记录,则滚动到底部
                 this.$nextTick(()=>{
                     const windowContentWrap = document.querySelector('.window-content-wrap')
@@ -207,7 +208,7 @@ export default {
             this.activeWindowId=0
             this.activeWindow=null
             this.historyList=[]
-            this.model=''
+            this.model='GPT-4 Turbo'
             //this.inputText=''
             this.isTyping = false
         },
@@ -293,7 +294,7 @@ export default {
                 this.inputText+='\n'
                 return
             }
-            if(this.isTyping){
+            if(this.isTyping||this.answerLoading){
                 this.$message.warning('请等待回答完成')
                 return
             }
@@ -310,6 +311,7 @@ export default {
                 this.$message.warning('请输入提问')
                 return
             }
+            this.answerLoading=true
             this.activeWindowId===0&&(this.activeWindowId = -1)
             //this.activeWindowId!==0&&this.getWindowDetail()
             //mock 加入到historyList中
@@ -339,6 +341,7 @@ export default {
                 Ask:inputText,
                 Model:this.model
             }).then(res=>{
+                this.answerLoading=false
                 //在回答未获取前切换了新窗口
                 if(this.historyList.length===0){
                     this.getWindowList()
@@ -373,6 +376,8 @@ export default {
                 msg.Model = Model
                 msg.isPlay = true
                 this.historyList.splice(this.historyList.length-1,1,msg)
+            }).catch(()=>{
+                this.answerLoading=false
             })
         },
         //获取窗口列表

+ 1 - 1
src/views/operation_manage/AIQA/components/messageItem.vue

@@ -59,7 +59,7 @@ export default {
     },
     methods: {
         async playTyping(){
-            const writeText = (text,delay=150)=>{
+            const writeText = (text,delay=20)=>{
                 return new Promise((res,rej)=>{
                     setTimeout(()=>{
                         this.typingText+=text

+ 1 - 2
src/views/operation_manage/AIQA/components/newWindowHint.vue

@@ -2,8 +2,7 @@
     <div class="new-window-hint-wrap">
         <p class="title">使用说明:</p>
         <p>1、每账号每天最高500次问答。</p>
-        <p>2、在同一个对话窗口内提问,选择同一模型可联系上下文回答,切换模型后不支持。</p>
-        <p>3、历史问答默认用该对话窗口内第一个提问命名,可修改。</p>
+        <p>2、历史问答默认用该对话窗口内第一个提问命名,可修改。</p>
     </div>
 </template>
 

+ 17 - 8
src/views/rai_manage/activityManage/activityManage.vue

@@ -7,11 +7,11 @@
         <div class="tabs-box">
           <span v-for="(item, index) in listTitle" :key="item.ChartPermissionId" @click="tabsBoxBtn(item, index)" :class="index == tabsPitchon ? 'pitch' : ''">{{ item.PermissionName }}</span>
         </div>
-        <div style="display: flex">
-          <el-upload ref="imgUpload" action="#" :http-request="handleUploadImg" :show-file-list="false" accept="image/*">
-            <el-button type="primary">识图建会</el-button>
+        <div style="display: flex; align-items: center">
+          <el-upload style="height: 40px" ref="imgUpload" action="#" :http-request="handleUploadImg" :show-file-list="false" accept="image/*">
+            <el-button style="height: 40px" type="primary">识图建会</el-button>
           </el-upload>
-          <el-button style="margin-left: 20px" type="primary" @click="$router.push(!isResearch ? '/addActivity' : '/addPurchaserActivity')">添加活动</el-button>
+          <el-button style="margin-left: 20px; height: 40px" type="primary" @click="$router.push(!isResearch ? '/addActivity' : '/addPurchaserActivity')">添加活动</el-button>
         </div>
       </div>
     </el-card>
@@ -45,7 +45,7 @@
       <el-table :data="dataList" style="width: 100%" border>
         <el-table-column align="center" label="活动名称" min-width="285">
           <template slot-scope="{ row }">
-            <span class="editsty" @click="titleBtnClick(row.ActivityId)">{{ row.ActivityName }}</span>
+            <span :class="row.PublishStatus == 3 ? 'grey-color' : 'editsty'" @click="titleBtnClick(row.ActivityId)">{{ row.ActivityName }}</span>
           </template>
         </el-table-column>
         <el-table-column prop="ChartPermissionName" align="center" label="行业" min-width="90"></el-table-column>
@@ -65,14 +65,16 @@
           <template slot-scope="{ row }">
             <div class="operate-box">
               <p v-if="row.PublishStatus == 0 && tabsPitchon == 0" class="editsty" @click="operationBtn(row.ActivityId, '发布')">发布</p>
-              <p v-if="row.PublishStatus == 3" class="editsty" @click="operationBtn(row.ActivityId, '重新发布')">重新发布</p>
+              <p v-if="row.PublishStatus == 3" class="grey-color" @click="operationBtn(row.ActivityId, '重新发布')">重新发布</p>
               <p v-if="row.PublishStatus == 1" class="editsty" @click="operationBtn(row.ActivityId, '取消发布')">取消发布</p>
               &nbsp;&nbsp;
-              <p class="editsty" @click="editBtn(row.ActivityId, row.PublishStatus)">编辑</p>
+              <p :class="row.PublishStatus == 3 ? 'grey-color' : 'editsty'" @click="editBtn(row.ActivityId, row.PublishStatus)">编辑</p>
               &nbsp;&nbsp;
               <p class="deletesty" v-if="row.PublishStatus == 0 && tabsPitchon == 0" @click="operationBtn(row.ActivityId, '删除')">删除</p>
               <p class="editsty" v-if="row.IsShowSigninButton" @click="handleDownLoadImg(row)">下载签到码</p>
-              <p v-if="row.ChartPermissionId === 31 && tabsPitchon == 0" class="editsty" @click="overheadHandler(row.ActivityId, '置顶')">&nbsp;&nbsp;{{ row.TopTime == 0 ? "置顶" : "取消置顶" }}</p>
+              <p v-if="row.ChartPermissionId === 31 && tabsPitchon == 0 && row.PublishStatus == 1" class="editsty" @click="overheadHandler(row.ActivityId, '置顶')">
+                &nbsp;&nbsp;{{ row.TopTime == 0 ? "置顶" : "取消置顶" }}
+              </p>
             </div>
           </template>
         </el-table-column>
@@ -437,5 +439,12 @@ export default {
       flex-shrink: 0;
     }
   }
+  .el-upload {
+    height: 40px !important;
+    min-height: 40px !important;
+  }
+  .grey-color {
+    cursor: pointer;
+  }
 }
 </style>

+ 16 - 20
src/views/rai_manage/activityManage/applyManage.vue

@@ -37,14 +37,8 @@
           <el-button type="primary" @click="sendMessage">发送模板消息</el-button>
         </div>
         <div>
-          <el-select placeholder="行业" clearable v-model="industry" @change="conditionChange" style="margin-bottom: 20px"
-          v-if="!isResearch">
-            <el-option
-              v-for="item in chartPermissionList"
-              :label="item.PermissionName"
-              :key="item.ChartPermissionId"
-              :value="item.ChartPermissionId"
-            ></el-option>
+          <el-select placeholder="行业" clearable v-model="industry" @change="conditionChange" style="margin-bottom: 20px" v-if="!isResearch">
+            <el-option v-for="item in chartPermissionList" :label="item.PermissionName" :key="item.ChartPermissionId" :value="item.ChartPermissionId"></el-option>
           </el-select>
           <el-select placeholder="活动类型" clearable @focus="activityType" v-model="cactivityTypeVal" @change="conditionChange" style="margin-bottom: 20px">
             <el-option v-for="item in cactivityTypeList" :label="item.ActivityTypeName" :key="item.ActivityTypeId" :value="item.ActivityTypeId"></el-option>
@@ -81,7 +75,7 @@
               <span v-if="row.SignupFailPeopleNum == 0">--</span>
               <span v-else class="editsty" @click="particularsBtn('报名失败详情', row.ActivityId)">{{ row.SignupFailPeopleNum }}</span>
             </div>
-            <span v-else @click="handleRowClick(row, item.key)" :style="handleRowStyle(item.key)">{{ handleRowContent(row, item.key) }}</span>
+            <span v-else @click="handleRowClick(row, item.key)" :style="handleRowStyle(item.key, row)">{{ handleRowContent(row, item.key) }}</span>
           </template>
         </el-table-column>
       </el-table>
@@ -118,7 +112,7 @@ import ParticularsDialog from "../components/apply/particularsDialog.vue";
 import AtcParticulars from "../components/atcParticulars.vue";
 import GenerationAsk from "../components/generationAsk.vue";
 import SummaryRemind from "../components/apply/summaryRemind.vue";
-import { ListTitle , purchaserListTitle , TableApplyColums, StatusSelect, PublishSelect } from "../components/apply/applyTableColums";
+import { ListTitle, purchaserListTitle, TableApplyColums, StatusSelect, PublishSelect } from "../components/apply/applyTableColums";
 import TemplateMessage from "../components/apply/templateMessage.vue";
 export default {
   name: "",
@@ -166,11 +160,11 @@ export default {
   },
   computed: {
     // 弘则 研选 是否是研选
-    isResearch(){
-      return this.$route.path.indexOf("purchaser")!=-1?true:false
+    isResearch() {
+      return this.$route.path.indexOf("purchaser") != -1 ? true : false;
     },
     listTitle() {
-      return !this.isResearch?ListTitle:purchaserListTitle;
+      return !this.isResearch ? ListTitle : purchaserListTitle;
     },
     statusSelect() {
       return StatusSelect;
@@ -187,7 +181,7 @@ export default {
       this.page_no = 1;
       this.init();
       this.getsDataList();
-    }
+    },
   },
   created() {},
   mounted() {
@@ -225,7 +219,7 @@ export default {
           ActivityTypeId: this.cactivityTypeVal,
           ActiveState: this.cactivityStatus,
           PublishStatus: this.publishStatus ? Number(this.publishStatus) : 2,
-          IsResearch:this.isResearch
+          IsResearch: this.isResearch,
         })
         .then((res) => {
           if (res.Ret !== 200) return;
@@ -315,7 +309,7 @@ export default {
     },
     //获取行业
     chartPermission() {
-      raiInterface.chartPermission({IsHideResearch:!this.isResearch}).then((res) => {
+      raiInterface.chartPermission({ IsHideResearch: !this.isResearch }).then((res) => {
         if (res.Ret === 200) {
           this.chartPermissionList = res.Data.List;
         }
@@ -372,9 +366,11 @@ export default {
       }
     },
     /* 表格行的样式 */
-    handleRowStyle(key) {
-      let isStyle = ["ActivityName", "SignupPeopleNum", "AppointmentPeopleNum", "AskNum"];
-      return isStyle.includes(key) ? "color: #409eff; cursor: pointer" : "";
+    handleRowStyle(key, row) {
+      if (["ActivityName", "SignupPeopleNum", "AppointmentPeopleNum", "AskNum"].includes(key)) {
+        return row.PublishStatus == 3 ? "cursor: pointer" : "color: #409eff; cursor: pointer";
+      }
+      return "";
     },
     /* 表格行的点击事件 */
     handleRowClick(row, key) {
@@ -403,7 +399,7 @@ export default {
         let status = row[key] == 1 ? "未开始" : row[key] == 2 ? "进行中" : "已结束";
         return status;
       } else if (key == "PublishStatus") {
-        let status = row["PublishStatus"] == 1 ? "已发布" : row["PublishStatus"] == 2 ?"未发布":"已取消";
+        let status = row["PublishStatus"] == 1 ? "已发布" : row["PublishStatus"] == 2 ? "未发布" : "已取消";
         return status;
       } else {
         return row[key];

+ 4 - 4
src/views/rai_manage/activityManage/components/addActivity.vue

@@ -144,7 +144,7 @@
                   <el-radio :label="1">仅本组客户可见</el-radio>
                   <el-radio :label="2">所有组客户可见</el-radio>
                 </el-radio-group>
-                <el-checkbox v-model="decisionChecked">仅决策人可见</el-checkbox>
+                <el-checkbox v-model="decisionChecked">仅KP可见</el-checkbox>
               </div>
               <div style="display: flex">
                 <span style="width: 70px; flex-shrink: 0" class="text-right"> 套餐类型: </span>
@@ -410,7 +410,7 @@ export default {
     if (!this.isResearch) {
       this.chartPermission();
     } else {
-      this.optionFormregion = "买方研选";
+      this.optionFormregion = "研选订阅";
     }
     this.getActivityType();
     this.customerTypelist();
@@ -643,7 +643,7 @@ export default {
       this.saveTheRelease(type, arr, VoiceList, VideoDetail[0]);
     },
     //保存或发布
-    async saveTheRelease(type, arr, VoiceList, VideoDetail) {
+    saveTheRelease: _.debounce(async function (type, arr, VoiceList, VideoDetail) {
       let RefPage = this.$refs.researchSelect;
       let PointsSet = RefPage.PointsSet;
       const res = await raiInterface.preserveAndPublishAdd({
@@ -683,7 +683,7 @@ export default {
       if (res.Ret !== 200) return;
       this.$message.success("操作成功!");
       this.$router.back();
-    },
+    }, 500),
     //获取行业
     chartPermission() {
       raiInterface.chartPermissionList({ IsHideResearch: !this.isResearch }).then((res) => {

+ 1 - 1
src/views/rai_manage/activityManage/roadShow/components/addVideoDlg.vue

@@ -26,7 +26,7 @@
           <el-form-item prop="industryId">
             <el-select style="width: 100%" placeholder="请选择行业" v-model="addEditVideo.industryId" clearable @change="selectChangeHandle">
               <el-option 
-              v-for="item in chartPermissionList.filter(item => item.PermissionName != '宏观' && item.PermissionName != '策略' && item.PermissionName != '买方研选')" 
+              v-for="item in chartPermissionList.filter(item => item.PermissionName != '宏观' && item.PermissionName != '策略' && item.PermissionName != '研选订阅')" 
                 :label="item.PermissionName" :key="item.ChartPermissionId" :value="item.ChartPermissionId"></el-option>
             </el-select>
           </el-form-item>

+ 1 - 1
src/views/rai_manage/activityManage/roadShow/components/releaseAudio.vue

@@ -25,7 +25,7 @@
           <el-form-item prop="industryId">
             <el-select style="width: 100%" placeholder="请选择行业" v-model="addEditAudio.industryId" clearable @change="selectChangeHandle">
               <el-option
-                v-for="item in chartPermissionList.filter((item) => item.PermissionName != '宏观' && item.PermissionName != '策略' && item.PermissionName != '买方研选')"
+                v-for="item in chartPermissionList.filter((item) => item.PermissionName != '宏观' && item.PermissionName != '策略' && item.PermissionName != '研选订阅')"
                 :label="item.PermissionName"
                 :key="item.ChartPermissionId"
                 :value="item.ChartPermissionId"

+ 3 - 1
src/views/rai_manage/activityManage/roadShowList.vue

@@ -161,7 +161,9 @@ export default {
     },
     //获取行业
     async chartPermission() {
-      const res = await raiInterface.chartPermission();
+      const res = await raiInterface.chartPermission({
+        IsHideResearch: true,
+      });
       if (res.Ret === 200) {
         this.chartPermissionList = res.Data.List;
       }

+ 1 - 1
src/views/rai_manage/activityManage/specialResearch.vue

@@ -177,7 +177,7 @@ export default {
     },
     //获取行业
     chartPermission() {
-      raiInterface.getNoTacticsfirst().then((res) => {
+      raiInterface.getActivitySpecial().then((res) => {
         if (res.Ret === 200) {
           this.chartPermissionList = res.Data.List;
         }

+ 13 - 67
src/views/rai_manage/activityManage/specialResearch/addResearch.vue

@@ -4,12 +4,7 @@
       <el-form :model="ruleForm" :rules="rules" ref="ruleFormList" label-width="100px" class="demo-ruleForm">
         <el-form-item label="所属行业:" prop="industry">
           <el-select placeholder="请选择行业" style="width: 396px" clearable v-model="ruleForm.industry" @change="changeHandel">
-            <el-option
-              v-for="item in chartPermissionList"
-              :label="item.PermissionName"
-              :key="item.PermissionName"
-              :value="item.PermissionName"
-            ></el-option>
+            <el-option v-for="item in chartPermissionList" :label="item.PermissionName" :key="item.PermissionName" :value="item.PermissionName"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item label="调研主题:" prop="theme">
@@ -22,12 +17,7 @@
           <el-radio-group v-model="ruleForm.modality">
             <el-radio v-for="item in modalityRadio" :key="item.id" :label="item.id">{{ item.name }}</el-radio>
           </el-radio-group>
-          <el-input
-            v-model="ruleForm.city"
-            v-if="ruleForm.modality == 2"
-            style="width: 248px; margin-left: 10px"
-            placeholder="请输入调研城市,多个城市以','隔开"
-          ></el-input>
+          <el-input v-model="ruleForm.city" v-if="ruleForm.modality == 2" style="width: 248px; margin-left: 10px" placeholder="请输入调研城市,多个城市以','隔开"></el-input>
         </el-form-item>
         <el-form-item label="主题标签:">
           <div style="display: flex; align-items: center; flex-wrap: wrap">
@@ -47,25 +37,13 @@
               </el-cascader>
             </el-form-item>
             <el-form-item>
-              <el-select
-                style="margin: 0 15px 10px 0"
-                v-model="ruleForm.mark"
-                :disabled="selectDisabled"
-                @focus="markSelectFocus"
-                multiple
-                placeholder="请选择关联标的"
-              >
-                <el-option v-for="item in markOptions" :key="item.IndustrialSubjectId" :value="item.IndustrialSubjectId" :label="item.SubjectName">
-                </el-option>
+              <el-select style="margin: 0 15px 10px 0" v-model="ruleForm.mark" :disabled="selectDisabled" @focus="markSelectFocus" multiple placeholder="请选择关联标的">
+                <el-option v-for="item in markOptions" :key="item.IndustrialSubjectId" :value="item.IndustrialSubjectId" :label="item.SubjectName"> </el-option>
               </el-select>
             </el-form-item>
             <div v-for="(item, index) in addSubjectData" :key="index" style="display: inline-block">
               <el-input style="width: 220px; margin: 0 5px 10px 0" v-model="item.subjectVal" placeholder="请输入标的名称" type="text"> </el-input>
-              <img
-                @click="deleteSubject(item, index)"
-                style="width: 18px; margin-right: 20px; vertical-align: middle"
-                src="~@/assets/img/icons/delete-Item.png"
-              />
+              <img @click="deleteSubject(item, index)" style="width: 18px; margin-right: 20px; vertical-align: middle" src="~@/assets/img/icons/delete-Item.png" />
             </div>
             <el-tooltip class="item" effect="dark" content="添加标的" placement="top-start">
               <img @click="addLabelClick" class="editsty" src="~@/assets/img/set_m/add_ico.png" style="margin: 0 10px 10px" />
@@ -74,27 +52,14 @@
           <div style="display: flex; align-items: center; margin-top: 10px">
             <el-checkbox v-model="ruleForm.isMark">小程序内显示标的名称</el-checkbox>
             <el-checkbox style="margin-left: 10px" v-model="radioTemporary">临时标签</el-checkbox>
-            <el-input
-              style="width: 300px; margin: 0 10px"
-              v-model="valTemporary"
-              @focus="radioTemporary = true"
-              placeholder="请输入标签名称"
-              type="text"
-            ></el-input>
+            <el-input style="width: 300px; margin: 0 10px" v-model="valTemporary" @focus="radioTemporary = true" placeholder="请输入标签名称" type="text"></el-input>
             <div class="editsty" @click="dialogVisibleSubject = true">查询标的</div>
           </div>
         </el-form-item>
         <el-form-item label="活动可见:" prop="checkedCities">
           <div style="display: flex">
             <span style="width: 70px" class="text-right"> 套餐类型: </span>
-            <el-checkbox
-              :indeterminate="isIndeterminate"
-              v-model="ruleForm.checkAll"
-              @change="handleCheckAllChange"
-              :disabled="checkAllIs"
-              style="margin-right: 30px"
-              >全选</el-checkbox
-            >
+            <el-checkbox :indeterminate="isIndeterminate" v-model="ruleForm.checkAll" @change="handleCheckAllChange" :disabled="checkAllIs" style="margin-right: 30px">全选</el-checkbox>
             <el-checkbox-group v-model="ruleForm.checkedCities" @change="handleCheckedCitiesChange">
               <el-checkbox v-for="item in cities" :label="item.CustomerTypeId" :key="item.CustomerTypeId">
                 {{ item.CustomerName }}
@@ -130,29 +95,10 @@
         </div>
       </el-form>
     </el-card>
-    <el-dialog
-      width="500px"
-      v-dialogDrag
-      :close-on-click-modal="false"
-      :modal-append-to-body="false"
-      center
-      title="查询标的"
-      :visible.sync="dialogVisibleSubject"
-      :before-close="handleCloseSubject"
-    >
+    <el-dialog width="500px" v-dialogDrag :close-on-click-modal="false" :modal-append-to-body="false" center title="查询标的" :visible.sync="dialogVisibleSubject" :before-close="handleCloseSubject">
       <div>
-        <el-select
-          style="width: 100%"
-          v-model="addSubjectName"
-          remote
-          :remote-method="remoteMethod"
-          clearable
-          filterable
-          @change="searchInfo"
-          placeholder="请输入标的名称"
-        >
-          <el-option v-for="item in addSubjectOptions" :key="item.IndustrialSubjectId" :label="item.SubjectName" :value="item.SubjectName">
-          </el-option>
+        <el-select style="width: 100%" v-model="addSubjectName" remote :remote-method="remoteMethod" clearable filterable @change="searchInfo" placeholder="请输入标的名称">
+          <el-option v-for="item in addSubjectOptions" :key="item.IndustrialSubjectId" :label="item.SubjectName" :value="item.SubjectName"> </el-option>
         </el-select>
       </div>
       <p class="subject-text" v-if="isShowSubject">暂无数据</p>
@@ -263,7 +209,7 @@ export default {
   methods: {
     //获取行业
     chartPermission() {
-      raiInterface.getNoTacticsfirst().then((res) => {
+      raiInterface.getActivitySpecial().then((res) => {
         if (res.Ret === 200) {
           this.chartPermissionList = res.Data.List;
         }
@@ -424,7 +370,7 @@ export default {
       this.dialogVisibleSubject = false;
     },
     //保持或者发布
-    submitForm(type) {
+    submitForm: _.debounce(function (type) {
       if (this.selectDisabled) {
         if (!this.valTemporary) return this.$message.error("请输入临时标签");
         let validateFieldList = [];
@@ -450,7 +396,7 @@ export default {
           }
         });
       }
-    },
+    }, 500),
     async postPublish(type) {
       let arr = this.ruleForm.property.map((item) => {
         return item[1];

+ 1 - 1
src/views/rai_manage/activityManage/specialResearch/determineTravel.vue

@@ -317,7 +317,7 @@ export default {
   methods: {
     //获取行业
     chartPermission() {
-      raiInterface.getNoTacticsfirst().then((res) => {
+      raiInterface.getActivitySpecial().then((res) => {
         if (res.Ret === 200) {
           this.chartPermissionList = res.Data.List;
         }

+ 121 - 134
src/views/rai_manage/components/addChoiceness.vue

@@ -11,7 +11,7 @@
           </el-select>
         </el-col>
         <el-col :span="12">
-          <el-select v-if="updateMode == '继承往期'" v-model="inheritNum" placeholder="选择继承第几期" clearable @clear="inheritNumClear" @change="getDetail">
+          <el-select v-if="updateMode == '继承往期'" v-model="inheritNum" placeholder="选择继承第几期" clearable @change="getDetail">
             <el-option v-for="item in updateModeList" :key="item.Periods" :label="item.InheritPeriodsName" :value="item.Periods"></el-option>
           </el-select>
         </el-col>
@@ -42,7 +42,7 @@
           </el-form-item>
           <!-- 变更说明 -->
           <!-- 富文本 -->
-          <rich-text ref="oneRich" :spareId="contentValue" :isText="contentText" />
+          <rich-text ref="oneRich" v-model="marketStrategy" :spareId="contentValue" :isText="contentText" />
           <el-form-item prop="reportLink">
             <div style="display: flex; align-items: center; margin-top: 10px">
               <span style="flex-shrink: 0">详细报告链接:</span>
@@ -58,47 +58,54 @@
             </div>
           </draggable>
           <div v-for="(item, index) in industryList" :key="item.ChartPermissionId">
-            <RichText v-show="industryIndex == index" :ref="'logic' + index" :spareId="'logictest' + index" :isText="contentTextLogic" />
-          </div>
-          <draggable :list="industryListItem" animation="300" class="classification" filter=".addIndustrial" :move="onMove" @update="ificationSortChange">
-            <div v-for="(val, num) in industryListItem" :key="val.IndustrialSubjectId" class="industrial" @click="ificationIndustrialBtn(val, num)" :class="num == ificationIndustrial ? 'pitch' : ''">
-              <span style="margin-right: 19px">{{ val.IndustrialSubjectName }}</span>
-              <span v-if="num == ificationIndustrial">
-                <img src="~@/assets/img/icons/edit1.png" style="width: 12px; height: 12px; marginright: 10px" @click="editText(val, num)" />
-                <i class="el-icon-close" @click="deleteClassify(val, num)"></i>
-              </span>
-            </div>
-            <div class="addIndustrial" @click="addMulti">
-              <i class="el-icon-plus"></i>
-              <span>添加标的</span>
-            </div>
-          </draggable>
-          <template v-for="(val, num) in industryListItem">
-            <div class="industrial-is-new" :key="val.IndustrialSubjectId" v-if="num == ificationIndustrial">
-              <el-checkbox v-model="val.IsNew" :true-label="1" :false-label="0">显示new标签</el-checkbox>
-            </div>
-          </template>
-          <div v-if="industryListItem.length" style="margin-bottom: 20px; display: flex; align-items: center">
-            <div style="display: flex; align-items: center" v-for="(val, num) in industryListItem[ificationIndustrial].CompanyLabel" :key="num">
-              <el-input style="width: 260px; margin-right: 15px" v-model="val.name" placeholder="请输入公司标签"></el-input>
-              <img class="delete-item-icon" v-if="num > 0" @click="deleteLabelItem(val, num)" src="~@/assets/img/icons/delete-Item.png" alt="" />
+            <div v-show="industryIndex == index">
+              <RichText v-model="item.BodyChartSummary" :ref="'logic' + index" :spareId="'logictest' + index" :isText="contentTextLogic" />
+              <draggable :list="item.List" animation="300" class="classification" filter=".addIndustrial" :move="onMove" @update="ificationSortChange">
+                <div v-for="(val, num) in item.List" :key="val.IndustrialSubjectId" class="industrial" @click="ificationIndustrialBtn(val, num)" :class="num == ificationIndustrial ? 'pitch' : ''">
+                  <span style="margin-right: 19px">{{ val.IndustrialSubjectName }}</span>
+                  <span v-if="num == ificationIndustrial">
+                    <img src="~@/assets/img/icons/edit1.png" style="width: 12px; height: 12px; marginright: 10px" @click="editText(val, num)" />
+                    <i class="el-icon-close" @click="deleteClassify(val, num)"></i>
+                  </span>
+                </div>
+                <div class="addIndustrial" @click="addMulti" v-if="industryIndex == index">
+                  <i class="el-icon-plus"></i>
+                  <span>添加标的</span>
+                </div>
+              </draggable>
+              <template v-for="(val, num) in item.List">
+                <div :key="val.IndustrialSubjectId" v-show="industryIndex == index">
+                  <div class="industrial-is-new" v-show="num == ificationIndustrial">
+                    <el-checkbox v-model="val.IsNew" :true-label="1" :false-label="0">显示new标签</el-checkbox>
+                  </div>
+                  <div style="margin-bottom: 20px; display: flex; align-items: center" v-show="num == ificationIndustrial">
+                    <div style="display: flex; align-items: center" v-for="(son, num) in val.CompanyLabel" :key="num">
+                      <el-input style="width: 260px; margin-right: 15px" v-model="son.name" placeholder="请输入公司标签"></el-input>
+                      <img class="delete-item-icon" v-if="num > 0" @click="deleteLabelItem(val, num)" src="~@/assets/img/icons/delete-Item.png" alt="" />
+                    </div>
+                    <el-tooltip class="item" effect="dark" content="添加标签" placement="top-start">
+                      <img @click="addLabelClick(val)" class="editsty" src="~@/assets/img/set_m/add_ico.png" />
+                    </el-tooltip>
+                  </div>
+                  <rich-text :ref="'twoRich' + num" v-model="val.Body" :spareId="contentValueTwo" :isText="contentTextTwo" v-show="num == ificationIndustrial" />
+                </div>
+              </template>
             </div>
-            <el-tooltip class="item" effect="dark" content="添加标签" placement="top-start">
-              <img @click="addLabelClick" class="editsty" src="~@/assets/img/set_m/add_ico.png" />
-            </el-tooltip>
           </div>
         </div>
 
-        <rich-text ref="twoRich" :spareId="contentValueTwo" :isText="contentTextTwo" />
-        <div class="content-resource">
-          <span class="resource">产业资源包:</span>
-          <span class="show">{{ industrialSubjectName }}</span>
-        </div>
-        <div class="content-resource">
-          <span class="resource">综述报告:</span>
-          <span class="show">{{ overviewList.Title }}</span>
-          <div style="margin-left: 20px">
-            <el-switch @change="switchChangeHandler" v-model="overviewList.IsShowOverviewArticle" :active-value="1" :inactive-value="0" active-text="显示链接" inactive-text="不显示链接"> </el-switch>
+        <div>
+          <div class="content-resource">
+            <span class="resource">产业资源包:</span>
+            <span class="show">{{ industrialSubjectName }}</span>
+          </div>
+          <div class="content-resource">
+            <span class="resource">综述报告:</span>
+            <span class="show">{{ overviewList.Title }}</span>
+            <div style="margin-left: 20px">
+              <el-switch @change="switchChangeHandler" v-model="overviewList.IsShowOverviewArticle" :active-value="1" :inactive-value="0" active-text="显示链接" inactive-text="不显示链接">
+              </el-switch>
+            </div>
           </div>
         </div>
         <div class="content-bottom">
@@ -131,10 +138,11 @@
 import RichText from "./richText.vue";
 import { raiInterface } from "@/api/api.js";
 import draggable from "vuedraggable";
+import TemplateMessage from "./apply/templateMessage.vue";
 
 export default {
   name: "",
-  components: { RichText, draggable },
+  components: { RichText, draggable, TemplateMessage },
   props: {},
   data() {
     return {
@@ -154,10 +162,6 @@ export default {
       },
       rules: {
         title: [{ required: true, message: "请输入标题", trigger: "blur" }],
-        // author: [{ required: true, message: "请输入作者", trigger: "blur" }],
-        // time: [{ required: true, message: "请输入时间", trigger: "change" }],
-        // explain: [{ required: true, message: "请输入产品说明", trigger: "blur" }],
-        // reportLink: [{ required: true, message: "请输入报告链接", trigger: "blur" }],
       },
       industryList: [], //行业
       industryIndex: 0, //
@@ -168,61 +172,76 @@ export default {
       companyList: [],
       timeout: null,
       isShowStatus: true,
-      industryListItem: [],
       industrialSubjectName: "",
       chartPermissionId: "", //分类id
       subjectList: [],
       updateModeList: [], //期数的数组
       editNum: "",
       overviewList: {},
+      marketStrategy: "",
+      timeInterval: null, // 定时器
     };
   },
   computed: {},
-  watch: {
-    industryListItem: {
-      handler(nval) {
-        if (nval.length > 0) {
-          this.industrialSubjectName = this.industryListItem[this.ificationIndustrial].IndustrialManagementName || "";
-          this.overviewList = {
-            ArticleId: this.industryListItem[this.ificationIndustrial].OverviewArticleId,
-            Title: this.industryListItem[this.ificationIndustrial].OverviewArticleTitle,
-            IsShowOverviewArticle: this.industryListItem[this.ificationIndustrial].IsShowOverviewArticle,
-          };
-        } else {
-          this.industrialSubjectName = "";
-          this.overviewList = { ArticleId: 0, Title: "", IsShowOverviewArticle: 0 };
-        }
-      },
-      deep: true,
-    },
-  },
-  created() {},
   mounted() {
     if (this.$route.query.id) {
       this.isShowStatus = this.$route.query.status == 0;
       this.getDetail();
     } else {
       this.getNoTacticsfirst();
+      this.dataInit();
     }
     this.getListPeriods();
   },
   methods: {
+    // 报告的缓存处理数据
+    dataInit() {
+      if (sessionStorage.getItem("addChoicenessQY")) {
+        let data = JSON.parse(sessionStorage.getItem("addChoicenessQY"));
+        setTimeout(async () => {
+          this.industryList = data.industryList;
+          this.industryIndex = data.industryIndex;
+          this.ificationIndustrial = data.ificationIndustrial;
+          this.updateMode = data.updateMode;
+          this.inheritNum = data.inheritNum;
+          this.companyList = data.companyList;
+          this.industrialSubjectName = data.industrialSubjectName;
+          this.chartPermissionId = data.chartPermissionId;
+          this.subjectList = data.subjectList;
+          this.updateModeList = data.updateModeList;
+          this.editNum = data.editNum;
+          this.overviewList = data.overviewList;
+          this.ruleForm = data.ruleForm;
+          this.marketStrategy = data.MarketStrategy;
+        }, 200);
+      }
+      this.timeInterval = setInterval(() => {
+        let params = {
+          industryList: this.industryList,
+          industryIndex: this.industryIndex,
+          ificationIndustrial: this.ificationIndustrial,
+          updateMode: this.updateMode,
+          inheritNum: this.inheritNum,
+          companyList: this.companyList,
+          industrialSubjectName: this.industrialSubjectName,
+          chartPermissionId: this.chartPermissionId,
+          subjectList: this.subjectList,
+          updateModeList: this.updateModeList,
+          editNum: this.editNum,
+          overviewList: this.overviewList,
+          ruleForm: this.ruleForm,
+          MarketStrategy: this.marketStrategy,
+        };
+        sessionStorage.setItem("addChoicenessQY", JSON.stringify(params));
+      }, 120000);
+    },
     updateModeChange() {
       if (this.updateMode == "重新编辑") {
         this.init();
         this.industryList = [];
-        this.industryListItem = [];
         this.getNoTacticsfirst();
       }
     },
-    inheritNumClear() {
-      if (this.inheritNum == "") {
-        // this.init();
-        // this.industryList=[]
-        // this.industryListItem=[]
-        // this.getNoTacticsfirst();
-      }
-    },
     //获取编辑详情
     async getDetail() {
       const res = await raiInterface.reportSelectionDetail({ ArticleId: this.$route.query.id || "", Periods: this.inheritNum || "" });
@@ -240,13 +259,12 @@ export default {
           explain: res.Data.ProductDescription, //说明
           reportLink: res.Data.ReportLink, //变更
         };
-        this.$refs["oneRich"].value = res.Data.MarketStrategy;
+        this.marketStrategy = res.Data.MarketStrategy;
         this.inheritNum = this.inheritNum ? this.inheritNum : res.Data.InheritPeriods;
         this.industryList = res.Data.List;
         setTimeout(() => {
           res.Data.List.forEach((item, index) => {
-            this.$refs["logic" + index][0].value = item.BodyChartSummary && item.BodyChartSummary;
-            item.List.forEach((key) => {
+            item.List.forEach((key, i) => {
               key.CompanyLabel = key.CompanyLabel
                 ? key.CompanyLabel.map((val, i) => {
                     let obj = {
@@ -265,8 +283,6 @@ export default {
           });
         }, 300);
         this.chartPermissionId = res.Data.List[0].ChartPermissionId;
-        this.industryListItem = res.Data.List[0].List || [];
-        this.$refs.twoRich.value = res.Data.List[0].List ? res.Data.List[0].List[0].Body : "";
         this.industrialSubjectName = res.Data.List[0].List ? res.Data.List[0].List[0].IndustrialManagementName : "";
         this.overviewList = {
           ArticleId: res.Data.List[0].List && res.Data.List[0].List[0].OverviewArticleId,
@@ -281,50 +297,20 @@ export default {
       if (res.Ret === 200) {
         this.industryList = res.Data.List;
         this.chartPermissionId = res.Data.List[0].ChartPermissionId;
-        this.industryListItem = res.Data.List[0].List || [];
       }
     },
     //点击产业的事件
     industryBtn(item, index) {
-      if (this.industryListItem.length > 0) {
-        this.industryListItem[this.ificationIndustrial].Body = this.$refs["twoRich"].value;
-      }
-      this.industryList[this.industryIndex].BodyChartSummary = this.$refs["logic" + this.industryIndex][0].value;
       if (index !== this.industryIndex) {
         this.industryIndex = index;
-        this.industryListItem = item.List || [];
-        this.industryListItem.forEach((item) => {
-          if (item.CompanyLabel && typeof item.CompanyLabel[0] === "string") {
-            item.CompanyLabel = item.CompanyLabel
-              ? item.CompanyLabel.map((key, index) => {
-                  let obj = {
-                    name: key,
-                    value: index + 1,
-                  };
-                  return obj;
-                })
-              : [
-                  {
-                    name: "",
-                    value: 1,
-                  },
-                ];
-          }
-        });
-
-        this.$refs.twoRich.value = item.List[0] ? item.List[0].Body : "";
         this.chartPermissionId = item.ChartPermissionId;
         this.ificationIndustrial = 0;
       }
     },
     //标的的点击事件 处理
     ificationIndustrialBtn(item, index) {
-      if (this.industryListItem.length > 0) {
-        this.industryListItem[this.ificationIndustrial].Body = this.$refs["twoRich"].value;
-      }
       if (index !== this.ificationIndustrial) {
         this.ificationIndustrial = index;
-        this.$refs.twoRich.value = item.Body || "";
         this.industrialSubjectName = item.IndustrialManagementName || "";
         this.overviewList = {
           ArticleId: item.OverviewArticleId,
@@ -351,7 +337,6 @@ export default {
         .then(() => {
           this.industryList[this.industryIndex].List.splice(index, 1);
           this.ificationIndustrial = 0;
-          this.$refs["twoRich"].value = this.industryList[this.industryIndex].List.length > 0 ? this.industryList[this.industryIndex].List[0].Body : "";
           this.$message({
             type: "success",
             message: "删除成功!",
@@ -440,8 +425,8 @@ export default {
               IndustrialManagementName: arr.IndustryName,
               IndustrialSubjectId: arr.IndustrialSubjectId + "",
               IndustrialSubjectName: arr.SubjectName,
-              CompanyLabel: item.List[this.editNum].CompanyLabel && item.List[this.editNum].CompanyLabel.length>0?
-                            item.List[this.editNum].CompanyLabel : [{ name: "", value: item.List.length + 1 }],
+              CompanyLabel:
+                item.List[this.editNum].CompanyLabel && item.List[this.editNum].CompanyLabel.length > 0 ? item.List[this.editNum].CompanyLabel : [{ name: "", value: item.List.length + 1 }],
               OverviewArticleId: overviewList.ArticleId,
               OverviewArticleTitle: overviewList.Title,
               IsShowOverviewArticle: overviewList.IsShowOverviewArticle,
@@ -470,15 +455,9 @@ export default {
       }
     },
     //保存 发布
-    confirm(type) {
+    confirm: _.debounce(function (type) {
       this.$refs.ruleForm.validate(async (val) => {
         if (val) {
-          if (this.industryListItem.length > 0) {
-            this.industryListItem[this.ificationIndustrial].Body = this.$refs["twoRich"].value;
-          } else if (this.$refs["twoRich"].value) {
-            this.$message.error("文本内容无对应标的,请选择标的!");
-            return;
-          }
           let isText = [];
           this.industryList.forEach((item) => {
             item.List.forEach((key) => {
@@ -489,7 +468,6 @@ export default {
             return this.$message.error("请输入公司标签");
           }
           let params = this.dataHandle(type);
-          // console.log(params);
           if (type == "预览") {
             sessionStorage.setItem("choicenessPre", JSON.stringify(params));
             let { href } = this.$router.resolve({ name: "预览报告精选" });
@@ -497,6 +475,8 @@ export default {
           } else {
             const res = await raiInterface.industrialSubjectPreserveAndPublish(params);
             if (res.Ret === 200) {
+              clearInterval(this.timeInterval);
+              sessionStorage.removeItem("addChoicenessQY");
               this.$message.success("操作成功!");
               this.init();
               this.$router.back();
@@ -504,11 +484,13 @@ export default {
           }
         }
       });
-    },
+    }, 500),
     //取消
     cancel() {
-      this.$router.back();
+      clearInterval(this.timeInterval);
+      sessionStorage.removeItem("addChoicenessQY");
       this.$refs["ruleForm"].resetFields();
+      this.$router.back();
     },
     async getListPeriods() {
       const res = await raiInterface.industrialSubjectListPeriods();
@@ -525,12 +507,11 @@ export default {
         reportLink: "", //变更
       };
       this.$refs["ruleForm"].resetFields();
-      this.$refs["oneRich"].value = "";
-      this.$refs["twoRich"].value = "";
+      this.marketStrategy = "";
     },
     // 标的下添加公司标签
-    addLabelClick() {
-      this.industryListItem[this.ificationIndustrial].CompanyLabel.push({ name: "", value: this.industryListItem.length + 1 });
+    addLabelClick(item) {
+      item.CompanyLabel.push({ name: "", value: item.CompanyLabel.length + 1 });
     },
     // 处理保存的数据
     dataHandle(type) {
@@ -549,7 +530,7 @@ export default {
           ListSubject: [...item.List],
         });
       });
-      if (this.$refs["oneRich"].value == "") {
+      if (this.marketStrategy == "") {
         this.$message.error("市场策略核心逻辑汇总不能为空");
       }
       let params = {
@@ -558,7 +539,7 @@ export default {
         Department: this.ruleForm.author,
         Title: this.ruleForm.title,
         DoType: type == "发布" ? 1 : 0,
-        MarketStrategy: this.$refs["oneRich"].value,
+        MarketStrategy: this.marketStrategy,
         InheritPeriods: this.inheritNum,
         List: arr,
         ProductDescription: this.ruleForm.explain,
@@ -569,13 +550,15 @@ export default {
       return params;
     },
     deleteLabelItem(item, index) {
-      this.industryListItem[this.ificationIndustrial].CompanyLabel.splice(index, 1);
+      item.CompanyLabel.splice(index, 1);
     },
     switchChangeHandler(e) {
-      this.industryListItem.forEach((item) => {
-        if (item.OverviewArticleId === this.overviewList.ArticleId) {
-          item.IsShowOverviewArticle = e;
-        }
+      this.industryList.forEach((_) => {
+        _.List.forEach((item) => {
+          if (item.OverviewArticleId === this.overviewList.ArticleId) {
+            item.IsShowOverviewArticle = e;
+          }
+        });
       });
     },
     // 拖拽排序更新
@@ -588,7 +571,6 @@ export default {
     },
     // 排序更新后的逻辑
     sortChangeFun(currentIndex, oldIndex, newIndex) {
-      console.log({ currentIndex, oldIndex, newIndex });
       let bigger, smaller;
       if (oldIndex > newIndex) {
         bigger = oldIndex;
@@ -614,7 +596,12 @@ export default {
       // 返回false表示不允许停靠
       return !!e.relatedContext.element;
     },
-  }
+  },
+  // 路由离开了 清除定时器
+  beforeRouteLeave(to, from, next) {
+    clearInterval(this.timeInterval);
+    next();
+  },
 };
 </script>
 <style lang="scss">

+ 40 - 50
src/views/rai_manage/components/addMorningMeeting.vue

@@ -12,23 +12,19 @@
               <h3>段落{{ index + 1 }}:</h3>
               <span class="dele" v-if="index !== 0" @click="deleteSection(index)"> <img src="~@/assets/img/icons/delete-Item.png" /></span>
             </div>
+            <div>
+              <el-checkbox v-model="item.isJumpNot">可跳转报告详情</el-checkbox>
+              <template v-if="item.isJumpNot">
+                <el-input style="margin: 20px 0" v-model="item.reportLink" placeholder="请输入报告链接"></el-input>
+                <el-input v-model="item.headTitle" placeholder="请输入首行标题"></el-input>
+              </template>
+            </div>
             <div class="fr-wrapper">
-              <froala
-              :id="`froala-editor-${index}`"
-              :ref="`froalaEditor${index}`"
-              :tag="'textarea'"
-              :config="froalaConfig"
-              v-model="item.content"
-              ></froala>
+              <froala :id="`froala-editor-${index}`" :ref="`froalaEditor${index}`" :tag="'textarea'" :config="froalaConfig" v-model="item.content"></froala>
             </div>
           </div>
           <div class="classify-box">
-            <el-select
-              placeholder="请选择行业"
-              v-model="item.industry"
-              value-key="ChartPermissionId"
-              @change="handleSelectChange(item, index, 'industry')"
-            >
+            <el-select placeholder="请选择行业" v-model="item.industry" value-key="ChartPermissionId" @change="handleSelectChange(item, index, 'industry')">
               <el-option
                 v-for="industry in industryData"
                 :key="industry.ChartPermissionId"
@@ -36,27 +32,11 @@
                 :value="{ ChartPermissionId: industry.ChartPermissionId, PermissionName: industry.PermissionName }"
               />
             </el-select>
-            <el-select
-              placeholder="请选择产业"
-              filterable
-              v-model="item.property"
-              value-key="ChartPermissionId"
-              @change="handleSelectChange(item, index, 'property')"
-            >
-              <el-option
-                v-for="property in getPropertyData(item.industry)"
-                :key="property.ChartPermissionId"
-                :label="property.PermissionName"
-                :value="property"
-              />
+            <el-select placeholder="请选择产业" filterable v-model="item.property" value-key="ChartPermissionId" @change="handleSelectChange(item, index, 'property')">
+              <el-option v-for="property in getPropertyData(item.industry)" :key="property.ChartPermissionId" :label="property.PermissionName" :value="property" />
             </el-select>
             <el-select multiple placeholder="请选择标的" v-model="item.subject" @focus="getSubjectData(item.property)">
-              <el-option
-                v-for="subject in subjectData"
-                :key="subject.IndustrialSubjectId"
-                :label="subject.SubjectName"
-                :value="subject.IndustrialSubjectId"
-              />
+              <el-option v-for="subject in subjectData" :key="subject.IndustrialSubjectId" :label="subject.SubjectName" :value="subject.IndustrialSubjectId" />
             </el-select>
           </div>
         </div>
@@ -74,25 +54,15 @@
 
 <script>
 import { raiInterface } from "@/api/api.js";
-export default {    
+export default {
   data() {
     var that = this;
     return {
       meettingDate: "",
       meetingId: 0,
       froalaConfig: {
-        toolbarButtons: [
-          "bold",
-          "italic",
-          "underline",
-          "strikeThrough",
-          "insertHR",
-          "fontSize",
-          "align",
-          "undo",
-          "redo",
-        ],
-        height: 150,
+        toolbarButtons: ["bold", "italic", "underline", "strikeThrough", "insertHR", "fontSize", "align", "undo", "redo"],
+        height: 260,
         fontSizeDefaultSelection: "16",
         quickInsertEnabled: false,
         theme: "dark", //主题
@@ -107,6 +77,9 @@ export default {
       },
       sectionData: [
         {
+          isJumpNot: false, //是否跳转
+          reportLink: "", //报告链接
+          headTitle: "", //报告标题
           content: "", //晨会内容
           industry: "", //行业
           property: "", //行业
@@ -130,6 +103,9 @@ export default {
         industry: "",
         property: "",
         subject: "",
+        isJumpNot: false, //是否跳转
+        reportLink: "", //报告链接
+        headTitle: "", //报告标题
       };
       this.sectionData.push(section);
     },
@@ -200,6 +176,9 @@ export default {
           content: item.content,
           industry: { ChartPermissionId: item.chartPermissionId, PermissionName: item.chartPermissionName },
           property: { ChartPermissionId: item.industryId, PermissionName: item.industryName },
+          reportLink: item.reportLink,
+          headTitle: item.title,
+          isJumpNot: item.reportLink ? true : false,
         };
         let subject = [];
         let industrialSubjectList = item.industrialSubjectList || [];
@@ -213,7 +192,7 @@ export default {
       this.dataLoading = false;
     },
     //保存 发布 取消 操作
-    async comfirm(type) {
+    comfirm: _.debounce(async function (type) {
       if (type === "cancel") {
         this.$router.back();
         return;
@@ -229,7 +208,7 @@ export default {
       /* if(type==="cancel"){} */
 
       this.isGoBack && this.$router.back();
-    },
+    }, 500),
     async pubMeeting() {
       const list = this.getSectionData();
       const res = await raiInterface.publishMorningMeeting({
@@ -288,6 +267,8 @@ export default {
           IndustryId: item.property.ChartPermissionId,
           IndustryName: item.property.PermissionName,
           IndustrialSubjectIds: item.subject.join(),
+          ReportLink: item.reportLink,
+          Title: item.headTitle,
         };
         list.push(temp);
       });
@@ -296,6 +277,14 @@ export default {
     //检查晨会内容
     checkContent() {
       for (let i = 0; i < this.sectionData.length; i++) {
+        if (this.sectionData[i].isJumpNot && this.sectionData[i].reportLink.length === 0) {
+          this.$message.warning(`请输入段落${i + 1}报告链接`);
+          return false;
+        }
+        if (this.sectionData[i].isJumpNot && this.sectionData[i].headTitle.length === 0) {
+          this.$message.warning(`请输入段落${i + 1}报告标题`);
+          return false;
+        }
         //所有的段落有值
         if (this.sectionData[i].content.length === 0) {
           this.$message.warning(`请输入段落${i + 1}的内容`);
@@ -400,8 +389,9 @@ export default {
     }
   }
   .fr-wrapper {
-  border-top: 1px solid #cccccc !important;
-  border-bottom: 1px solid #cccccc !important;
-}
+    margin-top: 20px;
+    border-top: 1px solid #cccccc !important;
+    border-bottom: 1px solid #cccccc !important;
+  }
 }
 </style>

+ 60 - 11
src/views/rai_manage/components/addRoadshow.vue

@@ -70,6 +70,7 @@
 import RichText from "./richText.vue";
 
 import { raiInterface } from "@/api/api.js";
+import { async } from "@antv/x6/lib/registry/marker/main";
 export default {
   name: "",
   components: { RichText },
@@ -101,6 +102,7 @@ export default {
       contentValue: "请输入内容",
       propertyDetai: [],
       isShowStatus: true,
+      timeInterval: null,
     };
   },
   computed: {},
@@ -110,14 +112,53 @@ export default {
     this.getIndustryList();
     if (this.$route.query.id) {
       this.getDetail();
+    } else {
+      this.dataInit();
     }
   },
   methods: {
-    //
+    // 报告的缓存处理数据
+    dataInit() {
+      if (sessionStorage.getItem("addRoadshowReportQY")) {
+        let data = JSON.parse(sessionStorage.getItem("addRoadshowReportQY"));
+        setTimeout(async () => {
+          this.listForm = {
+            title: data.Title, //标题
+            author: data.SellerAndMobile, //作者
+            time: data.PublishDate, //时间
+            industry: data.ChartPermissionId, //行业
+            abstract: data.Abstract,
+            reportLink: data.ReportLink,
+            property: data.IndustrialManagementId,
+            target: data.IndustrialSubjectIdStr,
+          };
+          this.$refs.twoRich.value = data.Body;
+          if (this.listForm.industry) {
+            await this.getPropertyList();
+            await this.getTargetList();
+          }
+        }, 200);
+      }
+      this.timeInterval = setInterval(() => {
+        let params = {
+          Abstract: this.listForm.abstract,
+          Body: this.$refs.twoRich.value,
+          ChartPermissionId: this.listForm.industry,
+          IndustrialManagementId: this.listForm.property,
+          IndustrialSubjectIdStr: this.listForm.target,
+          ReportLink: this.listForm.reportLink,
+          PublishDate: this.listForm.time,
+          SellerAndMobile: this.listForm.author,
+          Title: this.listForm.title,
+        };
+        sessionStorage.setItem("addRoadshowReportQY", JSON.stringify(params));
+      }, 120000);
+    },
+    // 获取数据
     async getDetail() {
       const res = await raiInterface.roadshowEssenceDetail({ ArticleId: Number(this.$route.query.id) });
       if (res.Ret === 200) {
-        this.isShowStatus=res.Data.PublishStatus==0
+        this.isShowStatus = res.Data.PublishStatus == 0;
         this.listForm = {
           title: res.Data.Title, //标题
           author: res.Data.SellerAndMobile, //作者
@@ -161,7 +202,7 @@ export default {
       }
     },
     //保存 / 发布
-    confirm(type) {
+    confirm: _.debounce(function (type) {
       this.$refs.ruleForm.validate(async (value) => {
         if (value) {
           let params = {
@@ -176,23 +217,24 @@ export default {
             Title: this.listForm.title,
             DoType: type == "发布" ? 1 : 0,
             ArticleId: this.$route.query.id ? Number(this.$route.query.id) : 0,
-          }
-          if(type == "预览"){
-            sessionStorage.setItem('roadShowPre', JSON.stringify(params));
-            let { href } = this.$router.resolve({ name: '预览路演精华' });
-            window.open(href, '_blank');
-          }else{
+          };
+          if (type == "预览") {
+            sessionStorage.setItem("roadShowPre", JSON.stringify(params));
+            let { href } = this.$router.resolve({ name: "预览路演精华" });
+            window.open(href, "_blank");
+          } else {
             const res = await raiInterface.roadshowEssencePreserveAndPublish(params);
             if (res.Ret === 200) {
               this.$message.success(`${type}成功!`);
               this.$refs.ruleForm.resetFields();
+              clearInterval(this.timeInterval);
+              sessionStorage.removeItem("addRoadshowReportQY");
               this.$router.back();
             }
           }
-
         }
       });
-    },
+    }, 500),
     industryClear() {
       this.listForm.property = [];
       this.optionsProperty = [];
@@ -205,10 +247,17 @@ export default {
     },
     //取消事件
     cancel() {
+      clearInterval(this.timeInterval);
+      sessionStorage.removeItem("addRoadshowReportQY");
       this.$refs.ruleForm.resetFields();
       this.$router.back();
     },
   },
+  // 路由离开了 清除定时器
+  beforeRouteLeave(to, from, next) {
+    clearInterval(this.timeInterval);
+    next();
+  },
 };
 </script>
 <style lang="scss">

+ 1 - 1
src/views/rai_manage/components/addSummarizing.vue

@@ -227,7 +227,7 @@ export default {
           }
         }
       });
-    }, 300),
+    }, 500),
     fnConFirm() {
       let flag = false;
       let isCydyjy = this.ListCydyjy.some((item) => item.List.length > 0);

+ 57 - 4
src/views/rai_manage/components/addSummary.vue

@@ -210,6 +210,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
       synopsisText: [], //
       articleTypeName: "", //报告类型的名称
       isSource: "",
+      numNum: 0,
+      timeInterval: null,
     };
   },
   computed: {},
@@ -223,9 +225,53 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
     if (this.$route.query.id) {
       // 编辑进来的
       this.getsummaryManagedetail();
+    } else {
+      this.dataInit();
     }
   },
   methods: {
+    // 报告的缓存处理数据
+    dataInit() {
+      if (sessionStorage.getItem(this.isSource == "HZ" ? "addSummaryParamsHZ" : "addSummaryParamsQY")) {
+        let data = JSON.parse(sessionStorage.getItem(this.isSource == "HZ" ? "addSummaryParamsHZ" : "addSummaryParamsQY"));
+        setTimeout(() => {
+          this.addOfEditForm = {
+            industry: data.ChartPermissionId, //HZ  行业
+            regions: data.ArticleTypeId,
+            title: data.Title,
+            content: data.Body,
+            synopsis: data.Abstract,
+            mobile: data.SellerAndMobile,
+            ImgUrl: data.ImgUrl,
+            nickName: data.NickName,
+            reportLink: data.ReportLink,
+            publishTime: data.PublishDate,
+            property: data.IndustrialManagementIds,
+          };
+          this.articleTypeName = data.ArticleTypeName;
+          this.markValue = data.IndustrialSubjectIds;
+          data.IndustrialManagementIds && this.markSelectFocus();
+        }, 200);
+      }
+      this.timeInterval = setInterval(() => {
+        let params = {
+          Abstract: this.addOfEditForm.synopsis,
+          Body: this.addOfEditForm.content,
+          SellerAndMobile: this.addOfEditForm.mobile,
+          NickName: this.addOfEditForm.nickName,
+          ImgUrl: this.addOfEditForm.ImgUrl,
+          Title: this.addOfEditForm.title,
+          ArticleTypeId: this.addOfEditForm.regions,
+          IndustrialSubjectIds: this.markValue,
+          IndustrialManagementIds: this.addOfEditForm.property, //产业
+          PublishDate: this.addOfEditForm.publishTime,
+          ReportLink: this.addOfEditForm.reportLink,
+          ChartPermissionId: this.addOfEditForm.industry,
+        };
+        sessionStorage.setItem(this.isSource == "HZ" ? "addSummaryParamsHZ" : "addSummaryParamsQY", JSON.stringify(params));
+        this.numNum++;
+      }, 120000);
+    },
     //点击了添加产业
     addIndustryDlgIsShow() {
       if (this.addOfEditForm.regions) {
@@ -239,7 +285,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
     regionsChange(e) {
       this.articleTypeName = this.chartPermissionList.find((item) => item.ArticleTypeId == e).ArticleTypeName;
       let str = this.synopsisText.find((item) => item.ArticleTypeId == e);
-      this.addOfEditForm.synopsis = str ? str.Abstract : "";
     },
     //进来编辑的 获取内容的事件
     async getsummaryManagedetail() {
@@ -270,7 +315,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
       this.markSelectFocus();
     },
     //表单保存发布事件
-    async submitForm(type) {
+    submitForm: _.debounce(async function (type) {
       let validateFieldList = [];
       this.$refs.addOfEditForm.validateField([this.isSource === "HZ" ? "industry" : "regions", "property", "publishTime", "title", "synopsis", "mobile"], (valid) => {
         validateFieldList.push(valid);
@@ -306,16 +351,20 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
         } else {
           const res = this.isSource === "HZ" ? await raiInterface.reportPreserveAndPublish(params) : await raiInterface.preserveAndPublish(params);
           if (res.Ret === 200) {
+            clearInterval(this.timeInterval);
             this.$message.success("操作成功!");
+            sessionStorage.removeItem(this.isSource == "HZ" ? "addSummaryParamsHZ" : "addSummaryParamsQY");
             this.$refs.addOfEditForm.resetFields();
             this.$router.back();
           }
         }
       }
-    },
+    }, 500),
     //表单取消事件
     cancelBtn() {
+      clearInterval(this.timeInterval);
       this.$refs.addOfEditForm.resetFields();
+      sessionStorage.removeItem(this.isSource == "HZ" ? "addSummaryParamsHZ" : "addSummaryParamsQY");
       this.$router.back();
     },
     //获取行业
@@ -388,7 +437,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
       }
     },
     propertyChange() {
-      console.log("change");
       this.markOptions = [];
       this.markValue = "";
     },
@@ -471,6 +519,11 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`,
       });
     },
   },
+  // 路由离开了 清除定时器
+  beforeRouteLeave(to, from, next) {
+    clearInterval(this.timeInterval);
+    next();
+  },
 };
 </script>
 <style lang="scss">

+ 1 - 1
src/views/rai_manage/components/addThisWeek.vue

@@ -335,7 +335,7 @@ export default {
           }
         }
       });
-    }, 300),
+    }, 500),
     fnConFirm() {
       let flag = false;
       let isSdbg = this.ListSdbg.some((item) => item.List.length > 0); //深度报告篇

+ 1 - 2
src/views/rai_manage/components/apply/applyDialog.vue

@@ -110,8 +110,7 @@ export default {
     isType() {
       if (this.selectionArr.length > 0) {
         return this.selectionArr.some(
-          (item) =>
-            (item.ActivityTypeName == "公司调研电话会" && item.LimitPeopleNum !== 0) || item.ActivityTypeName == "专家电话会" || item.ActivityTypeName == "分析师电话会" || item.IsYidongConduct == 1
+          (item) => item.ActivityTypeName == "公司调研电话会" || item.ActivityTypeName == "专家电话会" || item.ActivityTypeName == "分析师电话会" || item.IsYidongConduct == 1
         );
       }
     },

+ 1 - 0
src/views/rai_manage/components/reportComponents/RichTextMixins.js

@@ -3,6 +3,7 @@ export default {
     var that = this;
     return {
       froalaConfig: {
+        key: "BWC6D-16D3B2F3C2H1A6A7wdwgacxuB-33c1fB2twtfG3A7A6B6A3B3B2G3D2H2==",
         toolbarButtons: [
           "textColor",
           "bold",

+ 14 - 1
src/views/rai_manage/components/richText.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="richtext">
-    <froala :id="'editor' + spareId" :tag="'textarea'" :config="froalaConfig" v-model="value"></froala>
+    <froala :id="'editor' + spareId" :tag="'textarea'" :config="froalaConfig" v-model="valueText" @input="inputHandler"></froala>
   </div>
 </template>
 
@@ -9,6 +9,10 @@ import VueFroala from "vue-froala-wysiwyg";
 export default {
   name: "",
   components: {},
+  model: {
+    prop: "valueText",
+    event: "contentText",
+  },
   props: {
     spareId: {
       type: String,
@@ -19,6 +23,10 @@ export default {
       required: true,
       default: "",
     },
+    valueText: {
+      type: String,
+      required: true,
+    },
   },
   watch: {
     isText: {
@@ -105,6 +113,11 @@ export default {
       value: "",
     };
   },
+  methods: {
+    inputHandler() {
+      this.$emit("contentText", this.valueText);
+    },
+  },
 };
 </script>
 <style lang="scss">

+ 2 - 0
src/views/rai_manage/cygxManage/components/lableDlg.vue

@@ -57,6 +57,8 @@ export default {
           ? "所有路演回放音视频"
           : this.dataRegular.TagType == 4
           ? "所有问答系列音频"
+          : this.dataRegular.TagType == 5
+          ? "医药-趋势观察 ,科技-产业跟踪 ,智造-产业跟踪 ,消费-月度调研"
           : "";
       return str;
     },

+ 9 - 2
src/views/rai_manage/cygxManage/lableManage.vue

@@ -30,7 +30,7 @@
           <span v-if="index == 0" class="divide">|</span>
         </div>
       </div>
-      <el-table border :data="tableList">
+      <el-table border :data="tableList" @sort-change="sortChangeHandle">
         <el-table-column align="center" key="name" prop="TagName" label="标签名称" width=""></el-table-column>
         <el-table-column align="center" key="series" prop="ArticleTypes" label="报告类型" width=""></el-table-column>
         <el-table-column align="center" key="type" prop="ActivityTypes" label="活动类型" width=""></el-table-column>
@@ -38,7 +38,7 @@
         <el-table-column align="center" key="subject" prop="SubjectNames" label="相关标的" width=""></el-table-column>
         <el-table-column align="center" key="tiem" prop="OnlineTime" label="上线时间" width="180"></el-table-column>
         <el-table-column align="center" key="remove" prop="OfflineTime" label="撤下时间" width="180" v-if="tableSelectActive == 0"></el-table-column>
-        <el-table-column align="center" key="pvuv" prop="Sort" label="pv/uv" width="90">
+        <el-table-column align="center" key="pvuv" prop="Sort" label="pv/uv" width="90" sortable="custom">
           <template slot-scope="{ row }">
             <div class="pv-uv-download">
               <span>{{ row.Pv }}/{{ row.Uv }}</span>
@@ -169,6 +169,7 @@ export default {
       dlgTitle: "添加",
       showRegularDlg: false,
       dataRegular: {},
+      sortType: "",
     };
   },
   computed: {},
@@ -187,6 +188,8 @@ export default {
         Status: this.tableSelectActive,
         PageSize: this.pageSize,
         CurrentIndex: this.page_no,
+        SortParam: "pv",
+        SortType: this.sortType,
       });
       if (res.Ret === 200) {
         this.total = res.Data.Paging.Totals;
@@ -401,6 +404,10 @@ export default {
         this.optionsSubject = [];
       }
     },
+    sortChangeHandle(column) {
+      this.sortType = column.order == "descending" ? "desc" : column.order == "ascending" ? "asc" : "";
+      this.getDataList();
+    },
   },
 };
 </script>

Some files were not shown because too many files changed in this diff