predictEdb.vue 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846
  1. <template>
  2. <div class="predictEdb-container" >
  3. <span
  4. class="slide-icon slide-right"
  5. @click="isSlideLeft = !isSlideLeft"
  6. v-show="isSlideLeft"
  7. >
  8. <i class="el-icon-d-arrow-right"></i>
  9. </span>
  10. <div class="predict-edb-main" id="box">
  11. <div class="main-left left" id="left" v-show="!isSlideLeft">
  12. <div class="datasheet_top">
  13. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_addEdb"
  14. type="primary" @click="addEdbHandle">添加指标</el-button>
  15. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_calcuEdb"
  16. type="primary" @click="addComputedHandler" style="margin-right:10px;">计算指标</el-button>
  17. <change-lang v-permission="permissionBtn.predictEdbPermission.edbPreData_switchEn"
  18. :lang="currentLang" style="height: 32px;" @changeLang="changeLangHandle"/>
  19. </div>
  20. <div class="search-cont" v-loading="searchLoading">
  21. <el-select
  22. v-model="search_txt"
  23. ref="searchRef"
  24. :filterable="!search_txt"
  25. remote
  26. clearable
  27. placeholder="指标名称"
  28. style="width: 100%"
  29. :remote-method="searchHandle"
  30. @focus="searchHandle('')"
  31. >
  32. <i slot="prefix" class="el-input__icon el-icon-search"></i>
  33. <el-option
  34. v-for="item in searchOptions"
  35. :key="item.EdbInfoId"
  36. :label="currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
  37. :value="item.EdbInfoId"
  38. >
  39. <span>{{ currentLang==='en' ? (item.EdbNameEn||item.EdbName) : item.EdbName }}</span>
  40. </el-option>
  41. </el-select>
  42. </div>
  43. <div style="margin:20px 0;padding:0 20px;display:flex;justify-content:space-between">
  44. <span>目录</span>
  45. <el-checkbox v-model="isOnlyMe" v-permission="permissionBtn.predictEdbPermission.edbPreData_isOnlyMine"
  46. @change="onlyMeHandler">只看我的</el-checkbox>
  47. </div>
  48. <div class="tree-cont">
  49. <el-tree
  50. ref="treeRef"
  51. class="target_tree"
  52. :data="treeData"
  53. node-key="UniqueCode"
  54. :props="defaultProp"
  55. :allow-drag="canDragHandle"
  56. :allow-drop="canDropHandle"
  57. :current-node-key="select_node"
  58. :default-expanded-keys="defaultShowNodes"
  59. :draggable="isEdbBtnShow('edbPreData_classifyOpt_move')"
  60. :expand-on-click-node="false"
  61. check-strictly
  62. empty-text="暂无分类"
  63. lazy
  64. :load="getLazyTreeData"
  65. @node-expand="handleNodeExpand"
  66. @node-collapse="handleNodeCollapse"
  67. @current-change="nodeChange"
  68. @node-drop="dropOverHandle"
  69. @node-drag-end="dropMouseLeave"
  70. @node-drag-leave="dropMouseLeave"
  71. @node-drag-enter="dropMouseOver"
  72. @node-drag-over="dropMouseOver"
  73. >
  74. <span class="custom-tree-node" slot-scope="{ node, data }">
  75. <el-input
  76. ref="editVal"
  77. style="width: 90px"
  78. placeholder="请输入值"
  79. class="label-input"
  80. v-model="new_label"
  81. v-if="data.isEdit"
  82. @blur="changeValue(data)"
  83. />
  84. <span
  85. @dblclick.stop="editNodeLabel(data)"
  86. v-else
  87. class="text_oneLine node_label"
  88. :style="`width:${
  89. (select_node === data.UniqueCode && node.Nodewidth) || ''
  90. }`"
  91. :id="`node${data.UniqueCode}`"
  92. >
  93. <span>{{ currentLang==='en' ? (data.ClassifyNameEn||data.ClassifyName) : data.ClassifyName }}</span>
  94. </span>
  95. <span
  96. style="display: flex; align-items: center"
  97. v-if="select_node === data.UniqueCode"
  98. >
  99. <img
  100. src="~@/assets/img/data_m/move_ico.png"
  101. alt=""
  102. style="width: 14px; height: 14px; margin-right: 8px"
  103. v-if="data.Button.MoveButton"
  104. />
  105. <!-- 添加子项 -->
  106. <img
  107. src="~@/assets/img/set_m/add.png"
  108. alt=""
  109. style="width: 14px; height: 14px; margin-right: 8px"
  110. @click.stop="addNode(node, data)"
  111. v-if="data.Button.AddButton&&!data.EdbInfoId&&isEdbBtnShow('edbPreData_classifyOpt_add')&&node.level<6"
  112. />
  113. <!-- 编辑目录 -->
  114. <img
  115. src="~@/assets/img/set_m/edit.png"
  116. alt=""
  117. style="width: 15px; height: 14px; margin-right: 8px"
  118. @click.stop="editNode(node, data)"
  119. v-if="data.Button.OpButton&&!data.EdbInfoId&&isEdbBtnShow('edbPreData_classifyOpt_add')"
  120. />
  121. <!-- 删除目录 -->
  122. <img
  123. slot="reference"
  124. src="~@/assets/img/set_m/del.png"
  125. alt=""
  126. style="width: 14px; height: 14px"
  127. @click.stop="removeNode(node, data)"
  128. v-if="data.Button.DeleteButton&&!data.EdbInfoId&&isEdbBtnShow('edbPreData_classifyOpt_delete')"
  129. />
  130. <!-- 查看预测规则 -->
  131. <i class="el-icon-view" v-if="data.EdbInfoId&&isEdbBtnShow('edbPreData_checkPreRule')" @click.stop="viewNode(node,data)"></i>
  132. <!-- 查看关联图表 -->
  133. <img
  134. v-if="data.Button.ShowChartRelation&&isEdbBtnShow('edbPreData_checkRelatedChart')"
  135. @click.stop="showAssociateChart=true,showAssociateComputeData=false"
  136. src="~@/assets/img/icons/associate_chart.png"
  137. style="width: 14px; height: 14px;margin-left: 8px"
  138. alt=""
  139. />
  140. <!-- 查看关联指标 -->
  141. <img
  142. v-if="data.Button.ShowEdbRelation&&isEdbBtnShow('edbPreData_checkRelatedEdb')"
  143. @click.stop="showAssociateComputeData=true,showAssociateChart=false"
  144. src="~@/assets/img/icons/associate_data.png"
  145. style="width: 14px; height: 14px;margin-left: 8px"
  146. alt=""
  147. />
  148. </span>
  149. </span>
  150. </el-tree>
  151. <div
  152. class="noDepart"
  153. @click="addLevelOneHandle"
  154. v-if="opLevelOneClassify&&isEdbBtnShow('edbPreData_classifyOpt_add')"
  155. >
  156. <img
  157. src="~@/assets/img/set_m/add_ico.png"
  158. alt=""
  159. style="width: 16px; height: 16px; margin-right: 10px"
  160. />
  161. <span>添加一级目录</span>
  162. </div>
  163. </div>
  164. <span
  165. class="move-btn resize"
  166. v-drag
  167. id="resize"
  168. @mousemove="dynamicNode && resetNodeStyle(dynamicNode)"
  169. ></span>
  170. <span class="slide-icon slide-left" @click="isSlideLeft = !isSlideLeft">
  171. <i class="el-icon-d-arrow-left"></i>
  172. </span>
  173. </div>
  174. <div class="main-right" id="right" :style="isSlideLeft ? 'width:100%' : 'width:80%'"
  175. :class="{'detail-main':select_id&&!showAssociateChart&&!showAssociateComputeData}"
  176. >
  177. <!-- 详情 -->
  178. <div class="edb-detail-wrapper main-min-width" v-if="select_id&&!showAssociateChart&&!showAssociateComputeData">
  179. <div class="detail-header">
  180. <el-tabs v-model="activeTab" @tab-click="changeShowType">
  181. <el-tab-pane label="走势图" name="Chart">
  182. </el-tab-pane>
  183. <el-tab-pane label="数据详情" name="Data">
  184. </el-tab-pane>
  185. </el-tabs>
  186. <div class="edb-tool-icon edb-tool" style="align-items: center;">
  187. <el-popover
  188. placement="left"
  189. trigger="click"
  190. popper-class="edb-tool-popover"
  191. width="320" style="display: inline-block;">
  192. <div class="edb-tool-wrap">
  193. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_enNameSetting"
  194. type="text" @click="clickEdbNameHandle" v-if="currentLang==='ch'||!edb_nameEn">
  195. 设置英文名称
  196. </el-button>
  197. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
  198. type="text" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</el-button>
  199. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_update"
  200. type="text" @click="updateEdbPartHandle">刷新</el-button>
  201. <el-button type="text" @click="editEdbHandle('')"
  202. v-if="edbButton.OpButton&&isEdbBtnShow('edbPreData_edit')">编辑</el-button>
  203. <el-button type="text" @click="saveEdbHandle"
  204. v-if="detail_show_chart&&isEdbBtnShow('edbPreData_save')">保存</el-button>
  205. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_recalcu"
  206. type="text" @click="updateEdbHandle">重新计算</el-button>
  207. <el-button class="deletesty" @click="delEdbHandle" type="text"
  208. v-if="edbButton.DeleteButton&&isEdbBtnShow('edbPreData_del')">删除</el-button>
  209. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_copyData"
  210. type="text" @click="copyData">复制数据</el-button>
  211. </div>
  212. <div class="edb-btn" slot="reference">
  213. <el-button type="text">操作</el-button>
  214. <i class="el-icon-more" style="font-size: 14px;transform: rotate(90deg);cursor: pointer;color: #3375e1;"/>
  215. </div>
  216. </el-popover>
  217. </div>
  218. <!-- <div class="edb-tool">
  219. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_enNameSetting"
  220. type="text" @click="clickEdbNameHandle" v-if="currentLang==='ch'||!edb_nameEn">
  221. 设置英文名称
  222. </el-button>
  223. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_edbSource"
  224. type="text" @click="isLookHistory=true;lookEdbId=select_id">指标溯源</el-button>
  225. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_update"
  226. type="text" @click="updateEdbPartHandle">刷新</el-button>
  227. <el-button type="text" @click="editEdbHandle('')"
  228. v-if="edbButton.OpButton&&isEdbBtnShow('edbPreData_edit')">编辑</el-button>
  229. <el-button type="text" @click="saveEdbHandle"
  230. v-if="detail_show_chart&&isEdbBtnShow('edbPreData_save')">保存</el-button>
  231. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_recalcu"
  232. type="text" @click="updateEdbHandle">重新计算</el-button>
  233. <el-button class="deletesty" @click="delEdbHandle" type="text"
  234. v-if="edbButton.DeleteButton&&isEdbBtnShow('edbPreData_del')">删除</el-button>
  235. <el-button v-permission="permissionBtn.predictEdbPermission.edbPreData_copyData"
  236. type="text" @click="copyData">复制数据</el-button>
  237. </div> -->
  238. </div>
  239. <!-- -->
  240. <div class="detail-wrap">
  241. <component
  242. :is="detail_show_chart?'edbDetail':'childData'"
  243. :id="select_id"
  244. :lang="currentLang"
  245. :isAllowEditLimit="isEdbBtnShow('edbPreData_editLimit')"
  246. ref="detailComponentRef"
  247. @updateTit="setNameBack"
  248. @setCurrentClassify="setCurrentClassify"
  249. @setOpera="(obj) => { edbButton = obj }"
  250. @openEnNameDia="openEnNameDia"
  251. />
  252. </div>
  253. </div>
  254. <!-- 列表 -->
  255. <div class="sheet-list-cont" v-else-if="!select_id">
  256. <div class="list-top">
  257. <span>共{{ edb_total }}个预测指标</span>
  258. </div>
  259. <div
  260. class="edbChartList-wrapper"
  261. ref="listRef"
  262. @scroll="loadMoreHandle"
  263. >
  264. <div class="chart-list-item-wrap">
  265. <div class="sheet-item" v-for="item in edbChartList" :key="item.EdbInfoId">
  266. <div class="item-top">
  267. <span class="text_oneLine">{{ currentLang === 'en' ? (item.EdbNameEn||item.EdbName) : item.EdbName }}</span>
  268. </div>
  269. <div class="chart-img" @click="detailShowHandle(item)"
  270. :style="item.ChartImage?{background: `no-repeat top/cover url('${item.ChartImage}')`}:{}"></div>
  271. <div class="item-bottom">
  272. <span>创建时间: {{ item.CreateTime.slice(0,10) }}</span>
  273. </div>
  274. </div>
  275. </div>
  276. <!-- <el-col
  277. :span="8"
  278. style="margin-bottom: 20px; padding-right: 20px"
  279. v-for="item in edbChartList"
  280. :key="item.EdbInfoId"
  281. >
  282. <el-card class="sheet-item">
  283. <div slot="header" class="item-top">
  284. <span class="text_oneLine">{{ currentLang === 'en' ? (item.EdbNameEn||item.EdbName) : item.EdbName }}</span>
  285. </div>
  286. <img
  287. :src="item.ChartImage"
  288. alt=""
  289. class="chart-img"
  290. @click="detailShowHandle(item)"
  291. />
  292. <div class="item-bottom">
  293. <span>创建时间: {{ item.CreateTime.slice(0,10) }}</span>
  294. </div>
  295. </el-card>
  296. </el-col> -->
  297. </div>
  298. <div v-if="!edb_total" class="nodata">
  299. <tableNoData text="暂无指标"/>
  300. </div>
  301. </div>
  302. <!-- 指标关联图模块 -->
  303. <div class="edb-detail-wrapper" style="padding: 30px 20px;" v-if="showAssociateChart&&select_id">
  304. <dataAssociateChart :edbInfoId="select_id"></dataAssociateChart>
  305. </div>
  306. <div class="edb-detail-wrapper" style="padding: 30px 20px;" v-if="showAssociateComputeData&&select_id">
  307. <dataAssociateComputeData :edbInfoId="select_id"></dataAssociateComputeData>
  308. </div>
  309. </div>
  310. </div>
  311. <!-- 计算弹窗控制 -->
  312. <el-dialog
  313. :visible.sync="isOpenComputed"
  314. :close-on-click-modal="false"
  315. :modal-append-to-body='false'
  316. @close="isOpenComputed=false;"
  317. custom-class="dialog-computed"
  318. top="6vh"
  319. center
  320. width="85vw"
  321. v-dialogDrag>
  322. <div class="dialog-computed-header">
  323. <el-radio-group v-model="computed_source" size="medium" @change="computed_type = 0">
  324. <el-radio-button :label="1">常规计算</el-radio-button>
  325. <el-radio-button :label="2">批量计算</el-radio-button>
  326. </el-radio-group>
  327. </div>
  328. <ul class="computed-ul">
  329. <li
  330. :class="['cpmputed-li',{'act':item.type === computed_type}]"
  331. v-for="item in computedTypes"
  332. :key="item.type"
  333. @click="changeComputedType(item.type)"
  334. >
  335. {{item.name}}
  336. <el-popover
  337. placement="top-start"
  338. width="450"
  339. trigger="hover"
  340. v-if="tips.get(item.type)"
  341. >
  342. <p style="padding:20px;line-height:25px;" v-html="tips.get(item.type)"/>
  343. <i slot="reference" class="el-icon-warning-outline"/>
  344. </el-popover>
  345. </li>
  346. </ul>
  347. </el-dialog>
  348. <!-- 指标弹窗 -->
  349. <edb-dialog
  350. :isShow.sync="isEdbDia"
  351. :title="edbdia_title"
  352. :edbForm="edbForm"
  353. @successHandle="handleEdbCallBack"
  354. />
  355. <!-- 分类弹窗 -->
  356. <edbClassifyDia
  357. :isOpenDialog.sync="classifyDia"
  358. :title="dialog_title"
  359. :form="classifyForm"
  360. @successCallback="getTreeData"
  361. />
  362. <!-- 输入英文指标弹窗 -->
  363. <set-en-name-dia
  364. :isOpenDialog="setEnName"
  365. @cancel="setEnName=false"
  366. :formData="formItemArray"
  367. @updateEnName="updateEnName"
  368. cType="predictEbd"
  369. />
  370. <!-- 运算指标弹窗 -->
  371. <computedDialog
  372. :isOpenComputed="computed_type === 31"
  373. :title="computedTit"
  374. :calulateForm="calulateForm"
  375. :calulateList="calulateList"
  376. @cancel="computed_type=0"
  377. @addCallBack="addComputedCallBack"
  378. @openPrev="isOpenComputed=true"
  379. @lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
  380. />
  381. <!-- 同比同差计算弹窗 -->
  382. <!-- 转月值 同比 同差 平均值弹窗 -->
  383. <operationDialog
  384. :isOperation="[42,32,33,39,43,44,45,46,49,54,55,64,65,66,69,70].includes(computed_type) && computed_source===1"
  385. :type="computed_type"
  386. :operationForm="operationForm"
  387. @cancel="computed_type=0"
  388. @addCallBack="addComputedCallBack"
  389. @openPrev="isOpenComputed=true"
  390. @lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
  391. @changeSource="changeComputedType"
  392. />
  393. <!-- 规则详情弹窗 -->
  394. <rules-detail
  395. :isOpenDialog.sync="isShowRuleDialog"
  396. :rules="showRules"
  397. :fromEdbInfo="showFromEdbInfo"
  398. />
  399. <!-- 批量计算弹窗 -->
  400. <batchComputedDialog
  401. :isBatchComputed="[32,33,39,43,44,45,42,64,65,66].includes(computed_type) && computed_source===2"
  402. :type="computed_type"
  403. edbSource="predict"
  404. @cancel="computed_type=0"
  405. @addCallBack="addComputedCallBack"
  406. @openPrev="isOpenComputed=true"
  407. @lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
  408. @changeSource="changeComputedType"
  409. />
  410. <!-- 拼接弹窗 -->
  411. <joint-target-dia
  412. :isShow="computed_type === 'joint'"
  413. :params="operationForm"
  414. :isPredict="true"
  415. @cancel="computed_type=0"
  416. @addCallBack="addComputedCallBack"
  417. @openPrev="isOpenComputed=true"
  418. />
  419. <!-- 拟合残差弹窗 -->
  420. <fittingResidueDia
  421. :isShow="computed_type === 50"
  422. :type="50"
  423. :operationForm="operationForm"
  424. :isPredict="true"
  425. @cancel="computed_type=0"
  426. @addCallBack="addComputedCallBack"
  427. @openPrev="isOpenComputed=true"
  428. />
  429. <!-- 扩散指数弹窗 -->
  430. <diffusionIndexDialog
  431. :isShow="computed_type === 56 && computed_source===1"
  432. :type="computed_type"
  433. :isPredict="true"
  434. :operationForm="operationForm"
  435. @cancel="computed_type=0"
  436. @addCallBack="addComputedCallBack"
  437. @openPrev="isOpenComputed=true"
  438. />
  439. <!-- 指标历史记录 -->
  440. <edbHistoryDialog
  441. :isOpenDialog.sync="isLookHistory"
  442. :edbId="lookEdbId"
  443. />
  444. <!-- 指数修匀弹窗 -->
  445. <SmoothEdbDialog
  446. :is-open-smooth="computed_type==='alpha'"
  447. :computed-source="computed_source"
  448. :operationForm="operationForm"
  449. :isPredict="true"
  450. @cancel="computed_type=0"
  451. @openPrev="isOpenComputed=true"
  452. @addCallBack="addComputedCallBack"
  453. @lookHistory="id => {isLookHistory=true;lookEdbId=id;}"
  454. />
  455. </div>
  456. </template>
  457. <script>
  458. import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
  459. import { dataBaseInterface } from '@/api/api.js';
  460. import leftMixin from './mixins/mixin';
  461. import edbDialog from './components/edbDia.vue'
  462. import childChart from './components/childChart.vue'
  463. import childData from './components/childData.vue'
  464. import edbDetail from './components/edbDetail.vue'
  465. import edbClassifyDia from './components/classifyDia.vue'
  466. import changeLang from "@/views/dataEntry_manage/components/changeLang.vue"
  467. import setEnNameDia from "@/views/dataEntry_manage/components/setEnNameDia.vue"
  468. import computedDialog from './components/computedDialog';
  469. import operationDialog from './components/operationDialog';
  470. import rulesDetail from './components/rulesDetailDia.vue'
  471. import batchComputedDialog from '@/views/dataEntry_manage/databaseComponents/batchComptedDialog.vue';
  472. import jointTargetDia from '@/views/dataEntry_manage/databaseComponents/jointTargetDia'
  473. import fittingResidueDia from '@/views/dataEntry_manage/databaseComponents/fittingResidueDia.vue';
  474. import diffusionIndexDialog from '@/views/dataEntry_manage/databaseComponents/diffusionIndexDia.vue';
  475. import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
  476. import dataAssociateChart from '@/views/dataEntry_manage/databaseComponents/dataAssociateChart.vue'
  477. import dataAssociateComputeData from '@/views/dataEntry_manage/databaseComponents/dataAssociateComputeData.vue'
  478. import SmoothEdbDialog from '@/views/dataEntry_manage/databaseComponents/smoothEdbDialog.vue';
  479. export default {
  480. name:'',
  481. components: {
  482. edbDialog,
  483. childChart,
  484. childData,
  485. edbClassifyDia,
  486. changeLang,
  487. setEnNameDia,
  488. computedDialog,
  489. operationDialog,
  490. edbDetail,
  491. rulesDetail,
  492. jointTargetDia,
  493. fittingResidueDia,
  494. batchComputedDialog,
  495. diffusionIndexDialog,
  496. dataAssociateChart,
  497. dataAssociateComputeData,
  498. SmoothEdbDialog
  499. },
  500. mixins:[ leftMixin ],
  501. beforeRouteLeave (to, from, next) {
  502. // 前去编辑则存一次选择的节点
  503. if(to.path=='/editpredictEdb'){
  504. const obj={
  505. code:this.select_node,
  506. id:this.select_id
  507. }
  508. sessionStorage.setItem('predictEdbTreeData',JSON.stringify(obj))
  509. }else{
  510. sessionStorage.setItem('predictEdbTreeData','')
  511. }
  512. next()
  513. },
  514. data () {
  515. return {
  516. showData: false,
  517. search_txt: '',
  518. searchOptions:[],
  519. isSlideLeft: false,//左侧分类收起
  520. select_node: '',//节点唯一标识code
  521. select_classify: '',
  522. new_label:'',//双击修改的value
  523. treeData: [], //分类数据
  524. defaultShowNodes: [], //展开节点
  525. defaultProp: {
  526. label: 'ClassifyName',
  527. children: 'Children',
  528. isLeaf:'isLeaf'
  529. }, //树结构配置项
  530. dynamicNode: null,
  531. edbName: '',
  532. edb_nameEn: '',
  533. edbUserId: '',
  534. /* 分类弹窗 */
  535. dialog_title:'',
  536. classifyDia: false, //
  537. classifyForm: {},
  538. /* 添加指标弹窗 */
  539. isEdbDia: false,
  540. edbdia_title:'',
  541. edbForm: {},
  542. select_id: '',//选中的id
  543. sheetDetailInfo: {},
  544. detail_show_chart: true,//详情展示方式 chart data
  545. /* 列表 */
  546. publicHaveMove: true,//是否还有列表数据
  547. edbChartList: [],
  548. edb_total: 0,
  549. public_page: 1,
  550. public_pages_size: 16,
  551. currentLang:'ch', // ch(中文) en(英文)
  552. setEnName:false,
  553. // 传入的formItem所需内容
  554. formItemArray:[],
  555. /* 计算指标弹窗 */
  556. isOpenComputed:false,
  557. computedTit:'',
  558. calulateForm:{},
  559. operationForm:{},
  560. calulateList:[],
  561. computed_type:0,//打开弹窗的类型
  562. tips: new Map([
  563. [31,formulaTip.get(4)],
  564. [42,formulaTip.get(5)],
  565. [32,formulaTip.get(6)],
  566. [33,formulaTip.get(7)],
  567. [39,formulaTip.get(8)],
  568. [43,formulaTip.get(12)],
  569. [44,formulaTip.get(13)],
  570. [45,formulaTip.get(14)],
  571. ['joint',formulaTip.get('joint')],
  572. [46,formulaTip.get(22)],
  573. [49,formulaTip.get(35)],
  574. [50,formulaTip.get(37)],
  575. [54,formulaTip.get(51)],
  576. [55,formulaTip.get(52)],
  577. [56,formulaTip.get(53)],
  578. ['toMonthSeason',formulaTip.get('toMonthSeason')],
  579. ['accumulate',formulaTip.get('accumulate')],
  580. [64,formulaTip.get(61)],
  581. [65,formulaTip.get(62)],
  582. [66,formulaTip.get(63)],
  583. ['alpha',formulaTip.get('alpha')]
  584. ]),//公式说明
  585. isShowRuleDialog: false,
  586. showRules: [],
  587. showFromEdbInfo: {},
  588. edbButton: {},//详情操作
  589. opLevelOneClassify: false,//一级分类按钮
  590. computed_source: 1,//计算类型 1常规 2批量
  591. isBatchComputed: false,//批量计算弹窗
  592. baseTypes: [
  593. { name: '指标运算',type: 31 },
  594. { name: '同比值',type: 32 },
  595. { name: '同差值',type: 33 },
  596. { name: 'N数值移动平均计算',type: 39 },
  597. { name: '累计值转月/季值',type: 'toMonthSeason' },
  598. { name: 'N数值环比值',type: 43 },
  599. { name: 'N数值环差值',type: 44 },
  600. { name: '升频',type: 45 },
  601. // { name: '指标拼接',type: 'joint' },
  602. { name: '时间移位',type: 46 },
  603. { name: '超季节性',type: 49 },
  604. { name: '拟合残差',type: 50 },
  605. { name: '年化',type: 55 },
  606. { name: '降频',type: 54 },
  607. { name: '扩散指数',type: 56 },
  608. { name: '累计值',type: 'accumulate' },
  609. { name: '指数修匀',type:'alpha'}
  610. ],
  611. batchTypes: [
  612. { name: '同比值',type: 32 },
  613. { name: '同差值',type: 33 },
  614. { name: 'N数值移动平均计算',type: 39 },
  615. { name: 'N数值环比值',type: 43 },
  616. { name: 'N数值环差值',type: 44 },
  617. { name: '升频',type: 45 },
  618. { name: '累计值转月/季值',type: 'toMonthSeason' },
  619. { name: '累计值',type: 'accumulate' },
  620. { name: '指数修匀',type:'alpha'}
  621. ],
  622. isOnlyMe:false,//只看我的
  623. /* 查看历史弹窗 */
  624. isLookHistory: false,
  625. lookEdbId: 0,
  626. searchLoading:false,
  627. showAssociateChart:false,//显示指标关联的图
  628. showAssociateComputeData:false,//显示指标关联的引用计算指标
  629. activeTab:'',
  630. };
  631. },
  632. computed: {
  633. computedTypes() {
  634. return this.computed_source === 1 ? this.baseTypes : this.batchTypes;
  635. },
  636. role() {
  637. let role = localStorage.getItem('Role') || '';
  638. if(['rai_admin','ficc_admin'].includes(role)) {
  639. return 'admin'
  640. }
  641. else {
  642. return role;
  643. }
  644. },
  645. /* 登录角色id */
  646. roleId() {
  647. let id = parseInt(localStorage.getItem('AdminId'));
  648. return id;
  649. },
  650. },
  651. watch: {
  652. /* 设置动态右侧区域宽度 */
  653. isSlideLeft(newval) {
  654. if (!newval) {
  655. this.$nextTick(() => {
  656. this.reloadRightWid();
  657. });
  658. }
  659. },
  660. // /* 表格id */
  661. select_id(newval) {
  662. this.detail_show_chart = true;
  663. this.activeTab='Chart'
  664. this.$nextTick(()=>{
  665. //切换为曲线图 重置选择状态
  666. if(this.$refs.detailComponentRef){
  667. this.$refs.detailComponentRef.$refs.chartInfo.chartInfo.ChartType=1;
  668. this.$refs.detailComponentRef.$refs.chartInfo.year_select=10;
  669. this.$refs.detailComponentRef.$refs.chartInfo.year_select_season=20;
  670. this.$refs.detailComponentRef.$refs.chartInfo.calendar_type='公历';
  671. this.$refs.detailComponentRef.$refs.chartInfo.count_year=5;
  672. this.$refs.detailComponentRef.$refs.chartInfo.count_year_season=5;
  673. this.$refs.detailComponentRef.$refs.chartInfo.select_date=[];
  674. this.$refs.detailComponentRef.$refs.chartInfo.season_year=[];
  675. this.$refs.detailComponentRef.$refs.chartInfo.dateTip='请选择时间段';
  676. }
  677. })
  678. },
  679. select_classify(newval) {
  680. if(this.$refs.listRef) this.$refs.listRef.scrollTop = 0;
  681. if(newval) {
  682. this.activeTab = ''
  683. this.public_page = 1;
  684. this.getPublicList()
  685. }
  686. },
  687. /* 搜索关键词 */
  688. search_txt(newval) {
  689. if(newval) {
  690. let search_obj = this.searchOptions.find(_ => _.EdbInfoId === newval);
  691. // let deep_arr = _.cloneDeep(this.treeData);
  692. // 查找图表的分类父级id
  693. // let arr = this.findParentNodeHandle(deep_arr, search_obj.ClassifyId).reverse(); // 父的父的父-父的父-父
  694. // this.defaultShowNodes = arr;
  695. this.select_node = search_obj.UniqueCode;
  696. this.$refs.treeRef.setCurrentKey(this.select_node);
  697. // 重置筛选状态
  698. this.select_id = newval;
  699. }
  700. }
  701. },
  702. methods: {
  703. isEdbBtnShow(type){
  704. const {predictEdbPermission,checkPermissionBtn}=this.permissionBtn
  705. return checkPermissionBtn(predictEdbPermission[type])||false
  706. },
  707. setCurrentClassify(ClassifyList){
  708. //获取指标详情后才能拿到准确的classifyId
  709. //根据准备的id查找指标的父级目录并展开
  710. console.log(ClassifyList);
  711. // 展开目录
  712. this.defaultShowNodes=ClassifyList.reverse().map(item=>item.UniqueCode)
  713. //滚动到高亮节点位置
  714. // this.$nextTick(()=>{
  715. setTimeout(() => {
  716. const dom = document.getElementById(`node${this.select_node}`)||{}
  717. const parentDom = document.getElementsByClassName('target_tree')[0];
  718. /* if (dom.offsetTop > parentDom.offsetHeight) {
  719. parentDom.scrollTo({
  720. top: dom.offsetTop - parentDom.offsetHeight / 2,
  721. left: 0,
  722. behavior: "smooth",
  723. });
  724. } */
  725. //parent可视区间:[scrollTop,scrollTop+offsetHeight]
  726. //node位置:node.offsetTop
  727. const overTop = dom.offsetTop+dom.clientHeight<parentDom.scrollTop
  728. const overBottom = dom.offsetTop+dom.clientHeight+30>parentDom.scrollTop+parentDom.offsetHeight
  729. if(overTop){
  730. parentDom.scrollTop = dom.offsetTop-30
  731. }
  732. if(overBottom){
  733. parentDom.scrollTop = dom.offsetTop - parentDom.offsetHeight/2
  734. }
  735. this.searchLoading = false;
  736. }, 1500);
  737. setTimeout(() => {
  738. this.$refs.treeRef.setCurrentKey(this.select_node);//设置高亮
  739. }, 1500);
  740. // })
  741. },
  742. setNameBack({edb_name,edb_nameEn,userid}) {
  743. this.edbName=edb_name;
  744. this.edb_nameEn= edb_nameEn;
  745. this.edbUserId=userid;
  746. },
  747. /* 添加指标 */
  748. addEdbHandle() {
  749. if(!this.treeData.length) return this.$message.warning('请先添加预测指标分类');
  750. this.$router.push({
  751. path:'/addpredictEdb'
  752. })
  753. },
  754. /* 获取分类 */
  755. getTreeData(params=null) {
  756. preDictEdbInterface.predictEdbCatalog({IsOnlyMe:this.isOnlyMe||false,ParentId:0}).then(res => {
  757. const { Ret,Data } = res;
  758. if(Ret !== 200) return
  759. this.treeData = Data.AllNodes || [];
  760. this.opLevelOneClassify = Data.CanOpClassify;
  761. this.currentLang = Data.Language === 'EN' ? 'en' : 'ch';
  762. this.showData = true;
  763. this.$nextTick(() => {
  764. /* 新增完成后 处理树展开和选中 */
  765. params && this.selectCurrentNode(params);
  766. });
  767. })
  768. },
  769. /* 搜索 */
  770. searchHandle(query) {
  771. if (query) {
  772. /* 查找列表 */
  773. preDictEdbInterface
  774. .edbSearch({
  775. Keyword: query,
  776. CurrentIndex: 1,
  777. PageSize: 10000,
  778. IsOnlyMe:this.isOnlyMe||false
  779. })
  780. .then((res) => {
  781. if (res.Ret !== 200) return
  782. this.searchOptions = res.Data.List || [];
  783. });
  784. } else {
  785. this.searchOptions = [];
  786. }
  787. },
  788. /* 选中分类变化时 */
  789. nodeChange({ UniqueCode,EdbInfoId,ClassifyId },node) {
  790. this.search_txt = '';
  791. this.select_node = UniqueCode;
  792. this.select_id = EdbInfoId || 0;
  793. this.select_classify = !EdbInfoId ? ClassifyId : 0;
  794. this.resetNodeStyle(node);
  795. this.dynamicNode = node;
  796. this.showAssociateChart=false
  797. this.showAssociateComputeData=false
  798. },
  799. async saveEdbHandle() {
  800. const {Ret} = await preDictEdbInterface.saveChartInfo({
  801. EdbInfoId: this.select_id,
  802. MaxValue: Number(this.$refs.detailComponentRef.$refs.chartInfo.tableData[0].MaxData),
  803. MinValue: Number(this.$refs.detailComponentRef.$refs.chartInfo.tableData[0].MinData)
  804. })
  805. if(Ret !== 200) return
  806. this.$message.success('保存成功')
  807. this.setChartImage()
  808. },
  809. /* 关联图片 */
  810. setChartImage() {
  811. let svg = this.$refs.detailComponentRef.$refs.chartInfo.$refs.chartRef.chart.getSVG({
  812. chart: {
  813. width: 340,
  814. height: 230,
  815. },
  816. });
  817. let form = new FormData();
  818. form.append("Img", svg);
  819. this.setImageHandle(form);
  820. },
  821. async setImageHandle(form) {
  822. let { Data } = await dataBaseInterface.uploadImgSvg(form);
  823. await preDictEdbInterface.setImg({
  824. EdbInfoId: this.select_id,
  825. ImageUrl: Data.ResourceUrl,
  826. });
  827. },
  828. /* 添加一级目录 */
  829. addLevelOneHandle() {
  830. this.dialog_title = '添加';
  831. this.classifyForm = {
  832. classify_name: '',
  833. Level:0,
  834. ParentId:0
  835. }
  836. this.classifyDia = true;
  837. },
  838. // 递归节点
  839. getNodeParentData(data,arr){
  840. if(data.level===0) return
  841. arr.push({classifyName:data.data.ClassifyName,classifyId:data.data.ClassifyId})
  842. this.getNodeParentData(data.parent,arr)
  843. return arr
  844. },
  845. addNode(node,{ClassifyName,ClassifyId}){
  846. this.dialog_title = '添加'
  847. let arr=[]
  848. arr=this.getNodeParentData(node,arr)
  849. /* 添加目录 */
  850. this.classifyForm = {
  851. classify_name:'',
  852. Level:node.level,
  853. ParentId:ClassifyId,
  854. parentArr:arr,
  855. }
  856. this.classifyDia = true;
  857. },
  858. /* 编辑节点 */
  859. editNode(node, { ClassifyName,ClassifyId,Level,ParentId}) {
  860. this.dialog_title = '编辑';
  861. let arr=[]
  862. arr=this.getNodeParentData(node.parent,arr)
  863. /* 编辑目录 */
  864. this.classifyForm = {
  865. classify_name: ClassifyName,
  866. classify_id: ClassifyId,
  867. Level:node.level-1,
  868. ParentId:ParentId,
  869. parentArr:arr,
  870. };
  871. this.classifyDia = true;
  872. },
  873. /* 删除节点校验 */
  874. async removeNode(node, { ClassifyId,EdbInfoId }) {
  875. const { Data } = await preDictEdbInterface.classifyDelCheck({ ClassifyId,EdbInfoId })
  876. const { DeleteStatus,TipsMsg } = Data;
  877. // DeleteStatus === 1
  878. // ? this.$confirm('该分类下关联指标不可删除', '删除失败', {
  879. // confirmButtonText: '知道了',
  880. // showCancelButton: false,
  881. // type: 'error',
  882. // }) : DeleteStatus === 0 && !EdbInfoId
  883. // ? this.$confirm('确定删除当前分类吗?', '提示', {
  884. // confirmButtonText: '确定',
  885. // cancelButtonText: '取消',
  886. // type: 'warning',
  887. // }).then(() => {
  888. // this.delApi(ClassifyId, EdbInfoId)
  889. // }): null;
  890. /**
  891. * 0 可删除
  892. * 1 关联指标
  893. * 2 有子目录无指标
  894. */
  895. const deleteLabelMap = {
  896. 1: '该目录关联指标不可删除',
  897. 2: '确认删除当前目录及包含的子目录吗?',
  898. 3: '当前指标已用作画图,不可删除',
  899. 4: TipsMsg
  900. }
  901. if([1,3,4].includes(DeleteStatus)) this.$confirm(
  902. deleteLabelMap[DeleteStatus],
  903. '删除失败',
  904. {
  905. confirmButtonText: '知道了',
  906. showCancelButton:false,
  907. type: 'error'
  908. })
  909. else if([0,2].includes(DeleteStatus)) this.$confirm(
  910. DeleteStatus === 2
  911. ? deleteLabelMap[DeleteStatus]
  912. : EdbInfoId?'删除后指标和指标值均不可使用,确认删除吗?':'确定删除当前目录吗?',
  913. '提示',
  914. {
  915. confirmButtonText: '确定',
  916. cancelButtonText: '取消',
  917. type: 'warning'
  918. }).then(() => {
  919. this.delApi(ClassifyId, EdbInfoId)
  920. }).catch(() => {
  921. });
  922. },
  923. /* 删除方法 */
  924. delApi(ClassifyId, EdbInfoId, type='') {
  925. preDictEdbInterface
  926. .classifyDel({
  927. ClassifyId,
  928. EdbInfoId,
  929. })
  930. .then((res) => {
  931. if (res.Ret !== 200) return
  932. this.$message.success(res.Msg);
  933. if (!res.Data.EdbInfoId || !res.Data) this.select_id = '';
  934. //删除表格后自动显示下一张表格
  935. type && res.Data.EdbInfoId
  936. ? this.getTreeData({
  937. code: res.Data.UniqueCode,
  938. id: res.Data.EdbInfoId,
  939. classifyId:res.Data.ClassifyId
  940. })
  941. : this.getTreeData();
  942. });
  943. },
  944. /* 删除指标 */
  945. delEdbHandle() {
  946. this.$confirm('ETA预测指标删除后不可恢复,确认删除吗?', '提示', {
  947. confirmButtonText: '确定',
  948. cancelButtonText: '取消',
  949. type: 'warning',
  950. })
  951. .then(() => {
  952. this.delApi(
  953. this.select_classify || 0,
  954. this.select_id,
  955. 'del-edb'
  956. );
  957. })
  958. .catch(() => {});
  959. },
  960. /* 分类成功回调 */
  961. classifyCallback(type) {
  962. this.getTreeData();
  963. if (type === 'add') {
  964. //新增分类完成之后,展开父节点显示刚新增的分类,若已展开节点则不做处理
  965. let code = this.add_parent_id;
  966. let flag = this.defaultShowNodes.some(item => item === code);
  967. !flag && this.defaultShowNodes.push(code);
  968. this.add_parent_id = '';
  969. }
  970. },
  971. /* 展开对应菜单 显示详情 */
  972. detailShowHandle({ UniqueCode, EdbInfoId,ClassifyId}) {
  973. let params = {
  974. code: UniqueCode,
  975. id: EdbInfoId,
  976. classifyId:ClassifyId
  977. };
  978. this.selectCurrentNode(params);
  979. this.select_classify = 0;
  980. },
  981. /* 操作指标后 */
  982. handleEdbCallBack(param) {
  983. this.getTreeData(param)
  984. //编辑后刷数据
  985. if(!param) {
  986. console.log('编辑后刷数据');
  987. this.detail_show_chart ? this.$refs.detailComponentRef.getDetail('updateImg') : this.$refs.detailComponentRef.getData();
  988. }
  989. },
  990. /* 更新指标 */
  991. updateEdbHandle: _.debounce(function() {
  992. this.loading = this.$loading({
  993. lock: true,
  994. target:'.edb-detail-wrapper',
  995. text: '刷新数据中...',
  996. spinner: 'el-icon-loading',
  997. background: 'rgba(255, 255, 255, 0.8)'
  998. });
  999. preDictEdbInterface.edbRefresh({
  1000. EdbInfoId: this.select_id
  1001. }).then(res => {
  1002. this.loading.close();
  1003. if(res.Ret !== 200) return
  1004. this.$message.success(res.Msg)
  1005. //更新完刷数据
  1006. console.log('更新完刷数据');
  1007. this.detail_show_chart ? this.$refs.detailComponentRef.getDetail('updateImg') : this.$refs.detailComponentRef.getData();
  1008. })
  1009. },300),
  1010. /* 部分刷新 */
  1011. updateEdbPartHandle: _.debounce(function() {
  1012. this.loading = this.$loading({
  1013. lock: true,
  1014. target:'.edb-detail-wrapper',
  1015. text: '刷新数据中...',
  1016. spinner: 'el-icon-loading',
  1017. background: 'rgba(255, 255, 255, 0.8)'
  1018. });
  1019. preDictEdbInterface.edbPartRefresh({
  1020. EdbInfoId: this.select_id
  1021. }).then(res => {
  1022. this.loading.close();
  1023. if(res.Ret !== 200) return
  1024. this.$message.success(res.Msg)
  1025. //更新完刷数据
  1026. console.log('更新完刷数据');
  1027. this.detail_show_chart ? this.$refs.detailComponentRef.getDetail('updateImg') : this.$refs.detailComponentRef.getData();
  1028. })
  1029. },300),
  1030. /* 编辑指标 */
  1031. editEdbHandle(type="") {
  1032. preDictEdbInterface.edbDetail({
  1033. EdbInfoId: this.select_id
  1034. }).then(res => {
  1035. if(res.Ret !== 200) return
  1036. const { RuleList,EdbType,Source,CalculateList } = res.Data;
  1037. // 原始指标
  1038. if(EdbType === 1) {
  1039. !type && this.$router.push({
  1040. path:'/editpredictEdb',
  1041. query:{
  1042. id:this.select_id
  1043. }
  1044. })
  1045. if(type === 'view') {
  1046. this.showRules = RuleList;
  1047. this.showFromEdbInfo = CalculateList[0];
  1048. this.isShowRuleDialog=true};
  1049. } else {
  1050. //计算指标
  1051. this.setComputedDialogForm(res.Data,type);
  1052. this.computed_type =[47,48].includes(Source)?'joint': Source;
  1053. this.computed_type = [72,73].includes(Source)? 'alpha': Source;
  1054. }
  1055. })
  1056. },
  1057. /* 查看指标 */
  1058. viewNode() {
  1059. this.editEdbHandle('view')
  1060. },
  1061. /* 计算指标回显 */
  1062. setComputedDialogForm({Source,CalculateList,CalculateFormula,EdbInfoId,EdbName,Unit,Frequency,ClassifyId,ClassifyList,MoveType,MoveFrequency,Calendar,CorrelationStr},type='') {
  1063. //找到指标的父级
  1064. const parentNodes = ClassifyList.length&&ClassifyList.map(item=>item.ClassifyId)
  1065. //指标运算 or 其他计算类型指标
  1066. if( Source === 31 ) {
  1067. /* 回显指标和表单 */
  1068. this.computedTit = '编辑计算指标';
  1069. /* 依赖的指标列表 */
  1070. this.calulateList = CalculateList.map(item => ({
  1071. tag: item.FromTag,
  1072. edb_name: item.FromEdbName,
  1073. target: item.FromEdbInfoId,
  1074. start_date: item.StartDate,
  1075. end_date: item.EndDate
  1076. }))
  1077. /* 公式和表单 */
  1078. this.calulateForm = {
  1079. edb_id:EdbInfoId,
  1080. formula: CalculateFormula,
  1081. menu: parentNodes,
  1082. targetName: EdbName,
  1083. unit: Unit,
  1084. frequency: Frequency,
  1085. view: type === 'view'
  1086. };
  1087. } else {
  1088. if([47,48,50,56].includes(Source)){//拟合残差
  1089. this.operationForm={
  1090. edb_id:EdbInfoId,
  1091. targetName: EdbName,
  1092. frequency: Frequency,
  1093. unit: Unit,
  1094. menu: parentNodes,
  1095. view: type === 'view',
  1096. source: Source,
  1097. date: CalculateFormula,
  1098. pre_edb: Source === 47 ? CalculateList.find(item => item.FromTag === 'A').FromEdbInfoId : '', //俺也不懂为什么这么定义都是江西老表的锅
  1099. after_edb: Source === 47 ? CalculateList.find(item => item.FromTag === 'B').FromEdbInfoId : '',
  1100. old_stay_edb: Source === 48 ? CalculateList.find(item => item.FromTag === 'A').FromEdbInfoId : '',
  1101. concat_edb: Source === 48 ? CalculateList.find(item => item.FromTag === 'B').FromEdbInfoId : '',
  1102. from_arr: CalculateList,
  1103. correlationStr: CorrelationStr
  1104. }
  1105. return
  1106. }
  1107. this.operationForm = {
  1108. oldedb_id: CalculateList[0].FromEdbInfoId,
  1109. oldEdb_name: CalculateList[0].FromEdbName,
  1110. edb_id: EdbInfoId,
  1111. targetName: EdbName,
  1112. unit: Unit,
  1113. menu: parentNodes.reverse(),
  1114. frequency: Frequency,
  1115. formula: CalculateFormula || '',
  1116. view: type === 'view',
  1117. moveType: MoveType,
  1118. moveUnit: MoveFrequency,
  1119. moveVal: Source === 46 ? CalculateFormula : '',
  1120. calendar_type: Source === 49 ? Calendar : '',
  1121. }
  1122. if([72,73].includes(Source)){
  1123. this.operationForm = {
  1124. edb_id: EdbInfoId,
  1125. oldedb_id: CalculateList[0].FromEdbInfoId,
  1126. oldEdb_name: CalculateList[0].FromEdbName,
  1127. EdbName,Frequency,Unit,ClassifyId,Formula:CalculateFormula,
  1128. view: type === 'view'
  1129. }
  1130. }
  1131. }
  1132. },
  1133. /* 复制数据 */
  1134. copyData() {
  1135. preDictEdbInterface.edbDataInfo({
  1136. EdbInfoId: this.select_id,
  1137. CurrentIndex: 1,
  1138. PageSize: 100000,
  1139. }).then(res => {
  1140. if(res.Ret !== 200) return
  1141. const { DataList,PredictDataList } = res.Data.Item;
  1142. let total_data = [...PredictDataList,...DataList];
  1143. let str = '日期\t 值\n';
  1144. total_data.forEach((item) => (str += `${item.DataTime}\t${item.Value}\n`));
  1145. this.$copyText(str).then(
  1146. (res) => {
  1147. this.$message.success('已成功复制!');
  1148. },
  1149. (err) => {
  1150. this.$message.error('复制失败!');
  1151. }
  1152. );
  1153. })
  1154. },
  1155. /* 获取表格列表 */
  1156. getPublicList() {
  1157. preDictEdbInterface.edbList({
  1158. CurrentIndex: this.public_page,
  1159. PageSize: this.public_pages_size,
  1160. ClassifyId: this.select_classify || 0,
  1161. IsOnlyMe:this.isOnlyMe||false,
  1162. }).then(res => {
  1163. if(res.Ret !== 200) return
  1164. this.publicHaveMove = res.Data
  1165. ? this.public_page < res.Data.Paging.Pages
  1166. : false;
  1167. this.edbChartList = res.Data
  1168. ? this.public_page === 1
  1169. ? res.Data.List
  1170. : [...this.edbChartList, ...res.Data.List]
  1171. : [];
  1172. this.edb_total = res.Data ? res.Data.Paging.Totals : 0;
  1173. })
  1174. },
  1175. /* 加载更多 */
  1176. loadMoreHandle: _.throttle(function() {
  1177. let scrollTop = this.$refs.listRef.scrollTop;
  1178. let clientHeight = this.$refs.listRef.clientHeight;
  1179. let scrollHeight = this.$refs.listRef.scrollHeight;
  1180. if(scrollTop + clientHeight >= scrollHeight-10 && this.publicHaveMove){
  1181. this.public_page++;
  1182. this.getPublicList();
  1183. }
  1184. },300),
  1185. /* 切换中英文 */
  1186. changeLangHandle: _.debounce(async function (lang){
  1187. this.search_txt = '';
  1188. this.currentLang = lang;
  1189. await dataBaseInterface.setUserLang({
  1190. ConfigCode: 'predict_edb_language',
  1191. ConfigValue: lang === 'en' ? 'EN' : 'CN'
  1192. })
  1193. },200),
  1194. /* 编辑英文 */
  1195. openEnNameDia(info){
  1196. this.formItemArray=[{
  1197. label:'指标名称',
  1198. value:info.EdbName,
  1199. key:'EdbName',
  1200. notEdit:true
  1201. }]
  1202. // 中文单位有 才能编辑英文单位
  1203. if(info.Unit && info.Unit!='无'){
  1204. this.formItemArray.push({
  1205. label:'单位',
  1206. value:info.Unit,
  1207. key:'Unit',
  1208. notEdit:true
  1209. },
  1210. {
  1211. label:'英文指标名称',
  1212. value:info.EdbNameEn,
  1213. key:'EdbNameEn',
  1214. placeholder:'请输入英文指标名称'
  1215. },
  1216. {
  1217. label:'英文单位',
  1218. value:info.UnitEn,
  1219. key:'UnitEn',
  1220. placeholder:'请输入英文单位'
  1221. })
  1222. }else{
  1223. this.formItemArray.push({
  1224. label:'英文指标名称',
  1225. value:info.EdbNameEn,
  1226. key:'EdbNameEn',
  1227. placeholder:'请输入英文指标名称'
  1228. })
  1229. }
  1230. this.setEnName = true
  1231. },
  1232. clickEdbNameHandle() {
  1233. this.$refs.detailComponentRef.changeEnOptions();
  1234. },
  1235. updateEnName(item){
  1236. let params={
  1237. EdbInfoId: Number(this.select_id),
  1238. ...item
  1239. }
  1240. dataBaseInterface.edbInfoEditEn(params).then(res=>{
  1241. if(res.Ret ==200){
  1242. this.$message({
  1243. message:res.Msg,
  1244. type:"success"
  1245. })
  1246. this.detail_show_chart ? this.$refs.detailComponentRef.getDetail() : this.$refs.detailComponentRef.getData();
  1247. this.setEnName = false
  1248. this.getTreeData({
  1249. code: this.select_node,
  1250. id: this.select_id
  1251. });
  1252. }
  1253. })
  1254. },
  1255. /* 打开计算弹窗 */
  1256. addComputedHandler() {
  1257. this.computedTit = '计算指标';
  1258. this.calulateList = [];
  1259. this.calulateForm = {};
  1260. this.operationForm = {};
  1261. this.isOpenComputed = true;
  1262. },
  1263. /* 选择计算类型 */
  1264. changeComputedType(type) {
  1265. let typeMapSource = {
  1266. 'toMonthSeason': 42,
  1267. 'accumulate': 65
  1268. }
  1269. this.computed_type = typeMapSource[type] || type;;
  1270. this.isOpenComputed = false;
  1271. },
  1272. /* 新增计算指标回调 */
  1273. addComputedCallBack(type, params) {
  1274. this.computed_type = 0;
  1275. this.computed_source = 1;
  1276. this.showAssociateChart=false;
  1277. this.showAssociateComputeData=false;
  1278. type === 'add' ? this.getTreeData(params) : this.getTreeData();
  1279. if(type === 'edit') {
  1280. this.detail_show_chart ? this.$refs.detailComponentRef.getDetail() : this.$refs.detailComponentRef.getData();
  1281. }
  1282. },
  1283. /* 重绘右侧区域宽度 */
  1284. reloadRightWid() {
  1285. let total_wid = $('.predict-edb-main')[0].offsetWidth;
  1286. let left = $('#left')[0].offsetWidth;
  1287. let rigtWid = total_wid - left - 20 + 'px';
  1288. $('#right')[0].style.width = rigtWid;
  1289. },
  1290. //只看我的
  1291. onlyMeHandler(){
  1292. this.getTreeData()
  1293. this.public_page = 1;
  1294. this.$refs.listRef.scrollTop = 0;
  1295. this.getPublicList();
  1296. },
  1297. //懒加载el-tree
  1298. async getLazyTreeData(node,resolve,maxLevel=3){
  1299. if(node.level===0){
  1300. resolve(this.treeData)
  1301. }else{
  1302. let arr=[]
  1303. const res=await preDictEdbInterface.predictEdbCatalog({IsOnlyMe:this.isOnlyMe||false,ParentId:node.data.ClassifyId})
  1304. if (res.Ret === 200) {
  1305. const temarr = res.Data.AllNodes || [];
  1306. arr=temarr.map(item=>{
  1307. return {
  1308. ...item,
  1309. isLeaf:item.EdbInfoId?true:false
  1310. }
  1311. })
  1312. }
  1313. resolve(arr)
  1314. }
  1315. },
  1316. changeTreeNode(){
  1317. this.$refs.treeRef.setCurrentKey(this.select_node);
  1318. this.$nextTick(()=>{
  1319. const _node = this.$refs.treeRef.getNode(this.select_node)
  1320. this.dynamicNode = _node;
  1321. this.dynamicNode&&this.resetNodeStyle(this.dynamicNode)
  1322. })
  1323. },
  1324. changeShowType(){
  1325. if(!this.activeTab) return
  1326. this.detail_show_chart = this.activeTab==='Chart'?true:false
  1327. }
  1328. },
  1329. mounted() {
  1330. if (document.body.clientWidth <= 1400) {
  1331. //小屏适配
  1332. this.isSlideLeft = true;
  1333. }
  1334. const obj=sessionStorage.getItem('predictEdbTreeData')
  1335. if(obj||this.$route.query.code){
  1336. let code=obj?JSON.parse(obj).code:this.$route.query.code
  1337. let id=obj?JSON.parse(obj).id:this.$route.query.id
  1338. let classifyId=obj?JSON.parse(obj).classifyId:this.$route.query.classifyId
  1339. this.getTreeData({code: code,id: Number(id),classifyId:Number(classifyId)})
  1340. }else{
  1341. this.getTreeData()
  1342. }
  1343. // 清除缓存数据
  1344. setTimeout(() => {
  1345. sessionStorage.setItem('predictEdbTreeData','')
  1346. }, 1000);
  1347. this.getPublicList();
  1348. window.addEventListener('resize', this.reloadRightWid);
  1349. },
  1350. destroyed() {
  1351. window.removeEventListener('resize', this.reloadRightWid);
  1352. }
  1353. }
  1354. </script>
  1355. <style lang="scss">
  1356. .predictEdb-container{
  1357. .detail-header{
  1358. display: flex;
  1359. position: relative;
  1360. height: 60px;
  1361. .el-tabs{
  1362. width:200px;
  1363. .el-tabs__header{
  1364. margin-bottom: 0;
  1365. }
  1366. .el-tabs__nav{
  1367. display: flex;
  1368. width: 100%;
  1369. .el-tabs__item{
  1370. flex: 1;
  1371. text-align: center;
  1372. font-size: 16px;
  1373. height: 60px;
  1374. line-height: 60px;
  1375. }
  1376. }
  1377. }
  1378. }
  1379. .edb-tool{
  1380. flex: 1;
  1381. text-align: right;
  1382. display: flex;
  1383. gap: 16px;
  1384. justify-content: flex-end;
  1385. padding-right: 15px;
  1386. position: relative;
  1387. &::after{
  1388. position: absolute;
  1389. content:'';
  1390. width:100%;
  1391. left: 0;
  1392. bottom: 0;
  1393. height:2px;
  1394. background-color: #E4E7ED;
  1395. }
  1396. }
  1397. }
  1398. </style>
  1399. <style lang='scss' scoped>
  1400. @import "~@/styles/theme-vars.scss";
  1401. *{ box-sizing: border-box;}
  1402. $mini-font: 12px; $normal-font: 14px;
  1403. .predictEdb-container {
  1404. .slide-icon {
  1405. padding: 20px 0;
  1406. /* display: block; */
  1407. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.3);
  1408. border-radius: 5px;
  1409. cursor: pointer;
  1410. position: absolute;
  1411. top: 50%;
  1412. transform: translateY(-50%);
  1413. z-index: 99;
  1414. &:hover {
  1415. background-color: rgba(0, 0, 0, 0.05);
  1416. }
  1417. &.slide-left {
  1418. right: 0;
  1419. }
  1420. &.slide-right {
  1421. left: 0;
  1422. }
  1423. }
  1424. .predict-edb-main {
  1425. display: flex;
  1426. .main-left {
  1427. width: 400px;
  1428. min-width: 380px;
  1429. background: #fff;
  1430. margin-right: 20px;
  1431. border: 1px solid #ececec;
  1432. border-radius: 4px;
  1433. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
  1434. height: calc(100vh - 120px);
  1435. overflow: hidden;
  1436. position: relative;
  1437. box-sizing: border-box;
  1438. .datasheet_top {
  1439. padding: 20px;
  1440. background: #fff;
  1441. border: 1px solid #ececec;
  1442. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
  1443. margin-bottom: 20px;
  1444. display: flex;
  1445. align-items: center;
  1446. }
  1447. .search-cont {
  1448. padding: 0 20px;
  1449. }
  1450. .tree-cont {
  1451. padding: 0 20px 30px 20px;
  1452. /* max-height: calc(100vh - 280px);
  1453. overflow: auto; */
  1454. }
  1455. .target_tree {
  1456. color: #333;
  1457. max-height: calc(100vh - 400px);
  1458. overflow-y:auto;
  1459. .custom-tree-node {
  1460. display: flex !important;
  1461. justify-content: space-between;
  1462. align-items: center;
  1463. display: block;
  1464. flex: 1;
  1465. .node_label {
  1466. margin-right: 2px;
  1467. }
  1468. .el-icon-view {
  1469. color: #409eff;
  1470. font-size: 18px;
  1471. margin-left: 5px;
  1472. }
  1473. }
  1474. }
  1475. .noDepart {
  1476. margin: 30px 0;
  1477. display: flex;
  1478. align-items: center;
  1479. justify-content: center;
  1480. color: $theme-color;
  1481. font-size: 16px;
  1482. cursor: pointer;
  1483. }
  1484. .move-btn {
  1485. height: 100%;
  1486. width: 4px;
  1487. /* opacity: 0; */
  1488. position: absolute;
  1489. right: 0px;
  1490. top: 0;
  1491. &:hover {
  1492. cursor: col-resize;
  1493. /* background-color: orange */
  1494. }
  1495. }
  1496. }
  1497. .main-right {
  1498. width: 80%;
  1499. height: calc(100vh - 120px);
  1500. &.detail-main{
  1501. overflow-x:auto;
  1502. }
  1503. .edb-detail-wrapper {
  1504. height: 100%;
  1505. border: 1px solid #ececec;
  1506. border-radius: 4px;
  1507. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
  1508. overflow: hidden;
  1509. background: #fff;
  1510. &.main-min-width{
  1511. min-width: 780px;
  1512. }
  1513. .detail-top {
  1514. padding: 20px;
  1515. display: flex;
  1516. justify-content: space-between;
  1517. align-items: center;
  1518. border-bottom: 1px solid #ececec;
  1519. .title {
  1520. font-size: 16px;
  1521. &.disabled { color: #ccc; }
  1522. }
  1523. .action-ul {
  1524. display: flex;
  1525. li { margin: 0 10px; }
  1526. }
  1527. }
  1528. .detail-wrap {
  1529. position: relative;
  1530. padding: 16px;
  1531. height: calc(100vh - 180px);
  1532. overflow-y: auto;
  1533. .toggle-text {
  1534. position: absolute;
  1535. right: 20px;
  1536. top: 40px;
  1537. z-index: 2;
  1538. display: flex;
  1539. align-items: center;
  1540. }
  1541. /* min-height: 500px; */
  1542. }
  1543. }
  1544. .sheet-list-cont {
  1545. color: #333;
  1546. .el-card .el-card__header,
  1547. .el-card__body {
  1548. padding: 10px;
  1549. }
  1550. .list-top {
  1551. display: flex;
  1552. align-items: center;
  1553. justify-content: space-between;
  1554. }
  1555. .edbChartList-wrapper {
  1556. margin-top: 10px;
  1557. display: flex;
  1558. flex-wrap: wrap;
  1559. max-height: calc(100vh - 143px);
  1560. overflow: hidden;
  1561. overflow-y: auto;
  1562. .drag-cont {
  1563. width: 100%;
  1564. display: flex;
  1565. flex-wrap: wrap;
  1566. }
  1567. .dragShdow {
  1568. box-shadow: 0 1px 8px rgba(64, 158, 255, 0.8);
  1569. opacity: 0.5;
  1570. }
  1571. .sheet-item {
  1572. width:23%;
  1573. min-width: 255px;
  1574. border-radius: 4px;
  1575. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  1576. border: 1px solid #EBEEF5;
  1577. background-color: #FFFFFF;
  1578. overflow: hidden;
  1579. color: #303133;
  1580. transition: 0.3s;
  1581. .item-top,.item-bottom{
  1582. padding:10px;
  1583. text-align: left;
  1584. }
  1585. .item-top {
  1586. display: flex;
  1587. justify-content: space-between;
  1588. align-items: center;
  1589. font-size: 16px;
  1590. font-weight: 600;
  1591. box-shadow: 0 3px 6px rgba(37, 37, 239, 0.1);
  1592. }
  1593. .chart-img {
  1594. /* width: 100%;
  1595. height: 230px;
  1596. object-fit: fill !important; */
  1597. margin:10px;
  1598. margin-bottom: 0;
  1599. height: 0;
  1600. padding-bottom: 67%;
  1601. cursor: pointer;
  1602. }
  1603. .item-bottom {
  1604. display: flex;
  1605. justify-content: space-between;
  1606. font-size: 12px;
  1607. color: #666;
  1608. .collected {
  1609. color: #f00;
  1610. cursor: pointer;
  1611. }
  1612. .join_txt {
  1613. color: $theme-color;
  1614. cursor: pointer;
  1615. }
  1616. }
  1617. }
  1618. }
  1619. .nodata {
  1620. text-align: center;
  1621. }
  1622. }
  1623. }
  1624. }
  1625. .computed-ul {
  1626. max-height: 600px;
  1627. height: 70vh;
  1628. overflow-y: auto;
  1629. padding: 40px 92px;
  1630. display: flex;
  1631. flex-wrap: wrap;
  1632. .cpmputed-li {
  1633. width: 180px;
  1634. padding: 19px 0;
  1635. height:60px;
  1636. color: $theme-color;
  1637. font-size: 16px;
  1638. background:#ECF5FF;
  1639. border-radius: 8px;
  1640. border: 1px solid #B3D8FF;
  1641. text-align: center;
  1642. cursor: pointer;
  1643. margin-right: 65px;
  1644. margin-bottom: 55px;
  1645. &:nth-child(3n) {
  1646. margin-right:0;
  1647. }
  1648. &:hover {
  1649. background: $theme-color;
  1650. color: #fff;
  1651. }
  1652. &.act {
  1653. background: $theme-color;
  1654. color: #fff;
  1655. }
  1656. }
  1657. }
  1658. }
  1659. </style>
  1660. <style lang="scss">
  1661. @import "~@/styles/theme-vars.scss";
  1662. .predictEdb-container {
  1663. .label-input .el-input__inner {
  1664. height: 25px;
  1665. line-height: 25px;
  1666. padding: 0 10px;
  1667. }
  1668. .el-dialog--center .el-dialog__body {
  1669. padding: 40px 20px 30px 60px;
  1670. }
  1671. .el-tree__drop-indicator{
  1672. height:3px;
  1673. background-color: $theme-color;
  1674. }
  1675. .el-tree-node__content {
  1676. margin-bottom: 14px !important;
  1677. }
  1678. .el-tree-node__children {
  1679. .el-tree-node {
  1680. /* margin-bottom: 8px !important; */
  1681. margin-bottom: 0px !important;
  1682. padding-left: 18px;
  1683. }
  1684. .el-tree-node__content {
  1685. margin-bottom: 5px !important;
  1686. padding-left: 0 !important;
  1687. }
  1688. }
  1689. .expanded.el-icon-caret-right:before {
  1690. content: url('../../assets/img/set_m/down.png') !important;
  1691. }
  1692. .el-icon-caret-right:before {
  1693. content: url('../../assets/img/set_m/slide.png') !important;
  1694. }
  1695. .el-tree-node__expand-icon.is-leaf.el-icon-caret-right:before {
  1696. content: '' !important;
  1697. }
  1698. .el-tree-node__expand-icon.expanded {
  1699. -webkit-transform: rotate(0deg);
  1700. transform: rotate(0deg);
  1701. }
  1702. .el-tree-node.is-current > .el-tree-node__content {
  1703. background-color: #f0f4ff !important;
  1704. }
  1705. .el-tree-node__content {
  1706. padding-right: 10px !important;
  1707. }
  1708. .dialog-computed {
  1709. max-width:950px !important;
  1710. .el-dialog__header {
  1711. background-color: #fff;
  1712. .el-dialog__close {
  1713. color: #333;
  1714. }
  1715. }
  1716. }
  1717. }
  1718. </style>