FwmtData.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. <template>
  2. <div class="smmTarget-container target-container" id="box">
  3. <span
  4. v-show="!isLeftWrapShow"
  5. class="slide-btn-icon slide-right"
  6. @click="isLeftWrapShow = !isLeftWrapShow"
  7. >
  8. <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
  9. </span>
  10. <div class="left-cont minHeight" id="left" v-show="isLeftWrapShow">
  11. <span
  12. v-show="isLeftWrapShow"
  13. class="slide-btn-icon slide-left"
  14. @click="isLeftWrapShow = !isLeftWrapShow"
  15. >
  16. <i :class="{'el-icon-d-arrow-left':isLeftWrapShow,'el-icon-d-arrow-right':!isLeftWrapShow}"></i>
  17. </span>
  18. <div class="left-top">
  19. <el-button style="margin-left: 0;margin-bottom: 10px;" v-permission="permissionBtn.dataSourcePermission.mysteelData_batchAddEdb"
  20. type="primary" size="medium" @click="isBatchAddIndicsDiaShow = true"
  21. ><!-- 批量加入指标库 -->{{$t('SteelChemicalPage.batch_add_edb_btn')}}</el-button
  22. >
  23. <el-button
  24. v-permission="permissionBtn.dataSourcePermission.yyzxData_export"
  25. type="primary"
  26. plain
  27. size="medium"
  28. @click="exportClick"
  29. :loading="btnload"
  30. ><!-- 导出Excel -->{{$t('Common.exp_excel')}}</el-button
  31. >
  32. <el-autocomplete
  33. style="margin: 20px 0; width: 100%"
  34. prefix-icon="el-icon-search"
  35. v-model="leftSearchVal"
  36. :fetch-suggestions="handleLeftSearch"
  37. :trigger-on-focus="false"
  38. :placeholder="$t('Edb.InputHolderAll.input_name_orid')"
  39. @select="handleSelectLeftSearchval"
  40. popper-class="el-autocomplete-suggestion-data-entry"
  41. clearable
  42. >
  43. <template slot-scope="scope">
  44. <div v-if="scope.item.nodata" style="text-align: center">
  45. <!-- 暂无数据 -->{{$t('Table.prompt_slogan')}}
  46. </div>
  47. <div v-else>
  48. {{ scope.item.IndexName }}
  49. </div>
  50. </template>
  51. </el-autocomplete>
  52. </div>
  53. <div class="scroll-wrap">
  54. <el-tree
  55. ref="treeRef"
  56. class="target_tree word-wrap"
  57. :data="classifyList"
  58. node-key="ClassifyId"
  59. :props="{
  60. label: 'ClassifyName',
  61. children: 'Child',
  62. }"
  63. :default-expanded-keys="defaultShowNodes"
  64. :current-node-key="select_classify"
  65. :expand-on-click-node="false"
  66. check-strictly
  67. highlight-current
  68. empty-text="暂无分类"
  69. lazy
  70. :load="getLazyTreeData"
  71. @node-expand="handleNodeExpand"
  72. @node-collapse="handleNodeCollapse"
  73. @current-change="nodeChangeHandle"
  74. >
  75. <div slot-scope="{ node, data }" class="custom-tree-node">
  76. <div class="text_oneLine" style="width:100%">
  77. <span v-if="data.IndexCode">{{data.IndexName}}</span>
  78. <span v-else>
  79. <!-- {{ currentLang==='zh' ? data.ClassifyName : data.ClassifyNameEn }} -->
  80. {{ data.ClassifyName }}
  81. </span>
  82. </div>
  83. </div>
  84. </el-tree>
  85. </div>
  86. <span
  87. class="move-btn resize"
  88. v-drag
  89. id="resize"
  90. @mousemove="dynamicNode && resetNodeStyle(dynamicNode)"
  91. >
  92. </span>
  93. </div>
  94. <div
  95. class="right-cont minHeight"
  96. id="right"
  97. v-loading="dataloading"
  98. :element-loading-text="$t('Table.data_loading')"
  99. >
  100. <template v-if="rightShow">
  101. <div class="right-box" @scroll="scrollHandle">
  102. <div class="data-header">
  103. <lz-table
  104. :tableOption="tableOption"
  105. tableType="header"
  106. ref="table"
  107. source="yyzx"
  108. @addToLib="addToLib"
  109. @editTarget="editTargetByTable"
  110. />
  111. </div>
  112. <div class="data-cont" v-if="dateArr.length">
  113. <lz-table
  114. :tableOption="tableOption"
  115. tableType="data"
  116. :dateArr="dateArr"
  117. source="yyzx"
  118. />
  119. </div>
  120. <div v-else class="nodata"></div>
  121. </div>
  122. <el-button style="margin-left: 10px;margin-top: 20px;" plain
  123. type="primary" size="medium" @click=""
  124. ><!-- 批量加入指标库 -->周度</el-button
  125. >
  126. </template>
  127. <div v-else class="nodata-cont">
  128. <tableNoData :text="$t('Table.prompt_slogan')"/>
  129. </div>
  130. </div>
  131. <!-- 批量添加至指标库弹窗 -->
  132. <batchAddIndicsDia
  133. :isOpenDialog="isBatchAddIndicsDiaShow"
  134. @close="isBatchAddIndicsDiaShow=false"
  135. />
  136. <!-- 单个添加至指标库弹窗 -->
  137. <addIndicsDia
  138. :isOpenDialog="isAddIndicsDiaShow"
  139. :edbData="currentIndicData"
  140. @close="isAddIndicsDiaShow=false;"
  141. @addCallback="intoBaseBack"
  142. />
  143. </div>
  144. </template>
  145. <script>
  146. import lzTable from "@/components/lzTable.vue";
  147. import { fwmtInterface } from "@/api/api.js";
  148. import batchAddIndicsDia from "./components/batchAddIndicsDia"
  149. import addIndicsDia from './components/addIndicsDia.vue';
  150. import leftMixin from "./mixins/leftMixin.js";
  151. export default {
  152. name: "Fwmt",
  153. mixins: [leftMixin],
  154. components: { lzTable, batchAddIndicsDia, addIndicsDia },
  155. data() {
  156. return {
  157. isLeftWrapShow:true,
  158. exportBase:process.env.VUE_APP_API_ROOT + "/datamanage/fenwei/export", //ssm数据导出接口
  159. dataloading: false,
  160. rightShow: false,
  161. select_classify: 0,
  162. classifyList: [],
  163. tableOption: [],
  164. dateArr: [], //最长的日期数组
  165. btnload: false,
  166. page_no: 1,
  167. page_size: 20,
  168. havemore: true, //是否还有数据
  169. leftSearchVal: "", //左侧搜索值
  170. leftSearchTradeCode: "", //如果是搜索选择的 则有此code
  171. isShowSingleData: false, //右侧是否展示的是单个指标数据
  172. isBatchAddIndicsDiaShow: false, //批量添加指标弹窗
  173. currentIndicData:{}, //当前选中指标
  174. isAddIndicsDiaShow: false, //单个添加指标弹窗
  175. defaultShowNodes: [],
  176. repetition: null, // 是否重复请求
  177. };
  178. },
  179. methods: {
  180. /* 获取分类 */
  181. getClassify() {
  182. fwmtInterface.classifyList().then((res) => {
  183. if (res.Ret !== 200) return;
  184. this.classifyList = res.Data || [];
  185. });
  186. },
  187. /* 获取数据 */
  188. getDataList: _.throttle(function () {
  189. this.isShowSingleData = false;
  190. this.dataloading = true;
  191. fwmtInterface
  192. .dataList({
  193. ClassifyId: this.select_classify,
  194. PageSize: this.page_size,
  195. CurrentIndex: this.page_no,
  196. })
  197. .then((res) => {
  198. this.rightShow = true;
  199. if (res.Ret !== 200) return;
  200. // 找出最多的页码 判断是否还有数据
  201. let page_arrs = res.Data.map((item) => item.Paging.Pages);
  202. let totalPage = Math.max.apply(Math, page_arrs);
  203. this.havemore = this.page_no < totalPage ? true : false;
  204. // 合并数据
  205. if (this.page_no === 1) {
  206. this.tableOption = res.Data;
  207. } else {
  208. this.tableOption.forEach((item) => {
  209. res.Data.forEach((_item) => {
  210. if (item.IndexCode === _item.IndexCode) {
  211. item.DataList = item.DataList.concat(_item.DataList);
  212. }
  213. });
  214. });
  215. }
  216. // 合并所有指标中的日期 作为日期数组
  217. let arr = res.Data.map((item) => {
  218. return item.DataList;
  219. });
  220. let obj = [];
  221. for (let i of arr) {
  222. for (let j of i) {
  223. obj.push(j.DataTime);
  224. }
  225. }
  226. let arr2 = [...new Set(obj)].sort().reverse();
  227. let concatArr = [...new Set([...this.dateArr, ...arr2])]
  228. .sort()
  229. .reverse();
  230. this.dateArr = this.page_no === 1 ? arr2 : concatArr;
  231. /* 不满6个追加6个空的显示一排 别问 问就是为了美观 */
  232. if (this.tableOption.length < 7)
  233. for (let i = 0; i < 7; i++) {
  234. this.tableOption.push({
  235. DataList: [],
  236. });
  237. if (this.tableOption.length >= 7) break;
  238. }
  239. //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
  240. if (this.dateArr.length < 12)
  241. for (let i = 0; i < 12; i++) {
  242. this.dateArr.push("");
  243. if (this.dateArr.length >= 12) break;
  244. }
  245. this.dataloading = false;
  246. this.page_no === 1 &&
  247. this.$nextTick(() => {
  248. this.rightShow && this.initWidth();
  249. });
  250. });
  251. }, 200),
  252. // 获取单个指标数据
  253. async getTargetDataList(code) {
  254. this.isShowSingleData = true;
  255. this.dataloading = true;
  256. try {
  257. const res = await fwmtInterface.getTargetDataList({
  258. IndexCode: code,
  259. });
  260. this.rightShow = true;
  261. if (res.Ret !== 200) return;
  262. const DataList = res.Data.Data || [];
  263. // 设置为没有更多数据
  264. this.haveMore = false;
  265. // 合并数据
  266. this.tableOption = [
  267. {
  268. DataList: DataList,
  269. ...res.Data,
  270. },
  271. ];
  272. // 这里是单个指标所以不用合并日期
  273. const arr = DataList.map((item) => item.DataTime);
  274. this.dateArr = [...new Set(arr)].sort().reverse();
  275. /* 不满6个追加6个空的显示一排 别问 问就是为了美观 */
  276. for (let i = 0; i < 7; i++) {
  277. this.tableOption.push({
  278. DataList: [],
  279. });
  280. if (this.tableOption.length >= 7) break;
  281. }
  282. //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
  283. if (this.dateArr.length < 12)
  284. for (let i = 0; i < 12; i++) {
  285. this.dateArr.push("");
  286. if (this.dateArr.length >= 12) break;
  287. }
  288. this.select_quota = res.Data.IndexName;
  289. this.select_Unit = res.Data.Unit;
  290. this.select_frequency = res.Data.Frequency;
  291. this.select_ModifyTime = res.Data.ModifyTime || "";
  292. this.dataloading = false;
  293. this.rightShow && this.initWidth();
  294. } catch (err) {
  295. console.log(err);
  296. }
  297. },
  298. initWidth() {
  299. this.$nextTick(() => {
  300. $(".right-box")[0].style.width =
  301. this.$refs.table.$el.clientWidth + 5 + "px";
  302. $(".right-box")[0].scrollTop = 0;
  303. $(".right-box")[0].scrollLeft = 0;
  304. });
  305. },
  306. //指标懒加载
  307. async getLazyTreeData(node,resolve){
  308. let arr=[]
  309. if(node.level===2||node.data.ClassifyId === 0){
  310. const res=await fwmtInterface.dataList({
  311. ClassifyId: node.data.ClassifyId
  312. })
  313. if(res.Ret===200){
  314. const temarr=res.Data||[]
  315. arr=temarr.map(item=>{
  316. delete item.ClassifyId
  317. return {
  318. ...item,
  319. isLeaf:true
  320. }
  321. })
  322. }
  323. }else{
  324. arr=node.data.Child||[]
  325. }
  326. resolve(arr)
  327. },
  328. // 树节点展开
  329. handleNodeExpand(data) {
  330. // 保存当前展开的节点
  331. let flag = this.defaultShowNodes.some((item) => item === data.UniqueCode);
  332. if (!flag) {
  333. // 不存在则存到数组里
  334. this.defaultShowNodes.push(data.UniqueCode);
  335. }
  336. },
  337. // 树节点关闭
  338. handleNodeCollapse(data) {
  339. this.defaultShowNodes.some((item, index) => {
  340. if (item === data.UniqueCode) {
  341. // 删除关闭节点
  342. this.defaultShowNodes.length = index;
  343. }
  344. });
  345. },
  346. // 获取选中指标数据
  347. addToLib(data){
  348. //添加前校验 ID是否已存在指标库中
  349. //打开弹窗
  350. this.currentIndicData = data
  351. this.isAddIndicsDiaShow = true
  352. },
  353. //添加指标到库
  354. intoBaseBack() {
  355. this.isAddIndicsDiaShow = false
  356. if(this.selectedEdb){
  357. this.$refs.edbDetailRef.getEdbDetail()
  358. }else {
  359. this.getDataList()
  360. }
  361. },
  362. /* 无频度的异常显示处理 7*12*/
  363. nodataDeal() {
  364. this.tableOption = [];
  365. this.dateArr = [];
  366. for (let i = 0; i < 7; i++) {
  367. this.tableOption.push({
  368. DataList: [],
  369. });
  370. if (this.tableOption.length >= 7) break;
  371. }
  372. for (let i = 0; i < 12; i++) {
  373. this.dateArr.push("");
  374. if (this.dateArr.length >= 12) break;
  375. }
  376. },
  377. /* 滚动加载 */
  378. scrollHandle(e) {
  379. if (this.isShowSingleData) return;
  380. const dom = e.target;
  381. let total = dom.scrollTop + dom.clientHeight;
  382. if (total >= dom.scrollHeight && this.havemore) {
  383. this.page_no++;
  384. console.log("load下一页");
  385. this.getDataList();
  386. }
  387. },
  388. /* 数据导出 */
  389. exportClick() {
  390. this.btnload = true;
  391. const link = document.createElement("a");
  392. link.href = this.exportDataUrl;
  393. link.download = "";
  394. link.click();
  395. setTimeout(() => {
  396. this.btnload = false;
  397. }, 5000);
  398. },
  399. //左侧搜索
  400. async handleLeftSearch(query, cb) {
  401. cb([]);
  402. if (!query) return;
  403. const res = await fwmtInterface.getTargetListByName({
  404. Keyword: query,
  405. });
  406. if (res.Ret === 200) {
  407. let arr = res.Data || [];
  408. if (!arr.length) {
  409. cb([{ nodata: true }]);
  410. } else {
  411. cb(arr);
  412. }
  413. }
  414. },
  415. // 选中左侧搜索值
  416. handleSelectLeftSearchval(e) {
  417. if (!e.IndexCode) return;
  418. this.leftSearchTradeCode = e.IndexCode;
  419. this.leftSearchVal = e.IndexName;
  420. // 获取单独指标数据
  421. this.getTargetDataList(e.IndexCode);
  422. },
  423. /* 添加指标 */
  424. addTargetBatch() {
  425. this.batchAddDiaShow = true;
  426. },
  427. /* 添加后回调 */
  428. addSuccessCallback({ code, id,selectClassifyNodes,indexCode }) {
  429. indexCode && (this.index_code = indexCode)
  430. this.getClassify({ code, id,selectClassifyNodes });
  431. },
  432. getTargetData(code, arr) {
  433. for (const item of arr) {
  434. if (item.BaseFromBaiinfoIndexCode === code) return item;
  435. if (item.Children && item.Children.length) {
  436. const _item = this.getTargetData(code, item.Children);
  437. if (_item) return _item;
  438. }
  439. }
  440. },
  441. // 对[#,;]转义
  442. escapeStr(str) {
  443. return str.replace(/#/g, escape("#")).replace(/;/g, escape(";"));
  444. },
  445. //改变选中节点
  446. nodeChangeHandle(data, node) {
  447. if (data.ClassifyId === this.repetition || data.IndexCode === this.repetition) return;
  448. this.select_classify = data.ClassifyId;
  449. this.repetition = data.ClassifyId || data.IndexCode
  450. this.leftSearchVal=''
  451. this.page_no = 1;
  452. this.page_size = 20;
  453. if (!data.IndexCode)this.getDataList()
  454. // 获取单独指标数据
  455. else this.getTargetDataList(data.IndexCode);
  456. },
  457. },
  458. computed: {
  459. exportDataUrl() {
  460. // 数据导出接口
  461. let urlStr = this.exportBase;
  462. // token
  463. urlStr += `?${localStorage.getItem("auth") || ""}`;
  464. if (this.isShowSingleData) {
  465. // 指标id
  466. urlStr += `&IndexCode=${
  467. this.isShowSingleData ? this.leftSearchTradeCode : ""
  468. }`;
  469. } else {
  470. // 目录id
  471. urlStr += `&ClassifyId=${
  472. this.isShowSingleData ? "" : this.select_classify
  473. }`;
  474. }
  475. return this.escapeStr(urlStr);
  476. },
  477. },
  478. created() {},
  479. mounted() {
  480. this.getClassify();
  481. },
  482. };
  483. </script>
  484. <style lang="scss">
  485. @import "../css/customtree.scss";
  486. @import "../css/baseTargetPage.scss";
  487. .smmTarget-dialog-cont {
  488. .el-cascader {
  489. .el-input {
  490. width: 100% !important;
  491. }
  492. }
  493. }
  494. </style>
  495. <style lang="scss" scoped>
  496. .smmTarget-container {
  497. display: flex;
  498. * {
  499. box-sizing: border-box;
  500. }
  501. .minHeight {
  502. height: calc(100vh - 120px);
  503. background-color: #fff;
  504. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
  505. border-radius: 4px;
  506. }
  507. /* div::-webkit-scrollbar {
  508. width: 5px !important;
  509. } */
  510. .left-cont {
  511. min-width: 300px;
  512. width: 300px;
  513. margin-right: 20px;
  514. padding: 30px 0;
  515. overflow: hidden;
  516. position: relative;
  517. .left-top {
  518. padding: 0 20px;
  519. }
  520. .scroll-wrap {
  521. padding: 0 20px;
  522. height: calc(100vh - 280px);
  523. overflow-y: auto;
  524. margin-right: 20px;
  525. .target_tree {
  526. color: #333;
  527. .label-input .el-input__inner {
  528. height: 25px;
  529. line-height: 25px;
  530. }
  531. .custom-tree-node {
  532. display: flex !important;
  533. justify-content: space-between;
  534. align-items: center;
  535. display: block;
  536. flex: 1;
  537. .node_label {
  538. margin-right: 2px;
  539. }
  540. .el-icon-view {
  541. color: #409eff;
  542. font-size: 18px;
  543. margin-left: 5px;
  544. }
  545. }
  546. }
  547. .add-cont {
  548. margin: 50px 0 20px;
  549. display: flex;
  550. align-items: center;
  551. justify-content: center;
  552. color: #409eff;
  553. font-size: 16px;
  554. cursor: pointer;
  555. }
  556. }
  557. .move-btn {
  558. height: 100%;
  559. width: 4px;
  560. position: absolute;
  561. right: 0px;
  562. top: 0;
  563. &:hover {
  564. cursor: col-resize;
  565. }
  566. }
  567. .classify-list {
  568. padding: 0 20px;
  569. /* margin-top: 20px; */
  570. height: calc(100vh - 280px);
  571. overflow-y: auto;
  572. .classify-item {
  573. font-size: 14px;
  574. color: #666;
  575. margin-bottom: 20px;
  576. &:hover {
  577. cursor: pointer;
  578. color: #409eff;
  579. }
  580. &.act {
  581. color: #409eff;
  582. }
  583. }
  584. }
  585. }
  586. .right-cont {
  587. width: 82%;
  588. padding: 30px;
  589. .right-box {
  590. max-width: 100%;
  591. max-height: calc(100vh - 230px);
  592. border-left: 1px solid #dcdfe6;
  593. border-right: 1px solid #dcdfe6;
  594. overflow: auto;
  595. .data-header {
  596. width: 100%;
  597. position: sticky;
  598. top: 0;
  599. z-index: 2;
  600. }
  601. .data-cont {
  602. height: calc(100vh - 444px);
  603. }
  604. .nodata {
  605. height: calc(100vh - 460px);
  606. border: 1px solid #dcdfe6;
  607. font-size: 16px;
  608. color: #999;
  609. }
  610. }
  611. .frequency-list {
  612. margin-top: 20px;
  613. display: flex;
  614. flex-wrap: wrap;
  615. .frequency-btn {
  616. width: 112px;
  617. margin: 0 30px 10px 0;
  618. }
  619. }
  620. .nodata-cont {
  621. width: 150px !important;
  622. text-align: center;
  623. color: #666;
  624. font-size: 16px;
  625. margin: 0 auto;
  626. }
  627. }
  628. }
  629. .dialog-cont {
  630. padding-left: 50px;
  631. }
  632. .dia-bot {
  633. display: flex;
  634. justify-content: center;
  635. }
  636. </style>
  637. <style lang="scss">
  638. .smmTarget-container {
  639. .el-tree__drop-indicator {
  640. height: 3px;
  641. background-color: #409eff;
  642. }
  643. .el-tree-node__content {
  644. margin-bottom: 14px !important;
  645. }
  646. .el-tree-node__children {
  647. .el-tree-node {
  648. margin-bottom: 0px !important;
  649. padding-left: 18px;
  650. }
  651. .el-tree-node__content {
  652. margin-bottom: 5px !important;
  653. padding-left: 0 !important;
  654. }
  655. }
  656. .expanded.el-icon-caret-right:before {
  657. content: url("~@/assets/img/set_m/down.png") !important;
  658. }
  659. .el-icon-caret-right:before {
  660. content: url("~@/assets/img/set_m/slide.png") !important;
  661. }
  662. .el-tree-node__expand-icon.is-leaf.el-icon-caret-right:before {
  663. content: "" !important;
  664. }
  665. .el-tree-node__expand-icon.expanded {
  666. -webkit-transform: rotate(0deg);
  667. transform: rotate(0deg);
  668. }
  669. .el-tree-node.is-current > .el-tree-node__content {
  670. background-color: #f0f4ff !important;
  671. }
  672. .el-tree-node__content {
  673. padding-right: 10px !important;
  674. }
  675. }
  676. </style>