Sfoglia il codice sorgente

添加授课关系的批量导出调用

lm 1 mese fa
parent
commit
23a9a8879c

File diff suppressed because it is too large
+ 811 - 3
package-lock.json


+ 1 - 0
package.json

@@ -17,6 +17,7 @@
     "@vue-office/excel": "^1.7.14",
     "axios": "^1.9.0",
     "echarts": "^6.0.0",
+    "exceljs": "^4.4.0",
     "element-plus": "^2.9.11",
     "jsencrypt": "^3.5.4",
     "lodash": "^4.17.21",

+ 174 - 2
src/views/reviewManagement/stepComponent/teachingRelationshipComponent/TeachingRelationshipComponent.vue

@@ -29,7 +29,7 @@
             </div>
             <div class="content_right">
               <el-button class="delete_button_border_no_bg" @click="ClearTeachingRelationship">清空授课</el-button>
-              <el-button class="button_refresh">批量导出</el-button>
+              <el-button class="button_refresh" @click="HandleExportExcel">批量导出</el-button>
               <el-button class="button_refresh">批量导入</el-button>
               <el-button class="button_background" @click="FinishTeachingRelationship">完成</el-button>
             </div>
@@ -142,9 +142,12 @@
 
 <script setup lang="ts">
 import { ref, reactive, onMounted } from 'vue';
-import { useRoute } from 'vue-router';
+import { ErrorTypes, useRoute } from 'vue-router';
 import { useStore } from 'vuex';
 
+import ExcelJS from 'exceljs';
+
+
 import { Close } from '@element-plus/icons-vue';
 import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
 import Table from '@/baseComponents/Table.vue';
@@ -516,6 +519,175 @@ const ClearTeachingRelationship = async ()=>{
   }
 }
 
+// 批量导入/导出
+
+//前端 导出 Excel
+const LoopAddSheet=(finalTableColumn, finalTableData,workbook,sheetName )=>{
+  // 1. 提取表头
+  // 行政班和教学班不一样
+  let headers = []               // 行政班表头数据
+  let topHeaders:any[] = []      // 教学班 表头数据
+  let bottomHeaders:any[] = []   // 教学班 子表头数据
+
+  // 2.创建工作表
+  const worksheet = workbook.addWorksheet(sheetName);
+
+  // 3. 添加表头行
+  let headerRow
+  let subHeaderRow
+  
+  if(sheetName == '行政班'){
+    headers = finalTableColumn.map(column => column.label || column.name)
+    // 行政班:普通表头
+    headerRow = worksheet.addRow(headers)
+    // 定义表头样式
+    headerRow.eachCell((cell) => {
+      cell.style = {
+        font: { name: 'Microsoft YaHei', size: 12, bold: true, color: { argb: 'FF333333' } },
+        fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF4F6F8' } },
+        border: {
+          top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+        },
+        alignment: { vertical: 'middle', horizontal: 'left', wrapText: true },
+      }
+    })
+
+  }else if(sheetName == '教学班'){
+    finalTableColumn.forEach(column => {
+      topHeaders.push(column.label || column.name)
+      topHeaders.push('') // 占位,用于合并
+      bottomHeaders.push('班级')
+      bottomHeaders.push('教师')
+    })
+    
+    // 添加第一层表头
+    headerRow = worksheet.addRow(topHeaders)
+    // 添加第二层表头
+    subHeaderRow = worksheet.addRow(bottomHeaders)
+    
+    // 定义第一层表头样式
+    headerRow.eachCell((cell) => {
+      cell.style = {
+        font: { name: 'Microsoft YaHei', size: 12, bold: true, color: { argb: 'FF333333' } },
+        fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF4F6F8' } },
+        border: {
+          top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+        },
+        alignment: { vertical: 'middle', horizontal: 'center', wrapText: true },
+      }
+    })
+    
+    // 定义第二层表头样式
+    subHeaderRow.eachCell((cell) => {
+      cell.style = {
+        font: { name: 'Microsoft YaHei', size: 11, bold: true, color: { argb: 'FF333333' } },
+        fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF9FAFB' } },
+        border: {
+          top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+        },
+        alignment: { vertical: 'middle', horizontal: 'center', wrapText: true },
+      }
+    })
+  }
+
+  // 4. 添加数据行
+  // 行政班  和 教学班 不一样
+  finalTableData.forEach(row => {
+    const rowData = finalTableColumn.map(column => {
+      if (column.name === 'className') {
+        return row?.className?.className || '';
+      }
+      const cellValue = row[column.name];
+      if(sheetName == '行政班'){
+        return cellValue?.map((item: any) => item.teacherName || '').join(',') || '-';
+      }else if(sheetName == '教学班'){
+        let className = cellValue.className.className
+        let teacherList = cellValue.teacherList
+        let teacherName = teacherList.map((item: any) => item.teacherName || '').join(',') || '-';
+        return [className,teacherName]
+      }
+    }).flat();
+
+    const excelRow = worksheet.addRow(rowData);
+
+    // 6. 定义数据行样式
+    excelRow.eachCell({ includeEmpty: true }, (cell) => {
+      cell.style = {
+        font: { name: 'Microsoft YaHei', size: 12, color: { argb: 'FF333333' } },
+        border: {
+          top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+          right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
+        },
+        alignment: { vertical: 'top', horizontal: 'left', wrapText: true },
+      };
+    });
+  });
+
+  // 5. 设置列宽
+  if(sheetName == '行政班'){
+    worksheet.columns = headers.map(() => ({ width: 25 }));
+  }else if(sheetName == '教学班'){
+    worksheet.columns = bottomHeaders.map(() => ({ width: 25 }));
+    //放到最后合并 合并第一层表头的两列,放到设置列表前面,合并头的 宽度会缩小
+    let colIndex = 1
+    finalTableColumn.forEach(() => {
+      worksheet.mergeCells(1, colIndex, 1, colIndex + 1)
+      colIndex += 2
+    })
+  }
+}
+
+const HandleExportExcel = async () => {
+  // 1. 初始化sheet列表
+  let sheetList = [
+    {
+      tableColumn:filterAdministrativeClassTableColumns.value,
+      tableData:administrativeClassTableData.value,
+      sheetName:'行政班'
+    },
+    {
+      tableColumn:filterTeachingClassTableColumns.value,
+      tableData:teachingClassTableData.value,
+      sheetName:'教学班'
+    },
+  ]
+  // 2. 创建工作簿
+  const workbook = new ExcelJS.Workbook();
+
+  // 3. 添加sheet表
+  sheetList.forEach(item=>{
+    LoopAddSheet(item.tableColumn,item.tableData,workbook,item.sheetName)
+  })
+
+  // 4. 导出文件
+  const buffer = await workbook.xlsx.writeBuffer();
+  const blob = new Blob([buffer], { 
+    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 
+  });
+  
+  const url = URL.createObjectURL(blob);
+  const link = document.createElement('a');
+  link.href = url;
+  link.download = `授课关系表_${new Date().toISOString().slice(0, 10)}.xlsx`;
+  link.style.visibility = 'hidden';
+  document.body.appendChild(link);
+  link.click();
+  document.body.removeChild(link);
+  URL.revokeObjectURL(url);
+};
+
+
 // 重新加载页面数据
 const reloadData =async ()=>{
    await GetTeacherTableData()

Some files were not shown because too many files changed in this diff