const Base = require('../base.js'); module.exports = class extends Base { // 权限校验:所有操作需要 patient:export 权限 async __before() { const ret = await super.__before(); // 父类已处理(未登录等),直接返回 if (ret === false) return false; // 非页面请求时 loadUserPermissions 未执行,需手动加载 if (this.isAjax() && this.adminUser && !this.userPermissions) { await this.loadUserPermissions(); } const hasPermission = this.isSuperAdmin || (this.userPermissions || []).includes('patient:export'); if (!hasPermission) { if (this.isAjax()) { return this.fail('暂无操作权限'); } return this.redirect('/admin/dashboard.html'); } } // 下载管理页面 async indexAction() { this.assign('currentPage', 'export_task'); this.assign('pageTitle', '下载管理'); this.assign('breadcrumb', [{ name: '下载管理' }]); this.assign('adminUser', this.adminUser || {}); return this.display(); } // 获取任务列表 async listAction() { const { page = 1, pageSize = 10, status } = this.get(); const model = this.model('export_task'); const list = await model.getList({ page, pageSize, status }); return this.success(list); } // 查询单个任务状态(轮询用) async statusAction() { const { id } = this.get(); if (!id) return this.fail('参数错误'); const task = await this.model('export_task') .field('id, task_no, status, total_files, processed_files, file_url, file_size, error_log, finished_at') .where({ id, is_deleted: 0 }) .find(); if (think.isEmpty(task)) return this.fail('任务不存在'); return this.success(task); } // 批量查询任务状态(轮询用) async batchStatusAction() { const { ids } = this.get(); if (!ids) return this.success([]); const idArr = ids.split(',').map(Number).filter(Boolean); if (!idArr.length) return this.success([]); const tasks = await this.model('export_task') .field('id, status, processed_files, total_files, file_url, file_size') .where({ id: ['in', idArr], is_deleted: 0 }) .select(); return this.success(tasks); } // 创建导出任务 async createAction() { const { file_types, filter_params } = this.post(); if (!file_types || !file_types.length) { return this.fail('请选择要导出的附件类型'); } // 全局只允许一个打包中的任务 const processing = await this.model('export_task').where({ is_deleted: 0, status: ['in', [0, 1]] }).find(); if (!think.isEmpty(processing)) { return this.json({ code: 1001, msg: '有任务正在打包中,请稍后再试' }); } const model = this.model('export_task'); const taskNo = model.generateTaskNo(); // 构建标题 const typeLabels = { id_photos: '实名认证照片', documents: '上传资料', signs: '签字材料', sample_photos: '送检信息附件' }; const title = file_types.map(t => typeLabels[t] || t).join('、'); const id = await model.add({ task_no: taskNo, title, status: 0, file_types: JSON.stringify(file_types), filter_params: JSON.stringify(filter_params || {}), create_by: this.adminUser?.id || 0, create_by_name: this.adminUser?.nickname || this.adminUser?.username || '' }); await this.log('export', '下载管理', `创建导出任务「${title}」编号:${taskNo}`); // 触发后台处理 const exportService = this.service('export'); // 异步执行,不等待 setImmediate(() => exportService.startProcessing()); return this.success({ id, task_no: taskNo }); } // 删除任务(软删除) async deleteAction() { const { id } = this.post(); if (!id) return this.fail('参数错误'); const task = await this.model('export_task') .where({ id, is_deleted: 0 }) .find(); if (think.isEmpty(task)) return this.fail('任务不存在'); // 打包中的任务不允许删除 if (task.status === 1) { return this.fail('打包中的任务不能删除'); } await this.model('export_task').where({ id }).update({ is_deleted: 1 }); await this.log('delete', '下载管理', `删除导出任务(${task.task_no})`); return this.success(); } // 重试失败的任务 async retryAction() { const { id } = this.post(); if (!id) return this.fail('参数错误'); const task = await this.model('export_task') .where({ id, is_deleted: 0 }) .find(); if (think.isEmpty(task)) return this.fail('任务不存在'); if (task.status !== 3) return this.fail('只有失败的任务可以重试'); await this.model('export_task').where({ id }).update({ status: 0, error_log: '', started_at: null, finished_at: null, processed_files: 0, total_files: 0, file_url: '', file_size: 0 }); await this.log('edit', '下载管理', `重试导出任务(${task.task_no})`); const exportService = this.service('export'); setImmediate(() => exportService.startProcessing()); return this.success(); } };