glTargetbase.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. <template>
  2. <div class="lzTarget-container">
  3. <span
  4. class="slide-btn-icon"
  5. :class="{'slide-left':isLeftWrapShow,'slide-right':!isLeftWrapShow}"
  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" v-show="isLeftWrapShow">
  11. <div class="left-top">
  12. <!-- <el-button type="primary" plain size="medium" @click="exportClick" :loading="btnload">导出Excel</el-button> -->
  13. <el-button
  14. v-permission="permissionBtn.dataSourcePermission.glData_export"
  15. style="width: 100%"
  16. type="primary"
  17. plain
  18. size="medium"
  19. @click="exportClick"
  20. :loading="btnload"
  21. >导出Excel</el-button
  22. >
  23. <el-autocomplete
  24. style="margin: 20px 0; width: 100%"
  25. prefix-icon="el-icon-search"
  26. v-model="leftSearchVal"
  27. :fetch-suggestions="handleLeftSearch"
  28. :trigger-on-focus="false"
  29. placeholder="指标名称/指标ID"
  30. @select="handleSelectLeftSearchval"
  31. popper-class="el-autocomplete-suggestion-data-entry"
  32. clearable
  33. >
  34. <template slot-scope="scope">
  35. <div v-if="scope.item.nodata" style="text-align: center">
  36. 暂无数据
  37. </div>
  38. <div v-else>
  39. {{ scope.item.IndexName }}
  40. </div>
  41. </template>
  42. </el-autocomplete>
  43. </div>
  44. <ul class="classify-list">
  45. <li
  46. :class="[
  47. 'classify-item',
  48. { act: select_classify === item.BreedShortName },
  49. ]"
  50. v-for="item in classifyList"
  51. :key="item.BreedShortName"
  52. @click="changeClassify(item.BreedShortName)"
  53. >
  54. {{ item.BreedShortName }}
  55. </li>
  56. </ul>
  57. </div>
  58. <div
  59. class="right-cont minHeight"
  60. v-loading="dataloading"
  61. element-loading-text="获取数据中..."
  62. >
  63. <div
  64. class="right-box"
  65. v-infinite-scroll="loadNext"
  66. :infinite-scroll-disabled="!haveMore"
  67. :infinite-scroll-immediate="false"
  68. v-if="rightShow"
  69. >
  70. <div class="data-header">
  71. <lz-table
  72. :tableOption="tableOption"
  73. tableType="header"
  74. ref="table"
  75. source="gl"
  76. />
  77. </div>
  78. <div class="data-cont" v-if="dateArr.length">
  79. <lz-table
  80. :tableOption="tableOption"
  81. tableType="data"
  82. :dateArr="dateArr"
  83. source="gl"
  84. />
  85. </div>
  86. <div v-else class="nodata"></div>
  87. </div>
  88. <div class="frequency-list" v-if="rightShow">
  89. <el-button
  90. type="primary"
  91. class="frequency-btn"
  92. :plain="select_frequency !== item.key"
  93. v-for="item in frequencyList"
  94. :key="item.key"
  95. @click="changeFrequency(item.key)"
  96. >{{ item.key }}</el-button
  97. >
  98. </div>
  99. </div>
  100. </div>
  101. </template>
  102. <script>
  103. import lzTable from "@/components/lzTable.vue";
  104. import { glDataInterface } from "@/api/api.js";
  105. export default {
  106. name: "",
  107. components: { lzTable },
  108. watch: {
  109. select_classify(newval) {
  110. if (!this.isAuto) return;
  111. this.select_frequency = "";
  112. this.page_no = 1;
  113. newval && this.getFrequency();
  114. },
  115. select_frequency(newval) {
  116. if (!this.isAuto) return;
  117. this.page_no = 1;
  118. newval && this.getDataList();
  119. },
  120. },
  121. data() {
  122. return {
  123. isLeftWrapShow:true,
  124. dataloading: false,
  125. rightShow: false,
  126. exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/export/glList", //钢联数据导出接口
  127. select_classify: "",
  128. classifyList: [],
  129. select_frequency: "",
  130. frequencyList: [],
  131. tableOption: [],
  132. dateArr: [], //最长的日期数组
  133. btnload: false,
  134. page_size: 20,
  135. page_no: 1,
  136. haveMore: false,
  137. leftSearchVal: "", //左侧搜索值
  138. leftSearchTradeCode: "", //如果是搜索选择的 则有此code
  139. select_quota: "", // 选择的指标名
  140. select_Unit: "", // 选择的单位
  141. select_UpdateTime: "", // 更新时间
  142. select_breed: "", //选择的分类名
  143. isAuto: true, // 改变分类时是否自动获取数据
  144. };
  145. },
  146. methods: {
  147. /* 获取分类 */
  148. getClassify() {
  149. glDataInterface.classifyList().then((res) => {
  150. if (res.Ret !== 200) return;
  151. this.classifyList = res.Data || [];
  152. this.select_classify =
  153. this.select_classify || this.classifyList[0].BreedShortName;
  154. this.select_breed = this.select_classify;
  155. });
  156. },
  157. /* 获取频度 */
  158. getFrequency(defaultSelect) {
  159. glDataInterface
  160. .frequencyList({
  161. BreedShortName: this.select_classify,
  162. })
  163. .then((res) => {
  164. if (res.Ret !== 200) return;
  165. this.frequencyList = res.Data
  166. ? res.Data.map((item) => {
  167. return {
  168. key: item.Frequency,
  169. };
  170. })
  171. : [];
  172. //设置当前选中的频度,若传入有默认选项则选中默认频度,否则选中列表第一个
  173. this.select_frequency =
  174. defaultSelect || this.frequencyList.length
  175. ? this.frequencyList[0].key
  176. : "";
  177. !this.frequencyList.length && this.nodataDeal();
  178. //如果有默认频度,结束后恢复watcher
  179. this.$nextTick(() => {
  180. if (defaultSelect) this.isAuto = true;
  181. });
  182. });
  183. },
  184. /* 获取数据 */
  185. getDataList() {
  186. this.dataloading = true;
  187. glDataInterface
  188. .dataList({
  189. BreedShortName: this.select_classify,
  190. Frequency: this.select_frequency,
  191. PageSize: this.page_size,
  192. CurrentIndex: this.page_no,
  193. })
  194. .then((res) => {
  195. this.rightShow = true;
  196. if (res.Ret !== 200) return;
  197. // 找出最多的页码 判断是否还有数据
  198. let page_arrs = res.Data.map((item) => item.Paging.Pages);
  199. let totalPage = Math.max.apply(Math, page_arrs);
  200. this.haveMore = this.page_no < totalPage ? true : false;
  201. // 合并数据
  202. if (this.page_no === 1) {
  203. this.tableOption = res.Data;
  204. } else {
  205. this.tableOption.forEach((item) => {
  206. res.Data.forEach((_item) => {
  207. if (item.IndexCode === _item.IndexCode) {
  208. item.DataList = [...item.DataList, ..._item.DataList];
  209. }
  210. });
  211. });
  212. }
  213. // 找出所有指标中数据的日期做多的那个 拆出日期数组 用来遍历表格行 ---错误逻辑
  214. // 合并所有指标中的日期 作为日期数组
  215. let arr = res.Data.map((item) => {
  216. return item.DataList;
  217. });
  218. let obj = [];
  219. for (let i of arr) {
  220. for (let j of i) {
  221. obj.push(j.DataTime);
  222. }
  223. }
  224. let arr2 = [...new Set(obj)].sort().reverse();
  225. let concatArr = [...new Set([...this.dateArr, ...arr2])]
  226. .sort()
  227. .reverse();
  228. this.dateArr = this.page_no === 1 ? arr2 : concatArr;
  229. /* 不满6个追加6个空的显示一排 别问 问就是为了美观 */
  230. if (res.Data.length < 7)
  231. for (let i = 0; i < 7; i++) {
  232. this.tableOption.push({
  233. DataList: [],
  234. });
  235. if (this.tableOption.length >= 7) break;
  236. }
  237. //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
  238. if (this.dateArr.length < 12)
  239. for (let i = 0; i < 12; i++) {
  240. this.dateArr.push("");
  241. if (this.dateArr.length >= 12) break;
  242. }
  243. this.dataloading = false;
  244. this.page_no === 1 &&
  245. this.$nextTick(() => {
  246. this.initWidth();
  247. });
  248. });
  249. },
  250. // 获取单个指标数据
  251. async getTargetDataList(e) {
  252. this.dataloading = true;
  253. try {
  254. const res = await glDataInterface.getTargetDataList({
  255. IndexCode: this.leftSearchTradeCode,
  256. });
  257. this.rightShow = true;
  258. if (res.Ret !== 200) return;
  259. // 设置为没有更多数据
  260. this.haveMore = false;
  261. // 合并数据
  262. this.tableOption = [
  263. {
  264. DataList: res.Data,
  265. ...e,
  266. },
  267. ];
  268. // 这里是单个指标所以不用合并日期
  269. const arr = res.Data.map((item) => item.DataTime);
  270. this.dateArr = [...new Set(arr)].sort().reverse();
  271. /* 不满6个追加6个空的显示一排 别问 问就是为了美观 */
  272. for (let i = 0; i < 7; i++) {
  273. this.tableOption.push({
  274. DataList: [],
  275. });
  276. if (this.tableOption.length >= 7) break;
  277. }
  278. //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
  279. if (this.dateArr.length < 12)
  280. for (let i = 0; i < 12; i++) {
  281. this.dateArr.push("");
  282. if (this.dateArr.length >= 12) break;
  283. }
  284. this.dataloading = false;
  285. this.initWidth();
  286. } catch (err) {
  287. console.log(err);
  288. }
  289. },
  290. loadNext() {
  291. this.page_no++;
  292. this.getDataList();
  293. },
  294. /* 改变品种 */
  295. changeClassify(id) {
  296. this.select_classify = id;
  297. this.select_breed = id;
  298. this.leftSearchVal = "";
  299. this.leftSearchTradeCode = "";
  300. this.select_quota = "";
  301. this.select_Unit = "";
  302. this.select_UpdateTime = "";
  303. },
  304. /* 改变频度 */
  305. changeFrequency(key) {
  306. this.select_frequency = key;
  307. this.leftSearchVal = "";
  308. },
  309. initWidth() {
  310. $(".right-box")[0].style.width =
  311. this.$refs.table.$el.clientWidth + 5 + "px";
  312. $(".right-box")[0].scrollTop = 0;
  313. $(".right-box")[0].scrollLeft = 0;
  314. },
  315. /* 无频度的异常显示处理 7*12*/
  316. nodataDeal() {
  317. this.tableOption = [];
  318. this.dateArr = [];
  319. for (let i = 0; i < 7; i++) {
  320. this.tableOption.push({
  321. DataList: [],
  322. });
  323. if (this.tableOption.length >= 7) break;
  324. }
  325. for (let i = 0; i < 12; i++) {
  326. this.dateArr.push("");
  327. if (this.dateArr.length >= 12) break;
  328. }
  329. },
  330. /* 钢联数据导出 */
  331. exportClick() {
  332. this.btnload = true;
  333. // var iframe = document.createElement("iframe")
  334. // iframe.style.display = "none";
  335. // iframe.src = this.exportLzapi;
  336. // document.body.appendChild(iframe);
  337. const link = document.createElement("a");
  338. link.href = this.exportGlapi;
  339. link.download = "";
  340. link.click();
  341. console.log({
  342. QuotaName: this.select_quota,
  343. IndexCode: this.leftSearchTradeCode,
  344. BreedName: this.select_breed,
  345. sendBreedName: this.escapeStr(this.select_breed),
  346. Frequency: this.select_frequency,
  347. UnitName: this.select_Unit,
  348. ModifyTime: this.select_UpdateTime,
  349. url: this.exportGlapi,
  350. });
  351. setTimeout(() => {
  352. this.btnload = false;
  353. }, 5000);
  354. },
  355. //左侧搜索
  356. async handleLeftSearch(query, cb) {
  357. cb([]);
  358. if (!query) return;
  359. const res = await glDataInterface.getTargetListByName({
  360. Keyword: query,
  361. });
  362. if (res.Ret === 200) {
  363. let arr = res.Data || [];
  364. if (!arr.length) {
  365. cb([{ nodata: true }]);
  366. } else {
  367. cb(arr);
  368. }
  369. }
  370. },
  371. // 选中左侧搜索值
  372. handleSelectLeftSearchval(e) {
  373. if (!e.IndexCode) return;
  374. this.rightShow = false;
  375. this.select_frequency = e.FrequencyName;
  376. this.select_classify = e.BreedShortName;
  377. this.leftSearchTradeCode = e.IndexCode;
  378. this.leftSearchVal = e.IndexName;
  379. this.select_quota = e.IndexName;
  380. this.select_Unit = e.UnitName;
  381. this.select_UpdateTime = e.UpdateTime;
  382. this.select_breed = "";
  383. // 关闭watcher
  384. this.isAuto = false;
  385. this.getFrequency(e.FrequencyName);
  386. // 获取单独指标数据
  387. this.getTargetDataList(e);
  388. // this.getDataList()
  389. this.$nextTick(() => {
  390. this.rightShow = true;
  391. this.handleScrollLeftWrap();
  392. });
  393. },
  394. // 左侧滚动
  395. handleScrollLeftWrap() {
  396. let top = $(".act")[0].offsetTop;
  397. $(".classify-list").animate({
  398. scrollTop: top - 200,
  399. });
  400. },
  401. // 对[# ;]转义
  402. escapeStr(str) {
  403. return str.replace(/#/g, escape("#")).replace(/;/g, escape(";"));
  404. },
  405. },
  406. computed: {
  407. exportGlapi() {
  408. // 钢联数据导出接口
  409. let urlStr = this.exportBase;
  410. // token
  411. urlStr += `?${localStorage.getItem("auth") || ""}`;
  412. // 指标名称参数
  413. urlStr += `&QuotaName=${this.select_quota}`;
  414. // 指标id
  415. urlStr += `&IndexCode=${this.leftSearchTradeCode}`;
  416. // 分类名称
  417. urlStr += `&BreedName=${this.select_breed}`;
  418. // 频度
  419. urlStr += `&Frequency=${this.select_frequency}`;
  420. // 单位
  421. urlStr += `&UnitName=${this.select_Unit}`;
  422. // 修改时间
  423. urlStr += `&ModifyTime=${this.select_UpdateTime}`;
  424. return this.escapeStr(urlStr);
  425. },
  426. },
  427. created() {},
  428. mounted() {
  429. this.getClassify();
  430. },
  431. };
  432. </script>
  433. <style lang="scss" scoped>
  434. .lzTarget-container {
  435. display: flex;
  436. position:relative;
  437. .slide-btn-icon{
  438. &.slide-left{
  439. left:225px;
  440. }
  441. &.slide-right{
  442. left: 0;
  443. }
  444. }
  445. * {
  446. box-sizing: border-box;
  447. }
  448. .minHeight {
  449. height: calc(100vh - 120px);
  450. background-color: #fff;
  451. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
  452. border-radius: 4px;
  453. }
  454. div::-webkit-scrollbar {
  455. width: 5px !important;
  456. }
  457. .left-cont {
  458. min-width: 240px;
  459. width:240px;
  460. margin-right: 20px;
  461. padding: 30px 0;
  462. overflow: hidden;
  463. .left-top {
  464. padding: 0 20px;
  465. }
  466. .classify-list {
  467. padding: 0 20px;
  468. /* margin-top: 20px; */
  469. height: calc(100vh - 280px);
  470. overflow-y: auto;
  471. .classify-item {
  472. font-size: 14px;
  473. color: #666;
  474. margin-bottom: 20px;
  475. &:hover {
  476. cursor: pointer;
  477. color: #409eff;
  478. }
  479. &.act {
  480. color: #409eff;
  481. }
  482. }
  483. }
  484. }
  485. .right-cont {
  486. flex:1;
  487. padding: 30px;
  488. overflow-x: auto;
  489. .right-box {
  490. max-width: 100%;
  491. max-height: calc(100vh - 240px);
  492. border-left: 1px solid #dcdfe6;
  493. border-right: 1px solid #dcdfe6;
  494. overflow: auto;
  495. .data-header {
  496. width: 100%;
  497. position: sticky;
  498. top: 0;
  499. z-index: 2;
  500. }
  501. .data-cont {
  502. height: calc(100vh - 444px);
  503. }
  504. .nodata {
  505. height: calc(100vh - 460px);
  506. border: 1px solid #dcdfe6;
  507. font-size: 16px;
  508. color: #999;
  509. }
  510. }
  511. .frequency-list {
  512. margin-top: 20px;
  513. display: flex;
  514. flex-wrap: wrap;
  515. gap:20px;
  516. .el-button{
  517. margin-left: 0 !important;
  518. }
  519. .frequency-btn {
  520. width: 112px;
  521. }
  522. }
  523. }
  524. }
  525. </style>