import axios from "@/axios"; export function generateLessonPlan(studentId, unitId) { return axios.post('/plan/generate', { studentId: studentId, unitId: unitId }) } export function downloadLessonPlan(data) { return axios.post('/plan/download', data, { // 1. 重要:必须指定响应类型为 blob,否则下载的文件会损坏(乱码) responseType: 'blob', headers: { 'Content-Type': 'application/json; application/octet-stream' // 根据需要调整 } }).then(response => { // 2. 提取文件名 (处理后端设置的 Content-Disposition) // 后端示例: header("Content-Disposition", "attachment; filename*=UTF-8''" + fileName) let fileName = 'download.zip'; // 默认兜底文件名 const contentDisposition = response.headers['content-disposition']; if (contentDisposition) { // 正则提取 filename*=utf-8''xxx.zip 或 filename="xxx.zip" const fileNameMatch = contentDisposition.match(/filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']*)['"]?;?/); if (fileNameMatch && fileNameMatch[1]) { // 后端如果用了 URLEncoder,这里需要 decode fileName = decodeURIComponent(fileNameMatch[1]); } } // 3. 开始下载流程 resolveBlob(response.data, fileName); }).catch(error => { console.error('下载失败', error); showMessage('下载失败' + error, 'error'); // 注意:如果后端报错返回 JSON,因为 responseType 是 blob, // 这里看到的 error.response.data 也是 blob,需要转回文本才能看到错误信息 const reader = new FileReader(); reader.readAsText(error.response.data); reader.onload = () => { console.log(JSON.parse(reader.result)); // 打印后端实际报错 } }); } const resolveBlob = (res, fileName) => { // 创建 Blob 对象,可以指定 type,也可以让浏览器自动推断 const blob = new Blob([res], { type: 'application/octet-stream' }); // 兼容 IE/Edge (虽然现在很少用了) if (window.navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob, fileName); } else { // 创建一个临时的 URL 指向 Blob const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = fileName; // 触发点击 link.style.display = 'none'; document.body.appendChild(link); link.click(); // 清理资源 document.body.removeChild(link); window.URL.revokeObjectURL(link.href); } };