|
|
@@ -173,10 +173,7 @@ export default {
|
|
|
},
|
|
|
rules: {
|
|
|
book_name: [{ required: true, message: '请选择教材', trigger: 'blur' }],
|
|
|
- effective_count: [
|
|
|
- { required: true, message: '请填写有效次数', trigger: 'blur' },
|
|
|
- { type: 'number', message: '有效次数必须为数字值' },
|
|
|
- ],
|
|
|
+ effective_count: [{ type: 'number', message: '有效次数必须为数字值' }],
|
|
|
effective_end_date: [{ required: true, message: '请选择有效截止日期', trigger: 'blur' }],
|
|
|
},
|
|
|
tempDir: '', // 临时目录,用于存放下载的文件
|
|
|
@@ -258,6 +255,9 @@ export default {
|
|
|
this.$refs[formName].validate((valid) => {
|
|
|
if (valid) {
|
|
|
let data = this.editForm;
|
|
|
+ if (data.effective_count === undefined || data.effective_count === null) {
|
|
|
+ data.effective_count = 99999;
|
|
|
+ }
|
|
|
this.dialogSearchBook = false;
|
|
|
AddBookOfflinePackAuth(data).then((res) => {
|
|
|
if (res && res.status === 1) {
|
|
|
@@ -330,15 +330,30 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 获取课件名称(用于命名保存目录)
|
|
|
+ await this.resolvePackageName(file_info_list);
|
|
|
+
|
|
|
+ // 在用户选择的保存目录下,新建以课件名称命名的目录作为工作目录
|
|
|
if (this.tempDir.length === 0) {
|
|
|
- this.tempDir = window.fileAPI.createTempDir(); // 创建临时保存目录
|
|
|
+ this.tempDir = `${this.savePath}\\${this.packageName}`;
|
|
|
+ // 若目录已存在(如上次导出失败残留),先清理再重建
|
|
|
+ if (window.fileAPI.existsSync(this.tempDir)) {
|
|
|
+ window.fileAPI.deleteTempDir(this.tempDir);
|
|
|
+ }
|
|
|
+ window.fileAPI.mkdirSync(`${this.tempDir}\\resource`);
|
|
|
+ window.fileAPI.mkdirSync(`${this.tempDir}\\courseware`);
|
|
|
}
|
|
|
|
|
|
this.visible = true;
|
|
|
|
|
|
for (const { dir_name, file_name, file_url } of this.file_info_list) {
|
|
|
const dirPath = dir_name.length > 0 ? `${this.tempDir}\\${dir_name}` : this.tempDir;
|
|
|
- await window.fileAPI.downloadFile(file_url, `${dirPath}\\${file_name}`);
|
|
|
+ try {
|
|
|
+ await window.fileAPI.downloadFile(file_url, `${dirPath}\\${file_name}`);
|
|
|
+ } catch (e) {
|
|
|
+ this.handleDownloadError(e);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const struct = await this.readFileContent('struct.json'); // 读取章节结构文件内容
|
|
|
@@ -371,6 +386,75 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
+ * 解析并设置离线包课件名称
|
|
|
+ * 先下载 struct.json 到系统临时目录读取课件名称,再删除临时目录
|
|
|
+ * @param {Array} file_info_list 章节结构文件列表
|
|
|
+ */
|
|
|
+ async resolvePackageName(file_info_list) {
|
|
|
+ const structFile = file_info_list.find((fileInfo) => fileInfo.file_name === 'struct.json');
|
|
|
+ if (!structFile) return;
|
|
|
+
|
|
|
+ const tmpDir = window.fileAPI.createTempDir('eep-struct-');
|
|
|
+ try {
|
|
|
+ await window.fileAPI.downloadFile(structFile.file_url, `${tmpDir}\\${structFile.file_name}`);
|
|
|
+ const content = window.fileAPI.readZipFileSync(tmpDir, 'struct.json');
|
|
|
+ const text = new TextDecoder().decode(content);
|
|
|
+ const struct = JSON.parse(text);
|
|
|
+ if (struct.node_list && struct.node_list.length > 0) {
|
|
|
+ this.packageName = struct.node_list[0].name;
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('读取课件名称失败:', e);
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ window.fileAPI.deleteTempDir(tmpDir);
|
|
|
+ } catch (e) {
|
|
|
+ console.error('删除临时目录失败:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否为磁盘空间不足错误
|
|
|
+ * @param {Error} e 错误对象
|
|
|
+ * @return {boolean}
|
|
|
+ */
|
|
|
+ isNoSpaceError(e) {
|
|
|
+ if (!e) return false;
|
|
|
+ if (e.code === 'ENOSPC') return true;
|
|
|
+ return /空间不足|ENOSPC|no space|disk full/i.test(e.message || '');
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理下载失败(含磁盘空间不足)
|
|
|
+ * @param {Error} e 错误对象
|
|
|
+ */
|
|
|
+ handleDownloadError(e) {
|
|
|
+ if (this.isNoSpaceError(e)) {
|
|
|
+ this.$message.error('磁盘空间不足,请清理磁盘空间后重试!');
|
|
|
+ } else {
|
|
|
+ console.error('下载失败:', e);
|
|
|
+ this.$message.error('离线包下载失败,请重试!');
|
|
|
+ }
|
|
|
+ this.cleanupWorkDir();
|
|
|
+ this.visible = false;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除工作目录并置空 tempDir
|
|
|
+ */
|
|
|
+ cleanupWorkDir() {
|
|
|
+ if (this.tempDir && this.tempDir.length > 0) {
|
|
|
+ try {
|
|
|
+ window.fileAPI.deleteTempDir(this.tempDir);
|
|
|
+ } catch (e) {
|
|
|
+ console.error('删除工作目录失败:', e);
|
|
|
+ }
|
|
|
+ this.tempDir = '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
* 下载课件文件列表
|
|
|
* @param {Number} courseware_id 课件ID
|
|
|
* @return {Promise} Promise对象
|
|
|
@@ -388,9 +472,14 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- window.fileAPI.downloadFile(file_url, `${this.tempDir}\\${dir_name}\\${file_name}`).then(() => {
|
|
|
- this.downloadCompleted += 1;
|
|
|
- });
|
|
|
+ window.fileAPI
|
|
|
+ .downloadFile(file_url, `${this.tempDir}\\${dir_name}\\${file_name}`)
|
|
|
+ .then(() => {
|
|
|
+ this.downloadCompleted += 1;
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ this.handleDownloadError(e);
|
|
|
+ });
|
|
|
});
|
|
|
},
|
|
|
|
|
|
@@ -421,8 +510,13 @@ export default {
|
|
|
offErr();
|
|
|
} catch (e) {
|
|
|
console.error('压缩失败:', e);
|
|
|
- this.$message.error('离线包下载失败,请重试!');
|
|
|
- this.tempDir = '';
|
|
|
+ if (this.isNoSpaceError(e)) {
|
|
|
+ this.$message.error('磁盘空间不足,请清理磁盘空间后重试!');
|
|
|
+ } else {
|
|
|
+ this.$message.error('离线包下载失败,请重试!');
|
|
|
+ }
|
|
|
+ // 删除工作目录,避免在保存目录下残留中间文件
|
|
|
+ this.cleanupWorkDir();
|
|
|
this.visible = false;
|
|
|
return;
|
|
|
} finally {
|
|
|
@@ -432,7 +526,8 @@ export default {
|
|
|
|
|
|
// 删除临时目录及其内容
|
|
|
try {
|
|
|
- await window.fileAPI.deleteTempDir(this.tempDir);
|
|
|
+ // 用于测试:压缩成功后保留工作目录
|
|
|
+ // await window.fileAPI.deleteTempDir(this.tempDir);
|
|
|
this.tempDir = '';
|
|
|
} catch (e) {
|
|
|
console.error('删除临时目录失败:', e);
|