ExportExcel.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <div class="ExportExcel">
  3. <el-row style="margin-bottom: 15px;padding-bottom: 15px;border-bottom: 2px solid #EEE8D5;">
  4. <el-col :span="12">
  5. <button class="btn" :class="templateId == 1?'green':''" @click="typeClick(1)">单机数据模板</button>
  6. <button class="btn" :class="templateId == 2?'green':''" @click="typeClick(2)">上网电量及功率、测风塔数据模板</button>
  7. </el-col>
  8. <el-col :span="12">
  9. <el-row justify="end">
  10. <button class="btn green" @click="allExport()">一键导出</button>
  11. </el-row>
  12. </el-col>
  13. </el-row>
  14. <table class="com-table">
  15. <thead>
  16. <tr>
  17. <th>
  18. 场站
  19. </th>
  20. <th>
  21. <input class='t2' type='checkbox' @click="rqCheck" checked='checked'/>
  22. 日期
  23. </th>
  24. <th>
  25. <input class='t2' type='checkbox' @click="sjCheck" checked='checked'/>
  26. 时间间隔(s)
  27. </th>
  28. <th width="120px">
  29. 操作
  30. </th>
  31. </tr>
  32. </thead>
  33. <el-scrollbar>
  34. <tbody>
  35. <tr v-for="(row, index) of tableData" :key="index">
  36. <td>
  37. {{row.fdc}}
  38. </td>
  39. <td class="excelPickerTd">
  40. <el-date-picker v-model="value1[index]" type="daterange" @change='value1Change(index)' range-separator="至"
  41. start-placeholder="开始日期" end-placeholder="结束日期" class="mr15">
  42. </el-date-picker>
  43. </td>
  44. <td>
  45. <el-input placeholder="请输入时间间隔" type='number' v-model="inputVal[index]" @change='inputValChange(index)'></el-input>
  46. </td>
  47. <td width="120px">
  48. <el-button type='text' style='cursor: pointer;' @click="thisExport(index)">导出
  49. </el-button>
  50. </td>
  51. </tr>
  52. </tbody>
  53. </el-scrollbar>
  54. </table>
  55. </div>
  56. </template>
  57. <script>
  58. import JsZip from 'jszip';
  59. import {
  60. export_blob,
  61. export_more_blob
  62. } from "@tools/excel/Export2Excel.js";
  63. import BASE from "@tools/basicTool.js";
  64. export default {
  65. components: {
  66. JsZip
  67. },
  68. data() {
  69. const that = this;
  70. return {
  71. single:false,//单击导出状态【点击后,用于判断其状态,为true时,loading显示】
  72. rqChecked:true,//日期单击checkbox状态【为true时,下方任意日期选择与当前选择同步】
  73. sjChecked:true,//时间间隔checkbox状态【为true时,下方任意时间选择与当前选择同步】
  74. tableData: [],//表格数据
  75. value1: [],//日期数组,默认一个月的,当用户改变某一个时,找到对应下标去改数据
  76. inputVal: [],//时间同上
  77. startTs: [],//起始时间,通过下标去找对应的时间
  78. endTs: [],//结束时间
  79. muBan: {
  80. type1: ['数据时间', 'scada风速(m/s)', 'scada功率(kW)', '是否故障(故障=1,不故障=0)', '是否限电(限电=1,不限电=0)'],
  81. type2: [
  82. ['数据时间', '日报上网电量(mWh)'],
  83. ['数据时间', '上网功率(kW)'],
  84. ['数据时间', '轮毂高度平均风速(m/s)', '轮毂高度平均风向(°)', '温度(℃)', '压强(hPa)', '湿度(%)']
  85. ],
  86. },
  87. templateId: 1,//模板默认为1
  88. stations: [],//场站名
  89. paths: [],//excel的所有数据,最终给zip传
  90. pathName: [],//excel的名字
  91. zipNames: [],
  92. tempArrayS: [],//模板2时,遍历里面的数据
  93. }
  94. },
  95. created() {
  96. this.tableVal();
  97. },
  98. methods: {
  99. value1Change(index){//日期数组,默认一个月的,当用户改变某一个时,找到对应下标去改数据
  100. if(this.rqChecked){
  101. var date = this.value1[index];
  102. this.value1 = [];
  103. this.tableData.forEach((ele, index) => {
  104. this.value1.push(date);
  105. this.time(index, date);
  106. })
  107. }
  108. },
  109. inputValChange(index){
  110. if(this.sjChecked){
  111. var sj = this.inputVal[index];
  112. this.inputVal = [];
  113. this.tableData.forEach((ele, index) => {
  114. this.inputVal.push(sj);
  115. })
  116. }
  117. },
  118. rqCheck(){
  119. this.rqChecked=event.target.checked
  120. },
  121. sjCheck(){
  122. this.sjChecked=event.target.checked
  123. },
  124. typeClick(a){//模板切换,改变按钮颜色
  125. this.templateId = a;
  126. },
  127. thisExport(index) {//当前导出,index为下标
  128. let that = this;
  129. that.single = true;
  130. // 下面的是通过下标找到对应的数据,请求ajax
  131. that.time(index, that.value1[index]);
  132. that.stations[index] = that.tableData[index].value;
  133. that.allExportF(0, index);
  134. },
  135. tableVal() {
  136. let that = this;
  137. that.API.requestData({
  138. method: "GET",
  139. subUrl: "export/databases",
  140. success(res) {
  141. if (res.code === 200) {
  142. const arr3 = [];
  143. const arr4 = [];
  144. var data = []; //项目列表
  145. res.data.forEach((item,index) => {
  146. const value = Object.keys(item)[0];
  147. arr3.push(value);
  148. arr4.push(item[value]);
  149. data.push({
  150. fdc: item[value],
  151. value: value,
  152. });
  153. that.inputVal.push(1800);
  154. })
  155. that.stations = arr3;
  156. that.zipNames = arr4;
  157. that.tableData = data;
  158. that.defaultValue1();
  159. }
  160. },
  161. });
  162. },
  163. defaultValue1() { //默认时间区间
  164. const end = new Date();
  165. const start = new Date();
  166. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
  167. /////////////
  168. var nowDate = new Date();
  169. var year = nowDate.getFullYear();
  170. var month = nowDate.getMonth();
  171. var day = nowDate.getDate();
  172. this.tableData.forEach((ele, index) => {
  173. this.value1.push([start, end]);
  174. this.time(index, [start, end]);
  175. })
  176. },
  177. formatJson(filterVal, jsonData) {//模板1时,转数据格式
  178. return jsonData.map(v => filterVal.map(j => v[j]));
  179. },
  180. allExport() {//一键导出
  181. this.allExportF(0);
  182. },
  183. allExportF(_index, thisIndex) {//_index递归递增,thisIndex单击导出【下标】
  184. BASE.showLoading({text:'正在导出,请耐心等待...'});
  185. const that = this;
  186. if (that.stations[_index]) {
  187. that.API.requestData({
  188. method: "GET",
  189. subUrl: "export/history/all",
  190. data: {
  191. templateId: that.templateId,
  192. startTs: thisIndex!=undefined ? that.startTs[thisIndex] : that.startTs[_index],
  193. endTs: thisIndex!=undefined ? that.endTs[thisIndex] + 86400000 : that.endTs[_index] + 86400000,
  194. interval: thisIndex!=undefined ? that.inputVal[thisIndex] : that.inputVal[_index],
  195. station: thisIndex!=undefined ? that.stations[thisIndex] : that.stations[_index]
  196. },
  197. success(res) {
  198. if (res.code == 200) {
  199. if (thisIndex!=undefined) {//单击导出
  200. if (that.templateId == 1) {//模板1
  201. that.export(res.data, 0, that.zipNames[thisIndex]);
  202. } else if (that.templateId == 2) {//模板2
  203. that.exportMuban2(res.data, 0, that.zipNames[thisIndex]);
  204. }
  205. } else {//一键导出
  206. if (that.templateId == 1) {
  207. that.export(res.data, 0, that.zipNames[_index], ++_index);
  208. } else if (that.templateId == 2) {
  209. that.exportMuban2(res.data, 0, that.zipNames[_index], ++_index);
  210. }
  211. }
  212. }
  213. }
  214. });
  215. }
  216. },
  217. export (data, _index, zipName, deepIndex) {
  218. // deepIndex判断单击或一键
  219. const that = this;
  220. let tHeader = that.muBan['type' + that.templateId];
  221. var dataKey = Object.keys(data);
  222. var key = dataKey[_index];
  223. if (key) {
  224. let tempObject = {};
  225. let tempArray = [];
  226. const dataLength = data[key].length;
  227. let filterVal = [];
  228. data[key][0].forEach((pEle, pIndex) => {
  229. for (let i = 0; i < dataLength; i++) {
  230. tempObject[String(i)] = data[key][i][pIndex];
  231. }
  232. tempArray.push(tempObject)
  233. tempObject = {};
  234. })
  235. data[key][0].forEach((ele, index) => {
  236. filterVal.push(index);
  237. });
  238. that.paths.push(export_blob(tHeader, that.formatJson(filterVal, tempArray))); //传blob
  239. var str = key.split('_');
  240. that.pathName.push(str[0].substring(0,2)+str[1]); //excel的名字
  241. _index++;
  242. if (deepIndex!=undefined) {
  243. setTimeout(() => {
  244. that.export(data, _index, zipName, deepIndex);
  245. }, 500);
  246. if (dataKey.length == _index) { //当长度一致时,向zip塞值
  247. var thisPath = that.paths,
  248. thisPathName = that.pathName;
  249. that.paths = [];
  250. that.pathName = [];
  251. that.zipOut(thisPath, thisPathName, zipName, deepIndex)
  252. }
  253. } else {
  254. setTimeout(() => {
  255. that.export(data, _index, zipName);
  256. }, 500);
  257. if (dataKey.length == _index) { //当长度一致时,向zip塞值
  258. var thisPath = that.paths,
  259. thisPathName = that.pathName;
  260. that.paths = [];
  261. that.pathName = [];
  262. that.zipOut(thisPath, thisPathName, zipName)
  263. }
  264. }
  265. }
  266. },
  267. exportMuban2(data, _index, excelName, deepIndex) {
  268. const that = this;
  269. var dataKey = Object.keys(data);
  270. let tHeader = that.muBan['type' + that.templateId];
  271. var key = dataKey[_index];
  272. if (key) {
  273. let tempObject = {};
  274. let tempArray = [];
  275. const dataLength = data[key].length;
  276. data[key][0].forEach((pEle, pIndex) => {
  277. for (let i = 0; i < dataLength; i++) {
  278. tempObject[String(i)] = data[key][i][pIndex];
  279. }
  280. tempArray.push(tempObject)
  281. tempObject = {};
  282. })
  283. that.tempArrayS.push(tempArray);
  284. _index++;
  285. if (dataKey.length == that.tempArrayS.length) {
  286. let obj = [];
  287. that.tempArrayS.forEach((ele, index) => {
  288. obj[index] = [];
  289. ele.forEach((ele2, index2) => {
  290. var key = Object.keys(ele2)
  291. var arr = [];
  292. key.forEach((ele3, index3) => {
  293. arr.push(ele2[ele3])
  294. })
  295. obj[index][index2] = arr;
  296. arr = [];
  297. })
  298. })
  299. if (deepIndex!=undefined) {
  300. that.paths.push(export_more_blob(tHeader, obj)); //传blob
  301. that.pathName.push(excelName); //excel的名字
  302. that.tempArrayS = [];
  303. that.allExportF(deepIndex);
  304. } else {
  305. that.paths.push(export_more_blob(tHeader, obj, excelName)); //只渲染一个excel
  306. BASE.closeLoading();
  307. }
  308. }
  309. if (deepIndex!=undefined) {
  310. that.exportMuban2(data, _index, excelName, deepIndex);
  311. if (that.stations.length == deepIndex && _index == 1) { //当长度一致时,向zip塞值,_index只让执行第一次
  312. var thisPath = that.paths,
  313. thisPathName = that.pathName;
  314. that.tempArrayS = [];
  315. that.paths = [];
  316. that.pathName = [];
  317. that.zipOut(thisPath, thisPathName, '风电场_上网电量&功率&测风塔数据')
  318. BASE.closeLoading();
  319. }
  320. }else{
  321. that.exportMuban2(data, _index, excelName);
  322. if (that.stations.length && _index == 1) { //当长度一致时,向zip塞值,_index只让执行第一次
  323. var thisPath = that.paths,
  324. thisPathName = that.pathName;
  325. that.tempArrayS = [];
  326. that.paths = [];
  327. that.pathName = [];
  328. BASE.closeLoading();
  329. }
  330. }
  331. }
  332. },
  333. zipOut(paths, pathName, zipName, deepIndex) {
  334. // paths 所有blob
  335. // pathName 所有excel文件名
  336. // zipName zip的包名
  337. // deepIndex 执行ajax下标,当zipOut方法执行完后,再执行allExportF
  338. const that = this;
  339. var zip = new JsZip();
  340. paths.forEach((item, index) => {
  341. const arr_name = item // 下载文件, 并存成ArrayBuffer对象
  342. const file_name = pathName[index] + '.xlsx' // 获取文件名
  343. zip.file(file_name, arr_name, {
  344. binary: true
  345. }) // 逐个添加文件
  346. })
  347. zip.generateAsync({
  348. type: 'blob',
  349. })
  350. .then(function(content) {
  351. // 下载的文件名
  352. var filename = zipName + '.zip'
  353. // 创建隐藏的可下载链接
  354. var eleLink = document.createElement('a')
  355. eleLink.download = filename
  356. eleLink.style.display = 'none'
  357. // 下载内容转变成blob地址
  358. eleLink.href = URL.createObjectURL(content)
  359. // 触发点击
  360. document.body.appendChild(eleLink)
  361. eleLink.click()
  362. // 然后移除
  363. document.body.removeChild(eleLink)
  364. if (deepIndex) {
  365. that.allExportF(deepIndex); //递归,去执行ajax
  366. if(that.stations.length == deepIndex){
  367. BASE.closeLoading();
  368. }
  369. }else if(that.single){
  370. BASE.closeLoading();
  371. that.single = false;
  372. }
  373. })
  374. },
  375. time(index, val) {//时间转时间戳
  376. this.startTs[index] = Date.parse(new Date(val[0]));
  377. this.endTs[index] = Date.parse(new Date(val[1]) + 86400000);
  378. },
  379. },
  380. }
  381. </script>
  382. <style lang="less">
  383. .excelPickerTd input {
  384. flex: 1;
  385. }
  386. .el-date-editor--daterange.mr15{
  387. border: 1px solid rgba(96, 103, 105, 0.2);
  388. height: 33px;
  389. padding: 0 8px;
  390. width: 369px;
  391. input{
  392. background-color: transparent;
  393. color: white;
  394. }
  395. .el-range-separator{
  396. color: white;
  397. }
  398. }
  399. .com-table td{
  400. color: white !important;
  401. }
  402. .t2{top: 2px;position: relative !important;}
  403. </style>