students-change-excel.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <template>
  2. <el-popover placement="top-start" title="表格批量替换" width="280" trigger="hover">
  3. <view>
  4. 下载当前座位表格模板,更改后点击表格导入批量替换座位
  5. <view class="txt-red">请确保表格格式完整,切勿存在缺漏或重复</view>
  6. <view class="ui-flex-row ui-flex-center ui-mt20">
  7. <el-button type="" plain class="ui-mr20" @click="makeExcelFile">下载模板</el-button>
  8. <el-upload class="upload-demo" action="#" :before-upload="()=>{return false}" :auto-upload="false"
  9. :on-change="onStuChangeByExcel" :file-list="fileList">
  10. <!-- @click="onStuChangeByExcel" -->
  11. <el-button type="primary" plain>上传导入</el-button>
  12. </el-upload>
  13. </view>
  14. </view>
  15. <text slot="reference" class="txt-link">表格导入</text>
  16. </el-popover>
  17. </template>
  18. <script>
  19. import xlsx from '@/common/xlsx.core.min.js'
  20. export default {
  21. data() {
  22. return {
  23. fileList: [] //excel上传的数据
  24. }
  25. },
  26. props: {
  27. stuList: Array
  28. },
  29. methods: {
  30. makeExcelFile() { //下载表格模板
  31. let title = ['1组', '2组', '3组', '4组', '5组', '6组', '7组', '8组'];
  32. let list = [];
  33. this.stuList.forEach((item, index) => {
  34. item.nodes.forEach((el, ii) => {
  35. if (el.id) {
  36. if (!list[ii]) {
  37. list[ii] = [];
  38. }
  39. list[ii][index] = el.title;
  40. }
  41. })
  42. })
  43. list = [title].concat(list);
  44. console.log(list);
  45. // return;
  46. var sheet = xlsx.utils.aoa_to_sheet(list);
  47. this.openDownloadDialog(this.sheet2blob(sheet), '导出座位表.xlsx');
  48. },
  49. // 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
  50. sheet2blob(sheet, sheetName) {
  51. sheetName = sheetName || 'sheet1';
  52. var workbook = {
  53. SheetNames: [sheetName],
  54. Sheets: {}
  55. };
  56. workbook.Sheets[sheetName] = sheet;
  57. // 生成excel的配置项
  58. var wopts = {
  59. bookType: 'xlsx', // 要生成的文件类型
  60. bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
  61. type: 'binary'
  62. };
  63. var wbout = xlsx.write(workbook, wopts);
  64. var blob = new Blob([s2ab(wbout)], {
  65. type: "application/octet-stream"
  66. });
  67. // 字符串转ArrayBuffer
  68. function s2ab(s) {
  69. var buf = new ArrayBuffer(s.length);
  70. var view = new Uint8Array(buf);
  71. for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  72. return buf;
  73. }
  74. return blob;
  75. },
  76. openDownloadDialog(url, saveName) {
  77. if (typeof url == 'object' && url instanceof Blob) {
  78. url = URL.createObjectURL(url); // 创建blob地址
  79. }
  80. var aLink = document.createElement('a');
  81. aLink.href = url;
  82. aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  83. var event;
  84. if (window.MouseEvent) event = new MouseEvent('click');
  85. else {
  86. event = document.createEvent('MouseEvents');
  87. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0,
  88. null);
  89. }
  90. aLink.dispatchEvent(event);
  91. },
  92. stuLength(){
  93. let count = 0;
  94. this.stuList.forEach(item => {
  95. item.nodes.forEach(el => {
  96. if(el.id){
  97. count ++;
  98. }
  99. })
  100. })
  101. return count;
  102. },
  103. onStuChangeByExcel(e) {
  104. let fileRaw = e.raw;
  105. this.fileList = [];
  106. var reader = new FileReader();
  107. reader.onload = (e) => {
  108. var data = e.target.result;
  109. var workbook = xlsx.read(data, {
  110. type: 'binary'
  111. });
  112. console.log(workbook)
  113. var sheetNames = workbook.SheetNames; // 工作表名称集合
  114. var worksheet = workbook.Sheets[sheetNames[0]]; // 这里我们只读取第一张sheet
  115. var csv = xlsx.utils.sheet_to_csv(worksheet);
  116. console.log(csv);
  117. let json = csv.split("\n").map(item => {
  118. return item.split(',');
  119. })
  120. let header = json[0];
  121. json.splice(0,1);
  122. console.log(json);
  123. // console.log(json, xlsx.utils.sheet_to_json(worksheet));
  124. // return;
  125. let list = [];
  126. let maxLen = json.length;
  127. let insertList = []; //插入判断用于判断是否有重复的名字
  128. let error = null;
  129. json.forEach((item, index) => {
  130. item = Object.values(item);
  131. item.forEach((name, ii) => {
  132. if (name) {
  133. if(insertList.includes(name)){
  134. error = name + '学生异常';
  135. }
  136. insertList.push(name);
  137. if (!list[ii]) {
  138. list[ii] = {
  139. id: ii + 1,
  140. title: header[ii],
  141. nodes: []
  142. };
  143. }
  144. list[ii].nodes[index] = name;
  145. }
  146. })
  147. });
  148. if (error) {
  149. this.$alert(error, '表格异常', {
  150. confirmButtonText: '确定',
  151. });
  152. return;
  153. }
  154. if(insertList.length != this.stuLength()){
  155. this.$alert('表格中人数异常,请检查', '表格异常', {
  156. confirmButtonText: '确定',
  157. });
  158. return;
  159. }
  160. list.forEach((item, index) => {
  161. item.nodes.forEach((name, ii) => {
  162. list[index].nodes[ii] = this.findStuItem(name);
  163. })
  164. });
  165. list = Object.values(list);
  166. console.log(list)
  167. this.$emit('change', uni.$u.deepClone(list))
  168. };
  169. reader.readAsBinaryString(fileRaw);
  170. },
  171. findStuItem(name) {
  172. let findOne = null;
  173. this.stuList.some(item => {
  174. return item.nodes.some(el => {
  175. if (el.title == name) {
  176. findOne = el;
  177. }
  178. return !!findOne;
  179. })
  180. })
  181. return findOne;
  182. },
  183. }
  184. }
  185. </script>
  186. <style>
  187. </style>