ExportExcel.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. <template>
  2. <div class="ExportExcel">
  3. <el-row
  4. style="
  5. margin-bottom: 15px;
  6. padding-bottom: 15px;
  7. border-bottom: 2px solid #ffffff;
  8. "
  9. >
  10. <el-col :span="12">
  11. <button
  12. class="btn"
  13. :class="templateId == 1 ? 'green' : ''"
  14. @click="typeClick(1)"
  15. >
  16. 单机数据模板
  17. </button>
  18. <button
  19. class="btn"
  20. :class="templateId == 2 ? 'green' : ''"
  21. @click="typeClick(2)"
  22. >
  23. 上网电量及功率、测风塔数据模板
  24. </button>
  25. </el-col>
  26. <el-col :span="12">
  27. <el-row justify="end">
  28. <button class="btn green" @click="allExport()">一键导出</button>
  29. </el-row>
  30. </el-col>
  31. </el-row>
  32. <table class="com-table">
  33. <thead>
  34. <tr>
  35. <th>场站</th>
  36. <th>
  37. <input
  38. class="t2"
  39. type="checkbox"
  40. @click="rqCheck"
  41. checked="checked"
  42. />
  43. 日期
  44. </th>
  45. <th>
  46. <input
  47. class="t2"
  48. type="checkbox"
  49. @click="sjCheck"
  50. checked="checked"
  51. />
  52. 时间间隔(s)
  53. </th>
  54. <th width="120px">操作</th>
  55. </tr>
  56. </thead>
  57. <el-scrollbar>
  58. <tbody>
  59. <tr v-for="(row, index) of tableData" :key="index">
  60. <td>
  61. {{ row.fdc }}
  62. </td>
  63. <td class="excelPickerTd">
  64. <el-date-picker
  65. class="mr15"
  66. format="YYYY-MM"
  67. v-model="dateArray[index]"
  68. type="month"
  69. placeholder="请选择"
  70. @change="changeDate"
  71. >
  72. </el-date-picker>
  73. </td>
  74. <td>
  75. <el-select
  76. v-model="timeData[index]"
  77. clearable
  78. placeholder="Select"
  79. @change="changeTableTime"
  80. >
  81. <el-option
  82. v-for="item in timeArray"
  83. :key="item.value"
  84. :label="item.label"
  85. :value="item.value"
  86. >
  87. </el-option>
  88. </el-select>
  89. </td>
  90. <td width="120px">
  91. <el-button
  92. type="text"
  93. style="cursor: pointer"
  94. @click="singleExport(index)"
  95. >导出
  96. </el-button>
  97. </td>
  98. </tr>
  99. </tbody>
  100. </el-scrollbar>
  101. </table>
  102. </div>
  103. </template>
  104. <script>
  105. import JsZip from "jszip";
  106. import { export_blob, export_more_blob } from "@tools/excel/Export2Excel.js";
  107. import BASE from "@tools/basicTool.js";
  108. export default {
  109. components: {
  110. JsZip,
  111. },
  112. data() {
  113. const that = this;
  114. return {
  115. single: false, //单击导出状态【点击后,用于判断其状态,为true时,loading显示】
  116. rqChecked: true, //日期单击checkbox状态【为true时,下方任意日期选择与当前选择同步】
  117. sjChecked: true, //时间间隔checkbox状态【为true时,下方任意时间选择与当前选择同步】
  118. tableData: [], //表格数据
  119. dateArray: [], //日期数组,默认一个月的,当用户改变某一个时,找到对应下标去改数据
  120. //时间同上
  121. timeArray: [
  122. {
  123. label: "5分钟",
  124. value: "300",
  125. },
  126. {
  127. label: "10分钟",
  128. value: "600",
  129. },
  130. {
  131. label: "15分钟",
  132. value: "900",
  133. },
  134. ],
  135. timeData: [],
  136. startTs: [], //起始时间,通过下标去找对应的时间
  137. endTs: [], //结束时间
  138. muBan: {
  139. type1: [
  140. "数据时间",
  141. "scada风速(m/s)",
  142. "scada功率(kW)",
  143. "是否故障(故障=1,不故障=0)",
  144. "是否限电(限电=1,不限电=0)",
  145. ],
  146. type2: [
  147. ["数据时间", "日报上网电量(mWh)"],
  148. ["数据时间", "上网功率(kW)"],
  149. [
  150. "数据时间",
  151. "轮毂高度平均风速(m/s)",
  152. "轮毂高度平均风向(°)",
  153. "温度(℃)",
  154. "压强(hPa)",
  155. "湿度(%)",
  156. ],
  157. ],
  158. },
  159. templateId: 1, //模板默认为1
  160. stations: [], //场站名
  161. paths: [], //excel的所有数据,最终给zip传
  162. pathName: [], //excel的名字
  163. zipNames: [],
  164. tempArrayS: [], //模板2时,遍历里面的数据
  165. };
  166. },
  167. created() {
  168. this.tableVal();
  169. },
  170. methods: {
  171. rqCheck(event) {
  172. this.rqChecked = event.target.checked;
  173. },
  174. sjCheck(event) {
  175. this.sjChecked = event.target.checked;
  176. },
  177. typeClick(a) {
  178. //模板切换,改变按钮颜色
  179. this.templateId = a;
  180. },
  181. singleExport(index) {
  182. //当前导出,index为下标
  183. let that = this;
  184. that.API.requestData({
  185. method: "GET",
  186. subUrl: "export/downloadFile",
  187. showLoading: true,
  188. data: {
  189. station: that.tableData[index].value,
  190. templateId: that.templateId,
  191. month: that.dateArray[index].formatDate("yyyy-MM"),
  192. interval: that.timeData[index],
  193. },
  194. success(res) {
  195. var filename = res.data.name;
  196. var eleLink = document.createElement("a");
  197. const downloadLink = (res.data.path + "\\" + filename)
  198. .replace(/\\/g, "/")
  199. .replace(/http:\//g, "http://")
  200. .replace(/https:\//g, "https://");
  201. eleLink.download = filename;
  202. eleLink.style.display = "none";
  203. eleLink.href = downloadLink;
  204. document.body.appendChild(eleLink);
  205. eleLink.click();
  206. document.body.removeChild(eleLink);
  207. },
  208. });
  209. },
  210. tableVal() {
  211. let that = this;
  212. that.API.requestData({
  213. method: "GET",
  214. subUrl: "export/databases",
  215. success(res) {
  216. const arr3 = [];
  217. const arr4 = [];
  218. var data = []; //项目列表
  219. res.data.forEach((item, index) => {
  220. const value = Object.keys(item)[0];
  221. arr3.push(value);
  222. arr4.push(item[value]);
  223. data.push({
  224. fdc: item[value],
  225. value: value,
  226. });
  227. that.timeData.push("300");
  228. });
  229. that.stations = arr3;
  230. that.zipNames = arr4;
  231. that.tableData = data;
  232. that.defaultValue1();
  233. },
  234. });
  235. },
  236. defaultValue1() {
  237. const start = new Date();
  238. start.setTime(start.getTime());
  239. this.tableData.forEach((ele, index) => {
  240. this.dateArray.push(start);
  241. });
  242. },
  243. formatJson(filterVal, jsonData) {
  244. //模板1时,转数据格式
  245. return jsonData.map((v) => filterVal.map((j) => v[j]));
  246. },
  247. allExport() {
  248. //一键导出
  249. let that = this;
  250. let station = [];
  251. that.tableData.forEach((ele) => {
  252. station.push(ele.value);
  253. });
  254. let month = [];
  255. that.dateArray.forEach((ele) => {
  256. month.push(ele.formatDate("yyyy-MM"));
  257. });
  258. let interval = [];
  259. that.timeData.forEach((ele) => {
  260. interval.push(ele);
  261. });
  262. that.API.requestData({
  263. method: "GET",
  264. subUrl: "export/downloadFile",
  265. showLoading: true,
  266. data: {
  267. station: station.toString(),
  268. templateId: that.templateId,
  269. month: month.toString(),
  270. interval: interval.toString(),
  271. },
  272. success(res) {
  273. var filename = res.data.name;
  274. var eleLink = document.createElement("a");
  275. const downloadLink = (res.data.path + "\\" + filename)
  276. .replace(/\\/g, "/")
  277. .replace(/http:\//g, "http://")
  278. .replace(/https:\//g, "https://");
  279. eleLink.download = filename;
  280. eleLink.style.display = "none";
  281. eleLink.href = downloadLink;
  282. document.body.appendChild(eleLink);
  283. eleLink.click();
  284. document.body.removeChild(eleLink);
  285. },
  286. });
  287. },
  288. allExportF(_index, thisIndex) {
  289. //_index递归递增,thisIndex单击导出【下标】
  290. const that = this;
  291. var loadingName =
  292. thisIndex != undefined
  293. ? "正在导出" + that.zipNames[thisIndex]
  294. : that.zipNames[_index] != undefined
  295. ? "正在导出" + that.zipNames[_index]
  296. : "正在合成压缩包";
  297. BASE.showLoading({ text: loadingName + ",请耐心等待..." });
  298. if (that.stations[_index]) {
  299. that.API.requestData({
  300. method: "GET",
  301. subUrl: "export/history/all",
  302. data: {
  303. templateId: that.templateId,
  304. startTs:
  305. thisIndex != undefined
  306. ? that.startTs[thisIndex]
  307. : that.startTs[_index],
  308. endTs:
  309. thisIndex != undefined
  310. ? that.endTs[thisIndex] + 86400000
  311. : that.endTs[_index] + 86400000,
  312. interval:
  313. thisIndex != undefined
  314. ? that.inputVal[thisIndex]
  315. : that.inputVal[_index],
  316. station:
  317. thisIndex != undefined
  318. ? that.stations[thisIndex]
  319. : that.stations[_index],
  320. },
  321. success(res) {
  322. if (res.code == 200) {
  323. if (thisIndex != undefined) {
  324. //单击导出
  325. if (that.templateId == 1) {
  326. //模板1
  327. that.export(res.data, 0, that.zipNames[thisIndex]);
  328. } else if (that.templateId == 2) {
  329. //模板2
  330. that.exportMuban2(res.data, 0, that.zipNames[thisIndex]);
  331. }
  332. } else {
  333. //一键导出
  334. if (that.templateId == 1) {
  335. that.export(res.data, 0, that.zipNames[_index], ++_index);
  336. } else if (that.templateId == 2) {
  337. that.exportMuban2(
  338. res.data,
  339. 0,
  340. that.zipNames[_index],
  341. ++_index
  342. );
  343. }
  344. }
  345. }
  346. },
  347. });
  348. }
  349. },
  350. export(data, _index, zipName, deepIndex) {
  351. // deepIndex判断单击或一键
  352. const that = this;
  353. let tHeader = that.muBan["type" + that.templateId];
  354. var dataKey = Object.keys(data);
  355. var key = dataKey[_index];
  356. if (key) {
  357. let tempObject = {};
  358. let tempArray = [];
  359. const dataLength = data[key].length;
  360. let filterVal = [];
  361. data[key][0].forEach((pEle, pIndex) => {
  362. for (let i = 0; i < dataLength; i++) {
  363. tempObject[String(i)] = data[key][i][pIndex];
  364. }
  365. tempArray.push(tempObject);
  366. tempObject = {};
  367. });
  368. data[key][0].forEach((ele, index) => {
  369. filterVal.push(index);
  370. });
  371. that.paths.push(
  372. export_blob(tHeader, that.formatJson(filterVal, tempArray))
  373. ); //传blob
  374. var str = key.split("_");
  375. that.pathName.push(str[0].substring(0, 2) + str[1]); //excel的名字
  376. _index++;
  377. if (deepIndex != undefined) {
  378. setTimeout(() => {
  379. that.export(data, _index, zipName, deepIndex);
  380. }, 1000);
  381. if (dataKey.length == _index) {
  382. //当长度一致时,向zip塞值
  383. var thisPath = that.paths,
  384. thisPathName = that.pathName;
  385. that.paths = [];
  386. that.pathName = [];
  387. that.zipOut(thisPath, thisPathName, zipName, deepIndex);
  388. }
  389. } else {
  390. setTimeout(() => {
  391. that.export(data, _index, zipName);
  392. }, 1000);
  393. if (dataKey.length == _index) {
  394. //当长度一致时,向zip塞值
  395. var thisPath = that.paths,
  396. thisPathName = that.pathName;
  397. that.paths = [];
  398. that.pathName = [];
  399. that.zipOut(thisPath, thisPathName, zipName);
  400. }
  401. }
  402. }
  403. },
  404. exportMuban2(data, _index, excelName, deepIndex) {
  405. const that = this;
  406. var dataKey = Object.keys(data);
  407. let tHeader = that.muBan["type" + that.templateId];
  408. var key = dataKey[_index];
  409. if (key) {
  410. let tempObject = {};
  411. let tempArray = [];
  412. const dataLength = data[key].length;
  413. data[key][0].forEach((pEle, pIndex) => {
  414. for (let i = 0; i < dataLength; i++) {
  415. tempObject[String(i)] = data[key][i][pIndex];
  416. }
  417. tempArray.push(tempObject);
  418. tempObject = {};
  419. });
  420. that.tempArrayS.push(tempArray);
  421. _index++;
  422. if (dataKey.length == that.tempArrayS.length) {
  423. let obj = [];
  424. that.tempArrayS.forEach((ele, index) => {
  425. obj[index] = [];
  426. ele.forEach((ele2, index2) => {
  427. var key = Object.keys(ele2);
  428. var arr = [];
  429. key.forEach((ele3, index3) => {
  430. arr.push(ele2[ele3]);
  431. });
  432. obj[index][index2] = arr;
  433. arr = [];
  434. });
  435. });
  436. if (deepIndex != undefined) {
  437. that.paths.push(export_more_blob(tHeader, obj)); //传blob
  438. that.pathName.push(excelName); //excel的名字
  439. that.tempArrayS = [];
  440. that.allExportF(deepIndex);
  441. } else {
  442. that.paths.push(export_more_blob(tHeader, obj, excelName)); //只渲染一个excel
  443. BASE.closeLoading();
  444. }
  445. }
  446. if (deepIndex != undefined) {
  447. that.exportMuban2(data, _index, excelName, deepIndex);
  448. if (that.stations.length == deepIndex && _index == 1) {
  449. //当长度一致时,向zip塞值,_index只让执行第一次
  450. var thisPath = that.paths,
  451. thisPathName = that.pathName;
  452. that.tempArrayS = [];
  453. that.paths = [];
  454. that.pathName = [];
  455. that.zipOut(
  456. thisPath,
  457. thisPathName,
  458. "风电场_上网电量&功率&测风塔数据"
  459. );
  460. BASE.closeLoading();
  461. }
  462. } else {
  463. that.exportMuban2(data, _index, excelName);
  464. if (that.stations.length && _index == 1) {
  465. //当长度一致时,向zip塞值,_index只让执行第一次
  466. var thisPath = that.paths,
  467. thisPathName = that.pathName;
  468. that.tempArrayS = [];
  469. that.paths = [];
  470. that.pathName = [];
  471. BASE.closeLoading();
  472. }
  473. }
  474. }
  475. },
  476. changeDate(value) {
  477. if (this.rqCheck) {
  478. let dateArray = [];
  479. this.dateArray.forEach((ele) => {
  480. dateArray.push(value);
  481. });
  482. this.dateArray = dateArray;
  483. }
  484. },
  485. changeTableTime(value) {
  486. if (this.sjChecked) {
  487. let timeData = [];
  488. this.timeData.forEach((ele) => {
  489. timeData.push(value);
  490. });
  491. this.timeData = timeData;
  492. }
  493. },
  494. zipOut(paths, pathName, zipName, deepIndex) {
  495. // paths 所有blob
  496. // pathName 所有excel文件名
  497. // zipName zip的包名
  498. // deepIndex 执行ajax下标,当zipOut方法执行完后,再执行allExportF
  499. const that = this;
  500. var zip = new JsZip();
  501. paths.forEach((item, index) => {
  502. const arr_name = item; // 下载文件, 并存成ArrayBuffer对象
  503. const file_name = pathName[index] + ".xlsx"; // 获取文件名
  504. zip.file(file_name, arr_name, {
  505. binary: true,
  506. }); // 逐个添加文件
  507. });
  508. zip
  509. .generateAsync({
  510. type: "blob",
  511. })
  512. .then(function (content) {
  513. // 下载的文件名
  514. var filename = zipName + ".zip";
  515. // 创建隐藏的可下载链接
  516. var eleLink = document.createElement("a");
  517. eleLink.download = filename;
  518. eleLink.style.display = "none";
  519. // 下载内容转变成blob地址
  520. eleLink.href = URL.createObjectURL(content);
  521. // 触发点击
  522. document.body.appendChild(eleLink);
  523. eleLink.click();
  524. // 然后移除
  525. document.body.removeChild(eleLink);
  526. if (deepIndex) {
  527. that.allExportF(deepIndex); //递归,去执行ajax
  528. if (that.stations.length == deepIndex) {
  529. BASE.closeLoading();
  530. }
  531. } else if (that.single) {
  532. BASE.closeLoading();
  533. that.single = false;
  534. }
  535. });
  536. },
  537. },
  538. };
  539. </script>
  540. <style lang="less">
  541. .excelPickerTd input {
  542. flex: 1;
  543. }
  544. .el-date-editor--daterange.mr15 {
  545. border: 1px solid rgba(96, 103, 105, 0.2);
  546. height: 33px;
  547. padding: 0 8px;
  548. width: 369px;
  549. input {
  550. background-color: transparent;
  551. color: white;
  552. }
  553. .el-range-separator {
  554. color: white;
  555. }
  556. }
  557. .com-table td {
  558. color: white !important;
  559. }
  560. .t2 {
  561. top: 2px;
  562. position: relative !important;
  563. }
  564. </style>