diff --git a/src/controller/admin/export_task.js b/src/controller/admin/export_task.js index dfc0425..97380ad 100644 --- a/src/controller/admin/export_task.js +++ b/src/controller/admin/export_task.js @@ -63,12 +63,20 @@ module.exports = class extends Base { // 创建导出任务 async createAction() { - const { file_types, filter_params } = this.post(); + const { file_types, filter_params, scope, patient_ids } = this.post(); if (!file_types || !file_types.length) { return this.fail('请选择要导出的附件类型'); } + const exportScope = scope === 'selected' ? 'selected' : 'filter'; + const selectedIds = Array.isArray(patient_ids) + ? Array.from(new Set(patient_ids.map(id => parseInt(id, 10)).filter(Boolean))) + : []; + if (exportScope === 'selected' && !selectedIds.length) { + return this.fail('请选择要导出的患者'); + } + // 全局只允许一个打包中的任务 const processing = await this.model('export_task').where({ is_deleted: 0, @@ -83,14 +91,20 @@ module.exports = class extends Base { // 构建标题 const typeLabels = { id_photos: '实名认证照片', documents: '上传资料', signs: '签字材料', sample_photos: '送检信息附件' }; - const title = file_types.map(t => typeLabels[t] || t).join('、'); + const fileTypeTitle = file_types.map(t => typeLabels[t] || t).join('、'); + const title = exportScope === 'selected' ? `已选${selectedIds.length}名患者 - ${fileTypeTitle}` : fileTypeTitle; + const baseFilterParams = filter_params && typeof filter_params === 'object' && !Array.isArray(filter_params) ? filter_params : {}; + const exportFilterParams = Object.assign({}, baseFilterParams, { + export_scope: exportScope, + patient_ids: exportScope === 'selected' ? selectedIds : [] + }); const id = await model.add({ task_no: taskNo, title, status: 0, file_types: JSON.stringify(file_types), - filter_params: JSON.stringify(filter_params || {}), + filter_params: JSON.stringify(exportFilterParams), create_by: this.adminUser?.id || 0, create_by_name: this.adminUser?.nickname || this.adminUser?.username || '' }); diff --git a/src/service/export.js b/src/service/export.js index c6db16a..4ef5b2c 100644 --- a/src/service/export.js +++ b/src/service/export.js @@ -61,7 +61,21 @@ module.exports = class extends think.Service { } // 查询患者列表 - const patients = await patientModel.getAll(filterParams); + let patients = []; + const exportScope = filterParams.export_scope === 'selected' ? 'selected' : 'filter'; + if (exportScope === 'selected') { + const patientIds = Array.isArray(filterParams.patient_ids) + ? Array.from(new Set(filterParams.patient_ids.map(id => parseInt(id, 10)).filter(Boolean))) + : []; + if (patientIds.length) { + patients = await patientModel + .where({ id: ['in', patientIds], is_deleted: 0 }) + .order('id DESC') + .select(); + } + } else { + patients = await patientModel.getAll(filterParams); + } if (!patients.length) { await taskModel.where({ id: task.id }).update({ status: 2, diff --git a/view/admin/patient_index.html b/view/admin/patient_index.html index 5be1cb8..2962f24 100644 --- a/view/admin/patient_index.html +++ b/view/admin/patient_index.html @@ -61,7 +61,7 @@ - + @@ -295,7 +295,16 @@ -

将按当前筛选条件导出患者附件,打包为 ZIP 文件。请选择需要导出的附件类型:

+

可按当前筛选条件或已选患者导出附件,打包为 ZIP 文件。

+
+
导出范围
+ + 当前筛选结果(${ pagination.total }人) + 已选患者(${ selectedIds.length }人) + +
仅导出当前页已勾选患者。
+
+
附件类型
实名认证照片(身份证人像面、国徽面、免冠照片) @@ -428,6 +437,7 @@ const app = createApp({ var res = await fetch('/admin/patient/list?' + params).then(function(r) { return r.json(); }); if (res.code === 0) { tableData.value = res.data.data || []; + selectedIds.value = []; pagination.total = res.data.count || 0; if (res.data.counts) Object.assign(counts, res.data.counts); } else { @@ -731,10 +741,12 @@ const app = createApp({ const exportFilesVisible = ref(false); const exportFilesLoading = ref(false); const exportFileTypes = ref(['id_photos', 'documents', 'signs']); + const exportScope = ref('filter'); const exportSuccessVisible = ref(false); function showExportFilesDialog() { exportFileTypes.value = ['id_photos', 'documents', 'signs']; + exportScope.value = selectedIds.value.length ? 'selected' : 'filter'; exportFilesVisible.value = true; } @@ -742,6 +754,9 @@ const app = createApp({ if (!exportFileTypes.value.length) { return ElementPlus.ElMessage.warning('请至少选择一种附件类型'); } + if (exportScope.value === 'selected' && !selectedIds.value.length) { + return ElementPlus.ElMessage.warning('请先勾选要下载附件的患者'); + } exportFilesLoading.value = true; try { var filterObj = { @@ -762,7 +777,9 @@ const app = createApp({ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ file_types: exportFileTypes.value, - filter_params: filterObj + filter_params: filterObj, + scope: exportScope.value, + patient_ids: exportScope.value === 'selected' ? selectedIds.value : [] }) }).then(function(r) { return r.json(); }); @@ -801,7 +818,7 @@ const app = createApp({ uploadHeaders, addVisible, addSaving, addForm, exporting, editingId, perms, selectedIds, regionTree, tagOptions, isMinorComputed, Plus, Download, Delete, sampleReceiverVisible, sampleReceiverSaving, sampleReceiverForm, - exportFilesVisible, exportFilesLoading, exportFileTypes, exportSuccessVisible, + exportFilesVisible, exportFilesLoading, exportFileTypes, exportScope, exportSuccessVisible, loadList, resetFilter, onTabChange, onSizeChange, onSelectionChange, viewDetail, showAddDialog, showEditDialog, handleExport, onIdCardInput, onDocUpload, onSignUpload, submitAdd, handleDelete, handleBatchDelete, showSampleReceiverDialog, saveSampleReceiverConfig, showExportFilesDialog, submitExportFiles, goExportTask