elaSteoBase.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <template>
  2. <div class="eteo-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
  13. v-permission="permissionBtn.dataSourcePermission.eiaData_export"
  14. style="width: 100%"
  15. type="primary"
  16. plain
  17. size="medium"
  18. @click="exportClick"
  19. :loading="btnload"
  20. >导出Excel</el-button
  21. >
  22. <el-autocomplete
  23. style="margin: 20px 0; width: 100%"
  24. prefix-icon="el-icon-search"
  25. v-model="leftSearchVal"
  26. :fetch-suggestions="handleLeftSearch"
  27. :trigger-on-focus="false"
  28. placeholder="指标名称/指标ID"
  29. @select="handleSelectLeftSearchval"
  30. popper-class="el-autocomplete-suggestion-data-entry"
  31. clearable
  32. >
  33. <template slot-scope="scope">
  34. <div v-if="scope.item.nodata" style="text-align: center">
  35. 暂无数据
  36. </div>
  37. <div v-else>
  38. {{ scope.item.IndexName }}
  39. </div>
  40. </template>
  41. </el-autocomplete>
  42. </div>
  43. <ul class="classify-list">
  44. <li
  45. :class="[
  46. 'classify-item',
  47. { act: select_classify === item.BaseFromEiaSteoClassifyId },
  48. ]"
  49. v-for="item in classifyList"
  50. :key="item.BaseFromEiaSteoClassifyId"
  51. @click="changeClassify(item.BaseFromEiaSteoClassifyId)"
  52. >
  53. {{ item.ClassifyName }}
  54. </li>
  55. </ul>
  56. </div>
  57. <div
  58. class="right-cont minHeight"
  59. v-loading="dataloading"
  60. element-loading-text="获取数据中..."
  61. >
  62. <div class="right-box" @scroll="scrollHandle" v-if="rightShow">
  63. <div class="data-header">
  64. <lz-table
  65. :tableOption="tableOption"
  66. tableType="header"
  67. ref="table"
  68. source="smm"
  69. />
  70. </div>
  71. <div class="data-cont" v-if="dateArr.length">
  72. <lz-table
  73. :tableOption="tableOption"
  74. tableType="data"
  75. :dateArr="dateArr"
  76. source="smm"
  77. />
  78. </div>
  79. <div v-else class="nodata"></div>
  80. </div>
  81. </div>
  82. </div>
  83. </template>
  84. <script>
  85. import lzTable from "@/components/lzTable.vue";
  86. import { steoInterface } from "@/api/modules/thirdBaseApi.js";
  87. export default {
  88. name: "",
  89. components: { lzTable },
  90. data() {
  91. return {
  92. isLeftWrapShow:true,
  93. exportBase: process.env.VUE_APP_API_ROOT + "/datamanage/eia_steo/data", //数据导出接口
  94. dataloading: false,
  95. rightShow: false,
  96. select_classify: "",
  97. classifyList: [],
  98. tableOption: [],
  99. dateArr: [], //最长的日期数组
  100. btnload: false,
  101. page_no: 1,
  102. page_size: 20,
  103. havemore: true, //是否还有数据
  104. leftSearchVal: "", //左侧搜索值
  105. leftSearchTradeCode: "", //如果是搜索选择的 则有此code
  106. };
  107. },
  108. methods: {
  109. /* 获取分类 */
  110. getClassify() {
  111. steoInterface.classifyList().then((res) => {
  112. if (res.Ret !== 200) return;
  113. this.classifyList = res.Data || [];
  114. this.select_classify =
  115. this.select_classify ||
  116. this.classifyList[0].BaseFromEiaSteoClassifyId;
  117. this.page_no = 1;
  118. this.getDataList();
  119. });
  120. },
  121. /* 获取数据 */
  122. getDataList: _.throttle(function () {
  123. this.dataloading = true;
  124. steoInterface
  125. .dataList({
  126. BaseFromEiaSteoClassifyId: this.select_classify,
  127. IndexCode: this.leftSearchTradeCode || "",
  128. PageSize: this.page_size,
  129. CurrentIndex: this.page_no,
  130. IsExport: false,
  131. })
  132. .then((res) => {
  133. this.rightShow = true;
  134. if (res.Ret !== 200) return;
  135. // 找出最多的页码 判断是否还有数据
  136. let page_arrs = res.Data.map((item) => item.Paging.Pages);
  137. let totalPage = Math.max.apply(Math, page_arrs);
  138. this.havemore = this.page_no < totalPage ? true : false;
  139. // 合并数据
  140. if (this.page_no === 1) {
  141. this.tableOption = res.Data;
  142. } else {
  143. this.tableOption.forEach((item) => {
  144. res.Data.forEach((_item) => {
  145. if (item.IndexCode === _item.IndexCode) {
  146. item.DataList = item.DataList.concat(_item.DataList);
  147. }
  148. });
  149. });
  150. }
  151. // 合并所有指标中的日期 作为日期数组
  152. let arr = res.Data.map((item) => item.DataList);
  153. let obj = [];
  154. for (let i of arr) {
  155. for (let j of i) {
  156. obj.push(j.DataTime);
  157. }
  158. }
  159. let arr2 = [...new Set(obj)].sort().reverse();
  160. let concatArr = [...new Set([...this.dateArr, ...arr2])]
  161. .sort()
  162. .reverse();
  163. this.dateArr = this.page_no === 1 ? arr2 : concatArr;
  164. /* 不满6个追加6个空的显示一排 别问 问就是为了美观 */
  165. if (this.tableOption.length < 7)
  166. for (let i = 0; i < 7; i++) {
  167. this.tableOption.push({
  168. DataList: [],
  169. });
  170. if (this.tableOption.length >= 7) break;
  171. }
  172. //数据最大长度小于12个 追加数据满12个 别问 问就是为了美观
  173. if (this.dateArr.length < 12)
  174. for (let i = 0; i < 12; i++) {
  175. this.dateArr.push("");
  176. if (this.dateArr.length >= 12) break;
  177. }
  178. this.dataloading = false;
  179. this.page_no === 1 &&
  180. this.$nextTick(() => {
  181. this.initWidth();
  182. });
  183. });
  184. }, 200),
  185. /* 改变品种 */
  186. changeClassify(id) {
  187. this.select_classify = id;
  188. this.leftSearchVal = "";
  189. this.leftSearchTradeCode = "";
  190. this.page_no = 1;
  191. this.getDataList();
  192. },
  193. initWidth() {
  194. $(".right-box")[0].style.width =
  195. this.$refs.table.$el.clientWidth + 5 + "px";
  196. $(".right-box")[0].scrollTop = 0;
  197. $(".right-box")[0].scrollLeft = 0;
  198. },
  199. /* 滚动加载 */
  200. scrollHandle(e) {
  201. const dom = e.target;
  202. let total = dom.scrollTop + dom.clientHeight;
  203. if (total >= dom.scrollHeight && this.havemore) {
  204. this.page_no++;
  205. console.log("load下一页");
  206. this.getDataList();
  207. }
  208. },
  209. //左侧搜索
  210. async handleLeftSearch(query, cb) {
  211. cb([]);
  212. if (!query) return;
  213. const res = await steoInterface.targetSearch({
  214. Keyword: query,
  215. });
  216. if (res.Ret !== 200) return;
  217. let arr = res.Data || [];
  218. if (!arr.length) {
  219. cb([{ nodata: true }]);
  220. } else {
  221. cb(arr);
  222. }
  223. },
  224. // 选中左侧搜索值
  225. handleSelectLeftSearchval(e) {
  226. if (!e.IndexCode) return;
  227. this.rightShow = false;
  228. this.select_classify = e.BaseFromEiaSteoClassifyId;
  229. this.leftSearchTradeCode = e.IndexCode;
  230. this.leftSearchVal = e.IndexName;
  231. this.page_no = 1;
  232. // 获取单独指标数据
  233. this.getDataList();
  234. this.$nextTick(() => {
  235. this.rightShow = true;
  236. this.handleScrollLeftWrap();
  237. });
  238. },
  239. // 左侧滚动
  240. handleScrollLeftWrap() {
  241. let top = $(".act")[0].offsetTop;
  242. $(".classify-list").animate({
  243. scrollTop: top - 200,
  244. });
  245. },
  246. // 对[#,;]转义
  247. escapeStr(str) {
  248. return str.replace(/#/g, escape("#")).replace(/;/g, escape(";"));
  249. },
  250. exportClick() {
  251. this.btnload = true;
  252. const link = document.createElement("a");
  253. link.href = this.exportApi;
  254. console.log(this.exportApi);
  255. link.download = "";
  256. link.click();
  257. setTimeout(() => {
  258. this.btnload = false;
  259. }, 5000);
  260. },
  261. },
  262. computed: {
  263. exportApi() {
  264. //数据导出
  265. let urlStr = this.exportBase;
  266. // token
  267. urlStr += `?${localStorage.getItem("auth") || ""}`;
  268. // 指标名称参数
  269. urlStr += `&BaseFromEiaSteoClassifyId=${this.select_classify}`;
  270. // 指标id
  271. urlStr += `&IndexCode=${this.leftSearchTradeCode}`;
  272. // 分类名称
  273. urlStr += `&IsExport=true`;
  274. return this.escapeStr(urlStr);
  275. },
  276. },
  277. mounted() {
  278. this.getClassify();
  279. },
  280. };
  281. </script>
  282. <style lang="scss" scoped>
  283. .eteo-container {
  284. display: flex;
  285. position:relative;
  286. .slide-btn-icon{
  287. &.slide-left{
  288. left:225px;
  289. }
  290. &.slide-right{
  291. left: 0;
  292. }
  293. }
  294. * {
  295. box-sizing: border-box;
  296. }
  297. .minHeight {
  298. height: calc(100vh - 120px);
  299. background-color: #fff;
  300. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
  301. border-radius: 4px;
  302. }
  303. div::-webkit-scrollbar {
  304. width: 5px !important;
  305. }
  306. .left-cont {
  307. min-width: 240px;
  308. width:240px;
  309. margin-right: 20px;
  310. padding: 30px 0;
  311. overflow: hidden;
  312. .left-top {
  313. padding: 0 20px;
  314. }
  315. .classify-list {
  316. padding: 0 20px;
  317. /* margin-top: 20px; */
  318. height: calc(100vh - 280px);
  319. overflow-y: auto;
  320. .classify-item {
  321. font-size: 14px;
  322. color: #666;
  323. margin-bottom: 20px;
  324. &:hover {
  325. cursor: pointer;
  326. color: #409eff;
  327. }
  328. &.act {
  329. color: #409eff;
  330. }
  331. }
  332. }
  333. }
  334. .right-cont {
  335. flex:1;
  336. padding: 30px;
  337. overflow-x: auto;
  338. .right-box {
  339. max-width: 100%;
  340. max-height: calc(100vh - 230px);
  341. border-left: 1px solid #dcdfe6;
  342. border-right: 1px solid #dcdfe6;
  343. overflow: auto;
  344. .data-header {
  345. width: 100%;
  346. position: sticky;
  347. top: 0;
  348. z-index: 2;
  349. }
  350. .data-cont {
  351. height: calc(100vh - 444px);
  352. }
  353. .nodata {
  354. height: calc(100vh - 460px);
  355. border: 1px solid #dcdfe6;
  356. font-size: 16px;
  357. color: #999;
  358. }
  359. }
  360. .frequency-list {
  361. margin-top: 20px;
  362. display: flex;
  363. flex-wrap: wrap;
  364. .frequency-btn {
  365. width: 112px;
  366. margin: 0 30px 10px 0;
  367. }
  368. }
  369. }
  370. }
  371. </style>