| | |
| | | prop="organizerName" |
| | | label="组织者" |
| | | width="120" |
| | | /> |
| | | ><template #default="scope"> |
| | | <span>{{ scope.organizerName || scope.createBy }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | align="center" |
| | | prop="locationName" |
| | |
| | | </div> |
| | | |
| | | <!-- 会议纪要附件展示 --> |
| | | <div class="detail-attachments"> |
| | | <div |
| | | class="minutes-attachments" |
| | | v-if=" |
| | | currentRecord.recordattachment && |
| | | parseAttachments(currentRecord.recordattachment).length > 0 |
| | | " |
| | | v-if="parseAttachments(currentRecord.recordattachment).length > 0" |
| | | class="attachment-grid" |
| | | > |
| | | <el-divider content-position="left">会议纪要附件</el-divider> |
| | | <div class="attachment-list"> |
| | | <div |
| | | v-for="file in parseAttachments(currentRecord.recordattachment)" |
| | | :key="file.id || file.name" |
| | | class="attachment-item" |
| | | class="attachment-card" |
| | | > |
| | | <el-link |
| | | type="primary" |
| | | :href="file.url" |
| | | target="_blank" |
| | | class="file-link" |
| | | <template v-if="isImageFile(file)"> |
| | | <!-- 图片使用 el-image 预览 --> |
| | | <el-image |
| | | class="image-attachment" |
| | | :src="getFileUrl(file)" |
| | | :preview-src-list="getImagePreviewList(file)" |
| | | fit="cover" |
| | | :style="{ width: imageSize, height: imageSize }" |
| | | lazy |
| | | > |
| | | <div slot="error" class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | <span>加载失败</span> |
| | | </div> |
| | | <div slot="placeholder" class="image-loading"> |
| | | <i class="el-icon-loading"></i> |
| | | </div> |
| | | </el-image> |
| | | <div class="image-info"> |
| | | <div class="file-name" :title="file.name"> |
| | | {{ file.name }} |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | icon="el-icon-download" |
| | | title="下载" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | icon="el-icon-view" |
| | | title="预览" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <!-- 非图片文件保持原有样式 --> |
| | | <el-card shadow="hover" class="file-card"> |
| | | <div class="file-content"> |
| | | <i |
| | | :class="getFileIcon(file.type || file.name)" |
| | | style="margin-right: 8px;" |
| | | class="file-icon" |
| | | ></i> |
| | | <div class="file-info"> |
| | | <div class="file-name" :title="file.name"> |
| | | {{ file.name }} |
| | | <span class="file-size" v-if="file.size" |
| | | >({{ formatFileSize(file.size) }})</span |
| | | </div> |
| | | <div class="file-meta"> |
| | | <span class="file-type">{{ |
| | | getFileTypeText(file) |
| | | }}</span> |
| | | <span class="file-size" v-if="file.size"> |
| | | {{ formatFileSize(file.size) }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="file-actions" v-if="file.url"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | > |
| | | </el-link> |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="canPreview(file)" |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </el-descriptions-item> |
| | | |
| | | <!-- 会议附件 --> |
| | | 我理解您的需求,您希望将会议附件中的图片文件以el-image的预览图形式展示,其他文件类型保持原有的展示方式。让我修改这部分代码: |
| | | <el-descriptions-item label="会议附件" :span="2"> |
| | | <div class="detail-attachments"> |
| | | <div |
| | |
| | | " |
| | | class="attachment-grid" |
| | | > |
| | | <!-- 图片附件 - 使用 el-image 预览形式 --> |
| | | <div |
| | | v-for="file in parseAttachments(currentRecord.attachment)" |
| | | :key="file.id || file.name" |
| | | class="attachment-card" |
| | | > |
| | | <template v-if="isImageFile(file)"> |
| | | <!-- 图片使用 el-image 预览 --> |
| | | <el-image |
| | | class="image-attachment" |
| | | :src="getFileUrl(file)" |
| | | :preview-src-list="getImagePreviewList(file)" |
| | | fit="cover" |
| | | :style="{ width: imageSize, height: imageSize }" |
| | | lazy |
| | | > |
| | | <div slot="error" class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | <span>加载失败</span> |
| | | </div> |
| | | <div slot="placeholder" class="image-loading"> |
| | | <i class="el-icon-loading"></i> |
| | | </div> |
| | | </el-image> |
| | | <div class="image-info"> |
| | | <div class="file-name" :title="file.name"> |
| | | {{ file.name }} |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | icon="el-icon-download" |
| | | title="下载" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | icon="el-icon-view" |
| | | title="预览" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <!-- 非图片文件保持原有样式 --> |
| | | <el-card shadow="hover" class="file-card"> |
| | | <div class="file-content"> |
| | | <i |
| | |
| | | {{ file.name }} |
| | | </div> |
| | | <div class="file-meta"> |
| | | <span class="file-size" v-if="file.size">{{ |
| | | formatFileSize(file.size) |
| | | <span class="file-type">{{ |
| | | getFileTypeText(file) |
| | | }}</span> |
| | | <span class="file-size" v-if="file.size"> |
| | | {{ formatFileSize(file.size) }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | >下载</el-button |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="canPreview(file)" |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | <div v-else class="no-attachment"> |
| | |
| | | <el-dialog |
| | | :title="`${isEditing ? '编辑' : '新增'}会议`" |
| | | :visible.sync="editDialogVisible" |
| | | width="700px" |
| | | width="800px" |
| | | :before-close="handleEditClose" |
| | | > |
| | | <el-form |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="会议地点" prop="locationId"> |
| | | <el-form-item label="会议地点" prop="locationName"> |
| | | <el-select |
| | | v-model="editForm.locationId" |
| | | v-model="editForm.locationName" |
| | | placeholder="请选择会议地点" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="第一会议室" :value="1" /> |
| | | <el-option label="第二会议室" :value="2" /> |
| | | <el-option label="第三会议室" :value="3" /> |
| | | <el-option label="线上会议" :value="4" /> |
| | | <el-option label="第一会议室" value="第一会议室" /> |
| | | <el-option label="第二会议室" value="第二会议室" /> |
| | | <el-option label="第三会议室" value="第三会议室" /> |
| | | <el-option label="线上会议" value="线上会议" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <!-- 修改会议附件部分 --> |
| | | <el-form-item label="会议附件"> |
| | | <div class="attachment-upload-section"> |
| | | <div class="upload-tip">上传会议相关资料文件</div> |
| | | <el-upload |
| | | class="attachment-upload" |
| | | action="#" |
| | | :auto-upload="false" |
| | | :on-change="handleAttachmentChange" |
| | | :file-list="editForm.attachmentFiles" |
| | | :limit="10" |
| | | multiple |
| | | <div class="attachment-section"> |
| | | <div class="attachment-header"> |
| | | <i class="el-icon-paperclip"></i> |
| | | <span class="attachment-title">会议附件上传</span> |
| | | <span class="attachment-tip" |
| | | >支持上传文档、图片等文件 (最多{{ attachmentLimit }}个)</span |
| | | > |
| | | <el-button size="small" type="primary" icon="el-icon-upload"> |
| | | 上传会议附件 |
| | | </el-button> |
| | | <div slot="tip" class="el-upload__tip"> |
| | | 支持文档、图片等格式,单个文件不超过20MB |
| | | </div> |
| | | </el-upload> |
| | | |
| | | <!-- 使用 UploadAttachment 组件 --> |
| | | <UploadAttachment |
| | | ref="uploadAttachment" |
| | | :file-list="attachmentFileList" |
| | | :limit="attachmentLimit" |
| | | :accept="attachmentAccept" |
| | | @change="handleAttachmentChange" |
| | | @upload-success="handleAttachmentUploadSuccess" |
| | | @upload-error="handleAttachmentUploadError" |
| | | @remove="handleAttachmentRemove" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- 会议附件列表 --> |
| | | <div |
| | | v-if=" |
| | | editForm.attachmentFiles && editForm.attachmentFiles.length > 0 |
| | | " |
| | | class="uploaded-files" |
| | | class="attachment-list" |
| | | v-if="editForm.attachment && editForm.attachment.length > 0" |
| | | > |
| | | <div |
| | | v-for="(file, index) in editForm.attachmentFiles" |
| | | :key="file.uid || index" |
| | | class="file-item" |
| | | <div class="list-title"> |
| | | 已上传附件 ({{ editForm.attachment.length }}) |
| | | </div> |
| | | <el-table |
| | | :data="editForm.attachment" |
| | | style="width: 100%" |
| | | size="small" |
| | | border |
| | | > |
| | | <span class="file-name">{{ file.name }}</span> |
| | | <el-table-column label="文件名" min-width="200"> |
| | | <template #default="scope"> |
| | | <i |
| | | class="el-icon-document" |
| | | style="margin-right: 8px; color: #409EFF;" |
| | | ></i> |
| | | <span class="file-name">{{ scope.row.name }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件类型" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag size="small">{{ |
| | | getFileType(scope.row.name) |
| | | }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件大小" width="100"> |
| | | <template #default="scope"> |
| | | <span>{{ formatFileSize(scope.row.size) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleRemoveAttachmentFile(index)" |
| | | style="color: #F56C6C;" |
| | | type="primary" |
| | | @click="handlePreviewAttachment(scope.row)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveMeetingAttachment(scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | |
| | | </div> |
| | | </el-form-item> |
| | | |
| | | <!-- 修改会议纪要附件部分 --> |
| | | <el-form-item label="纪要附件"> |
| | | <div class="attachment-upload-section"> |
| | | <div class="upload-tip">上传与会议纪要相关的补充材料</div> |
| | | <el-upload |
| | | class="minutes-upload" |
| | | action="#" |
| | | :auto-upload="false" |
| | | :on-change="handleMinutesAttachmentChange" |
| | | :file-list="editForm.recordattachmentFiles" |
| | | :limit="5" |
| | | multiple |
| | | <div class="attachment-section"> |
| | | <div class="attachment-header"> |
| | | <i class="el-icon-paperclip"></i> |
| | | <span class="attachment-title">纪要附件上传</span> |
| | | <span class="attachment-tip" |
| | | >支持上传与纪要相关的补充材料 (最多{{ |
| | | minutesAttachmentLimit |
| | | }}个)</span |
| | | > |
| | | <el-button size="small" type="primary" icon="el-icon-upload"> |
| | | 上传纪要附件 |
| | | </el-button> |
| | | <div slot="tip" class="el-upload__tip"> |
| | | 支持图片、文档等格式,单个文件不超过10MB |
| | | </div> |
| | | </el-upload> |
| | | |
| | | <UploadAttachment |
| | | ref="uploadMinutesAttachment" |
| | | :file-list="minutesAttachmentFileList" |
| | | :limit="minutesAttachmentLimit" |
| | | :accept="minutesAttachmentAccept" |
| | | @change="handleMinutesAttachmentChange" |
| | | @upload-success="handleMinutesUploadSuccess" |
| | | @upload-error="handleMinutesUploadError" |
| | | @remove="handleMinutesAttachmentRemove" |
| | | /> |
| | | </div> |
| | | |
| | | <div |
| | | class="attachment-list" |
| | | v-if=" |
| | | editForm.recordattachment && editForm.recordattachment.length > 0 |
| | | " |
| | | > |
| | | <div class="list-title"> |
| | | 已上传纪要附件 ({{ editForm.recordattachment.length }}) |
| | | </div> |
| | | <el-table |
| | | :data="editForm.recordattachment" |
| | | style="width: 100%" |
| | | size="small" |
| | | border |
| | | > |
| | | <el-table-column label="文件名" min-width="200"> |
| | | <template #default="scope"> |
| | | <i |
| | | class="el-icon-document" |
| | | style="margin-right: 8px; color: #409EFF;" |
| | | ></i> |
| | | <span class="file-name">{{ scope.row.name }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件类型" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag size="small">{{ |
| | | getFileType(scope.row.name) |
| | | }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件大小" width="100"> |
| | | <template #default="scope"> |
| | | <span>{{ formatFileSize(scope.row.size) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="primary" |
| | | @click="handlePreviewMinutesAttachment(scope.row)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveMinutesAttachment(scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | |
| | | </el-button> |
| | | </span> |
| | | </el-dialog> |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="previewVisible" |
| | | :file="currentPreviewFile" |
| | | @close="previewVisible = false" |
| | | @download="handleDownload" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | meetingDel, |
| | | exporremeeting |
| | | } from "@/api/officeManagementApi"; |
| | | |
| | | import UploadAttachment from "@/components/UploadAttachment"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | import dayjs from "dayjs"; |
| | | export default { |
| | | name: "MeetingManagement", |
| | | components: { |
| | | UploadAttachment, |
| | | FilePreviewDialog |
| | | }, |
| | | data() { |
| | | return { |
| | | // 查询参数 |
| | |
| | | isEditing: false, |
| | | // 表格数据 |
| | | tableData: [], |
| | | imageSize: "100px", // 图片显示大小 |
| | | // 编辑表单数据 |
| | | editForm: this.getDefaultFormData(), |
| | | // 表单验证规则 |
| | |
| | | reminderMinutes: [ |
| | | { required: true, message: "请输入提前提醒时间", trigger: "blur" } |
| | | ] |
| | | } |
| | | }, |
| | | // 附件相关配置 |
| | | attachmentLimit: 10, |
| | | minutesAttachmentLimit: 5, |
| | | attachmentAccept: |
| | | ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar", |
| | | minutesAttachmentAccept: ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx", |
| | | |
| | | // 文件预览相关 |
| | | previewVisible: false, |
| | | currentPreviewFile: null, |
| | | |
| | | // 附件文件列表 |
| | | attachmentFileList: [], |
| | | minutesAttachmentFileList: [], |
| | | |
| | | // 编辑表单数据 - 修改默认值 |
| | | editForm: this.getDefaultFormData() |
| | | }; |
| | | }, |
| | | mounted() { |
| | |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | // 修改获取文件类型方法 |
| | | getFileType(fileName) { |
| | | if (!fileName) return "other"; |
| | | const extension = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"]; |
| | | const pdfTypes = ["pdf"]; |
| | | const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"]; |
| | | const zipTypes = ["zip", "rar"]; |
| | | |
| | | if (imageTypes.includes(extension)) return "image"; |
| | | if (pdfTypes.includes(extension)) return "pdf"; |
| | | if (officeTypes.includes(extension)) return "office"; |
| | | if (zipTypes.includes(extension)) return "archive"; |
| | | return "other"; |
| | | }, |
| | | // 判断是否为图片文件 |
| | | isImageFile(file) { |
| | | if (!file || !file.name) return false; |
| | | const imageExtensions = [ |
| | | "jpg", |
| | | "jpeg", |
| | | "png", |
| | | "gif", |
| | | "bmp", |
| | | "webp", |
| | | "svg" |
| | | ]; |
| | | const extension = file.name |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | return imageExtensions.includes(extension); |
| | | }, |
| | | |
| | | // 获取文件URL |
| | | getFileUrl(file) { |
| | | return file.url || file.path || file.fileUrl || ""; |
| | | }, |
| | | |
| | | // 获取图片预览列表 |
| | | getImagePreviewList(file) { |
| | | const url = this.getFileUrl(file); |
| | | if (!url) return []; |
| | | return [url]; |
| | | }, |
| | | // 获取文件类型文本 |
| | | getFileTypeText(file) { |
| | | if (!file.name) return "文件"; |
| | | const ext = file.name |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const typeMap = { |
| | | pdf: "PDF文档", |
| | | doc: "Word文档", |
| | | docx: "Word文档", |
| | | xls: "Excel表格", |
| | | xlsx: "Excel表格", |
| | | ppt: "PPT演示", |
| | | pptx: "PPT演示", |
| | | zip: "压缩包", |
| | | rar: "压缩包", |
| | | txt: "文本文档", |
| | | jpg: "图片", |
| | | jpeg: "图片", |
| | | png: "图片", |
| | | gif: "图片" |
| | | }; |
| | | return typeMap[ext] || "文件"; |
| | | }, |
| | | |
| | | // 判断文件是否可以预览 |
| | | canPreview(file) { |
| | | if (!file.name) return false; |
| | | const previewableExtensions = ["pdf", "jpg", "jpeg", "png", "gif", "txt"]; |
| | | const extension = file.name |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | return previewableExtensions.includes(extension); |
| | | }, |
| | | |
| | | // 文件预览 |
| | | handlePreview(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.name, |
| | | fileUrl: this.getFileUrl(file), |
| | | fileType: this.getFileType(file.name) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | // 附件转换为上传文件列表 |
| | | parseAttachmentToFileList(attachments) { |
| | | if (!attachments || !Array.isArray(attachments)) return []; |
| | | return attachments.map((item, index) => ({ |
| | | uid: item.id || `attachment-${index}-${Date.now()}`, |
| | | name: item.name || item.fileName, |
| | | url: item.url || item.path || item.fileUrl, |
| | | size: item.size, |
| | | status: "success" |
| | | })); |
| | | }, |
| | | // 获取文件图标 |
| | | getFileIcon(fileName) { |
| | | if (!fileName) return "el-icon-document"; |
| | |
| | | } |
| | | }, |
| | | |
| | | // 格式化文件大小 |
| | | // 文件大小格式化 |
| | | formatFileSize(bytes) { |
| | | if (!bytes) return "0 B"; |
| | | if (!bytes || bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | |
| | | try { |
| | | const response = await meetingInfo(id); |
| | | if (response.code === 200) { |
| | | this.currentRecord = response.data || {}; |
| | | const data = response.data || {}; |
| | | // 解析附件 |
| | | if (data.attachment && typeof data.attachment === "string") { |
| | | data.attachment = this.parseAttachments(data.attachment); |
| | | } |
| | | if ( |
| | | data.recordattachment && |
| | | typeof data.recordattachment === "string" |
| | | ) { |
| | | data.recordattachment = this.parseAttachments( |
| | | data.recordattachment |
| | | ); |
| | | } |
| | | this.currentRecord = data; |
| | | this.detailDialogVisible = true; |
| | | } else { |
| | | this.$message.error(response.msg || "获取详情失败"); |
| | |
| | | handleAdd() { |
| | | this.isEditing = false; |
| | | this.editForm = this.getDefaultFormData(); |
| | | this.attachmentFileList = []; |
| | | this.minutesAttachmentFileList = []; |
| | | this.editDialogVisible = true; |
| | | this.$nextTick(() => { |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | |
| | | const response = await meetingInfo(id); |
| | | if (response.code === 200) { |
| | | this.isEditing = true; |
| | | this.currentRecord = response.data || {}; |
| | | this.editForm = { ...response.data }; |
| | | const data = response.data || {}; |
| | | |
| | | // 解析附件 |
| | | if (this.editForm.attachment) { |
| | | this.editForm.attachmentFiles = this.parseAttachments( |
| | | this.editForm.attachment |
| | | if (data.attachment) { |
| | | data.attachment = this.parseAttachments(data.attachment); |
| | | this.attachmentFileList = this.parseAttachmentToFileList( |
| | | data.attachment |
| | | ); |
| | | } |
| | | if (this.editForm.recordattachment) { |
| | | this.editForm.recordattachmentFiles = this.parseAttachments( |
| | | this.editForm.recordattachment |
| | | if (data.recordattachment) { |
| | | data.recordattachment = this.parseAttachments( |
| | | data.recordattachment |
| | | ); |
| | | this.minutesAttachmentFileList = this.parseAttachmentToFileList( |
| | | data.recordattachment |
| | | ); |
| | | } |
| | | |
| | | this.currentRecord = data; |
| | | this.editForm = { ...data }; |
| | | this.editDialogVisible = true; |
| | | this.detailDialogVisible = false; |
| | | this.$nextTick(() => { |
| | |
| | | } |
| | | }, |
| | | |
| | | // 文件上传处理 |
| | | handleAttachmentChange(file, fileList) { |
| | | this.editForm.attachmentFiles = fileList; |
| | | // 附件变化处理 |
| | | handleAttachmentChange(fileList) { |
| | | this.attachmentFileList = fileList; |
| | | }, |
| | | |
| | | handleMinutesAttachmentChange(file, fileList) { |
| | | this.editForm.recordattachmentFiles = fileList; |
| | | handleMinutesAttachmentChange(fileList) { |
| | | this.minutesAttachmentFileList = fileList; |
| | | }, |
| | | // 附件上传成功处理 |
| | | handleAttachmentUploadSuccess({ file, fileList, response }) { |
| | | if (response && response.code === 200) { |
| | | if (!this.editForm.attachment) { |
| | | this.editForm.attachment = []; |
| | | } |
| | | |
| | | console.log(file, "file"); |
| | | console.log(response, "response"); |
| | | |
| | | const attachmentObj = { |
| | | name: file.name, |
| | | url: response.data || file.url, |
| | | fileName: file.name, |
| | | size: file.size || 0, |
| | | type: this.getFileExtension(file.name), |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss") |
| | | }; |
| | | console.log(this.editForm.attachment, "this.editForm.attachment"); |
| | | |
| | | this.editForm.attachment.push(attachmentObj); |
| | | console.log(this.editForm.attachment, "this.editForm.attachment"); |
| | | |
| | | this.$message.success("会议附件上传成功"); |
| | | } |
| | | }, |
| | | handleMinutesUploadSuccess({ file, fileList, response }) { |
| | | if (response && response.code === 200) { |
| | | if (!this.editForm.recordattachment) { |
| | | this.editForm.recordattachment = []; |
| | | } |
| | | |
| | | const attachmentObj = { |
| | | name: file.name, |
| | | url: response.data || file.url, |
| | | fileName: file.name, |
| | | size: file.size || 0, |
| | | type: this.getFileExtension(file.name), |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss") |
| | | }; |
| | | this.editForm.recordattachment.push(attachmentObj); |
| | | this.$message.success("纪要附件上传成功"); |
| | | } |
| | | }, |
| | | // 附件上传错误处理 |
| | | handleAttachmentUploadError({ file, fileList, error }) { |
| | | console.error("会议附件上传失败:", error); |
| | | this.$message.error("文件上传失败,请重试"); |
| | | }, |
| | | |
| | | // 删除已上传的文件 |
| | | handleRemoveAttachmentFile(index) { |
| | | this.editForm.attachmentFiles.splice(index, 1); |
| | | handleMinutesUploadError({ file, fileList, error }) { |
| | | console.error("纪要附件上传失败:", error); |
| | | this.$message.error("文件上传失败,请重试"); |
| | | }, |
| | | // 附件移除处理 |
| | | handleAttachmentRemove(file) { |
| | | if (file.url && this.editForm.attachment) { |
| | | const index = this.editForm.attachment.findIndex( |
| | | item => |
| | | item.url === file.url || |
| | | item.path === file.url || |
| | | item.fileUrl === file.url |
| | | ); |
| | | if (index > -1) { |
| | | this.editForm.attachment.splice(index, 1); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | handleMinutesAttachmentRemove(file) { |
| | | if (file.url && this.editForm.recordattachment) { |
| | | const index = this.editForm.recordattachment.findIndex( |
| | | item => |
| | | item.url === file.url || |
| | | item.path === file.url || |
| | | item.fileUrl === file.url |
| | | ); |
| | | if (index > -1) { |
| | | this.editForm.recordattachment.splice(index, 1); |
| | | } |
| | | } |
| | | }, |
| | | // 手动删除附件 |
| | | handleRemoveMeetingAttachment(index) { |
| | | if (this.editForm.attachment && this.editForm.attachment[index]) { |
| | | this.editForm.attachment.splice(index, 1); |
| | | this.attachmentFileList.splice(index, 1); |
| | | this.$message.success("会议附件删除成功"); |
| | | } |
| | | }, |
| | | |
| | | handleRemoveMinutesAttachment(index) { |
| | | if ( |
| | | this.editForm.recordattachment && |
| | | this.editForm.recordattachment[index] |
| | | ) { |
| | | this.editForm.recordattachment.splice(index, 1); |
| | | this.minutesAttachmentFileList.splice(index, 1); |
| | | this.$message.success("纪要附件删除成功"); |
| | | } |
| | | }, |
| | | // 文件预览 |
| | | handlePreviewAttachment(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.name || file.fileName, |
| | | fileUrl: file.url || file.path || file.fileUrl, |
| | | fileType: this.getFileType(file.name) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | |
| | | handlePreviewMinutesAttachment(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.name || file.fileName, |
| | | fileUrl: file.url || file.path || file.fileUrl, |
| | | fileType: this.getFileType(file.name) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | // 文件下载 |
| | | handleDownload(file) { |
| | | if (file.url) { |
| | | const link = document.createElement("a"); |
| | | link.href = file.url; |
| | | link.download = file.name; |
| | | link.download = file.name || file.fileName || "download"; |
| | | link.style.display = "none"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | this.$message.success(`开始下载: ${file.name}`); |
| | | document.body.removeChild(link); |
| | | this.$message.success("开始下载文件"); |
| | | } else { |
| | | this.$message.warning("文件地址不存在"); |
| | | this.$message.warning("文件地址不存在,无法下载"); |
| | | } |
| | | }, |
| | | |
| | | // 获取文件扩展名 |
| | | getFileExtension(filename) { |
| | | if (!filename) return ""; |
| | | return filename |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | }, |
| | | // 保存记录 |
| | | async handleSave() { |
| | | try { |
| | |
| | | } |
| | | } |
| | | |
| | | // 检查是否有未上传完成的文件 |
| | | const pendingFiles = [ |
| | | ...this.attachmentFileList.filter(item => item.status !== "success"), |
| | | ...this.minutesAttachmentFileList.filter( |
| | | item => item.status !== "success" |
| | | ) |
| | | ]; |
| | | |
| | | if (pendingFiles.length > 0) { |
| | | this.$message.warning( |
| | | "还有文件未上传完成,请先上传所有文件或移除未上传的文件" |
| | | ); |
| | | return; |
| | | } |
| | | |
| | | this.saveLoading = true; |
| | | |
| | | // 处理附件 |
| | | // 准备数据 |
| | | const formData = { ...this.editForm }; |
| | | |
| | | if (formData.attachmentFiles) { |
| | | // 处理附件为JSON字符串 |
| | | if (formData.attachment && Array.isArray(formData.attachment)) { |
| | | formData.attachment = JSON.stringify( |
| | | formData.attachmentFiles.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || "", |
| | | size: file.size || 0, |
| | | type: file.type || file.name.split(".").pop() |
| | | formData.attachment.map(item => ({ |
| | | name: item.name || item.fileName, |
| | | url: item.url || item.path || item.fileUrl, |
| | | size: item.size || 0, |
| | | type: |
| | | item.type || this.getFileExtension(item.name || item.fileName) |
| | | })) |
| | | ); |
| | | } |
| | | |
| | | if (formData.recordattachmentFiles) { |
| | | if ( |
| | | formData.recordattachment && |
| | | Array.isArray(formData.recordattachment) |
| | | ) { |
| | | formData.recordattachment = JSON.stringify( |
| | | formData.recordattachmentFiles.map(file => ({ |
| | | name: file.name, |
| | | url: file.url || "", |
| | | size: file.size || 0, |
| | | type: file.type || file.name.split(".").pop() |
| | | formData.recordattachment.map(item => ({ |
| | | name: item.name || item.fileName, |
| | | url: item.url || item.path || item.fileUrl, |
| | | size: item.size || 0, |
| | | type: |
| | | item.type || this.getFileExtension(item.name || item.fileName) |
| | | })) |
| | | ); |
| | | } |
| | | |
| | | // 清理文件列表字段 |
| | | // 清理临时字段 |
| | | delete formData.attachmentFiles; |
| | | delete formData.recordattachmentFiles; |
| | | |
| | |
| | | this.editDialogVisible = false; |
| | | this.currentRecord = {}; |
| | | this.editForm = this.getDefaultFormData(); |
| | | this.attachmentFileList = []; |
| | | this.minutesAttachmentFileList = []; |
| | | this.$nextTick(() => { |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | | }); |
| | |
| | | console.log("排序变化:", sort); |
| | | }, |
| | | |
| | | // 获取默认表单数据 |
| | | // 默认表单数据 |
| | | getDefaultFormData() { |
| | | return { |
| | | id: null, |
| | |
| | | endTime: "", |
| | | summary: "", |
| | | content: "", |
| | | attachment: null, |
| | | attachmentFiles: [], |
| | | status: 1, // 默认待开始 |
| | | isRecurring: 0, |
| | | recurringPattern: null, |
| | | parentMeetingId: null, |
| | | reminderMinutes: 30, |
| | | attachment: [], // 改为数组 |
| | | recordcontent: "", |
| | | recordattachment: null, |
| | | recordattachmentFiles: [], |
| | | recordattachment: [], // 改为数组 |
| | | recorderBy: "", |
| | | remark: "", |
| | | approvalStatus: 0 // 默认待审核 |
| | | status: 1, |
| | | reminderMinutes: 30, |
| | | approvalStatus: 0 |
| | | }; |
| | | } |
| | | } |
| | |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .meeting-management { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .attachment-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .attachment-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 16px; |
| | | padding: 8px 0; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .attachment-title { |
| | | font-weight: bold; |
| | | margin: 0 8px; |
| | | } |
| | | |
| | | .attachment-tip { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .attachment-list { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .list-title { |
| | | font-weight: bold; |
| | | margin-bottom: 12px; |
| | | color: #303133; |
| | | } |
| | | /* 图片附件样式 */ |
| | | .image-attachment { |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .image-attachment:hover { |
| | | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .image-info { |
| | | text-align: center; |
| | | padding: 4px 0; |
| | | } |
| | | |
| | | .image-info .file-name { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 4px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | max-width: 100px; |
| | | } |
| | | |
| | | .image-info .file-actions { |
| | | display: flex; |
| | | justify-content: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .image-loading, |
| | | .image-error { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | color: #909399; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .image-loading i, |
| | | .image-error i { |
| | | font-size: 20px; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | /* 文件卡片样式 */ |
| | | .file-card { |
| | | width: 100%; |
| | | min-height: 60px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .file-content { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .file-icon { |
| | | font-size: 24px; |
| | | margin-right: 12px; |
| | | color: #409eff; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | margin-bottom: 4px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | margin-top: 8px; |
| | | text-align: right; |
| | | } |
| | | |
| | | /* 附件网格布局 */ |
| | | .attachment-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| | | gap: 16px; |
| | | } |
| | | |
| | | .attachment-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | /* 响应式调整 */ |
| | | @media (max-width: 768px) { |
| | | .attachment-grid { |
| | | grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); |
| | | gap: 12px; |
| | | } |
| | | |
| | | .image-attachment { |
| | | width: 80px !important; |
| | | height: 80px !important; |
| | | } |
| | | } |
| | | .file-name { |
| | | font-size: 13px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* 其他样式保持不变 */ |
| | | .meeting-management { |
| | | padding: 20px; |
| | | } |
| | |
| | | .attachment-item { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .minutes-content { |
| | | margin-bottom: 16px; |
| | | } |
| | |
| | | margin: 0 -20px; |
| | | } |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .page-header { |
| | |
| | | justify-content: space-between; |
| | | } |
| | | } |
| | | |
| | | /* 新增附件相关样式 */ |
| | | .attachment-upload-section { |
| | | border: 1px solid #ebeef5; |
| | |
| | | caseData.name || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="性别"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="caseData.sex ? parseInt(caseData.sex) : ''" |
| | | /> |
| | | <dict-tag :options="dict.type.sys_user_sex" :value="caseData.sex" /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="年龄"> |
| | | {{ caseData.age || "-" |
| | |
| | | <el-descriptions-item label="部门名称">{{ |
| | | caseData.deptName || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="部门编号">{{ |
| | | caseData.deptNo || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="上报医院">{{ |
| | | caseData.toHospital || "-" |
| | | }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | |
| | |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="报告时间">{{ |
| | | formatDateTime(caseData.reporttime) |
| | | formatDateTime(caseData.createTime) |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="是否终止案例"> |
| | | {{ caseData.terminationCase === "1" ? "已终止" : "进行中" }} |
| | |
| | | </el-card> |
| | | |
| | | <!-- 附件信息模块 --> |
| | | <el-card class="detail-section" v-if="attachmentList.length > 0"> |
| | | <el-card |
| | | class="detail-section" |
| | | v-if="caseData.annexfilesList && caseData.annexfilesList.length > 0" |
| | | > |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">附件信息</span> |
| | | </div> |
| | | <el-table :data="attachmentList" style="width: 100%"> |
| | | <el-table-column label="文件名" width="300"> |
| | | <template slot-scope="scope"> |
| | | <i class="el-icon-document" style="margin-right: 8px;"></i> |
| | | <span>{{ scope.row.fileName }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件类型" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-tag size="small">{{ scope.row.fileType }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="大小" width="100"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatFileSize(scope.row.fileSize) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="上传时间" width="180"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.uploadTime }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" @click="handlePreview(scope.row)" |
| | | >预览</el-button |
| | | <div class="detail-attachments"> |
| | | <div class="attachment-grid"> |
| | | <div |
| | | v-for="file in caseData.annexfilesList" |
| | | :key="file.id || file.fileName" |
| | | class="attachment-card" |
| | | > |
| | | <template v-if="isImageFile(file.fileName || file.path)"> |
| | | <!-- 图片使用 el-image 预览 --> |
| | | <el-image |
| | | class="image-attachment" |
| | | :src="getFileUrl(file)" |
| | | :preview-src-list="getImagePreviewList(file)" |
| | | fit="cover" |
| | | :style="{ width: '120px', height: '120px' }" |
| | | lazy |
| | | > |
| | | <div slot="error" class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | <span>加载失败</span> |
| | | </div> |
| | | <div slot="placeholder" class="image-loading"> |
| | | <i class="el-icon-loading"></i> |
| | | </div> |
| | | </el-image> |
| | | <div class="image-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | type="success" |
| | | @click="handleDownload(scope.row)" |
| | | >下载</el-button |
| | | > |
| | | @click="handleDownload(file)" |
| | | icon="el-icon-download" |
| | | title="下载" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | icon="el-icon-view" |
| | | title="预览" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <template v-else> |
| | | <!-- 非图片文件使用卡片样式 --> |
| | | <el-card shadow="hover" class="file-card"> |
| | | <div class="file-content"> |
| | | <i :class="getFileIcon(file.fileName)" class="file-icon"></i> |
| | | <div class="file-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-meta"> |
| | | <span class="file-type">{{ |
| | | getFileTypeText(file.fileName) |
| | | }}</span> |
| | | <span v-if="file.createTime" class="file-time"> |
| | | {{ formatDateTime(file.createTime) }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="canPreview(file.fileName)" |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 备注信息 --> |
| | | <el-card class="detail-section" v-if="caseData.remark"> |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">备注信息</span> |
| | | </div> |
| | | <div class="remark-content"> |
| | | {{ caseData.remark }} |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 审批信息模块(状态为已同意或已驳回时显示) --> |
| | |
| | | {{ caseData.reportStatus === "3" ? "已同意" : "已驳回" }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="审批时间">{{ |
| | | formatDateTime(caseData.updateTime) |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="审批人">{{ |
| | | caseData.updateBy || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="审批时间">{{ |
| | | formatDateTime(caseData.updateTime) |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="审批意见">{{ |
| | | caseData.remark || "无" |
| | | }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | |
| | | <!-- PDF预览弹窗 --> |
| | | <el-dialog |
| | | :title="previewTitle" |
| | | :append-to-body="true" |
| | | :visible.sync="pdfPreviewVisible" |
| | | width="90%" |
| | | top="5vh" |
| | | :close-on-click-modal="true" |
| | | class="pdf-preview-dialog" |
| | | @close="handlePdfDialogClose" |
| | | <el-card |
| | | class="detail-section" |
| | | v-if=" |
| | | caseData.isTransport == '2' && |
| | | caseData.serviceTransport && |
| | | caseData.serviceTransport.length > 0 |
| | | " |
| | | > |
| | | <div class="pdf-preview-container" v-loading="pdfLoading"> |
| | | <!-- PDF控制工具栏 --> |
| | | <div class="pdf-toolbar"> |
| | | <el-button-group> |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">转运信息</span> |
| | | <el-button |
| | | size="mini" |
| | | @click="changePage(currentPage - 1)" |
| | | :disabled="currentPage <= 1" |
| | | icon="el-icon-arrow-left" |
| | | v-if="caseData.reportStatus === '3'" |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-truck" |
| | | @click="handleViewTransport" |
| | | > |
| | | 上一页 |
| | | 查看转运详情 |
| | | </el-button> |
| | | <el-button size="mini" disabled> |
| | | 第 {{ currentPage }} 页 / 共 {{ pageCount }} 页 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item |
| | | v-for="transport in caseData.serviceTransport" |
| | | :key="transport.id" |
| | | > |
| | | <!-- 转运单列表 --> |
| | | <div class="transport-info"> |
| | | <div class="transport-item"> |
| | | <strong>转运单号:</strong> {{ transport.reportId || "-" }} |
| | | </div> |
| | | <div class="transport-item"> |
| | | <strong>患者姓名:</strong> {{ transport.patName || "-" }} |
| | | </div> |
| | | <div class="transport-item"> |
| | | <strong>出发地点:</strong> |
| | | {{ transport.transportStartPlace || "-" }} |
| | | </div> |
| | | <div class="transport-item"> |
| | | <strong>出发时间:</strong> |
| | | {{ formatDateTime(transport.transportStartTime) }} |
| | | </div> |
| | | <div class="transport-item"> |
| | | <strong>转运状态:</strong> |
| | | <el-tag :type="getTransportStatusTag(transport)" size="small"> |
| | | {{ getTransportStatusText(transport) }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="transport-item"> |
| | | <strong>负责协调员:</strong> {{ transport.contactPerson || "-" }} |
| | | </div> |
| | | <div class="transport-item" v-if="transport.remark"> |
| | | <strong>备注:</strong> {{ transport.remark }} |
| | | </div> |
| | | </div> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | |
| | | <!-- 无转运信息但需要转运的提示 --> |
| | | <el-card |
| | | class="detail-section" |
| | | v-else-if="caseData.isTransport === '2' && caseData.reportStatus === '3'" |
| | | > |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">转运信息</span> |
| | | <el-button |
| | | size="mini" |
| | | @click="changePage(currentPage + 1)" |
| | | :disabled="currentPage >= pageCount" |
| | | icon="el-icon-arrow-right" |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-truck" |
| | | @click="handleCreateTransport" |
| | | > |
| | | 下一页 |
| | | </el-button> |
| | | </el-button-group> |
| | | |
| | | <el-button-group class="zoom-controls"> |
| | | <el-button size="mini" @click="zoomOut" :disabled="scale <= 50"> |
| | | <i class="el-icon-zoom-out"></i> 缩小 |
| | | </el-button> |
| | | <el-button size="mini" disabled> {{ scale }}% </el-button> |
| | | <el-button size="mini" @click="zoomIn" :disabled="scale >= 200"> |
| | | <i class="el-icon-zoom-in"></i> 放大 |
| | | </el-button> |
| | | <el-button size="mini" @click="resetZoom"> |
| | | <i class="el-icon-refresh-left"></i> 重置 |
| | | </el-button> |
| | | </el-button-group> |
| | | |
| | | <el-button |
| | | size="mini" |
| | | type="success" |
| | | @click="downloadPdf(currentFile)" |
| | | icon="el-icon-download" |
| | | > |
| | | 下载 |
| | | 创建转运单 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- PDF渲染区域 --> |
| | | <div class="pdf-viewport"> |
| | | <pdf |
| | | ref="pdf" |
| | | :src="pdfUrl" |
| | | :page="currentPage" |
| | | :rotate="pageRotate" |
| | | @num-pages="pageCount = $event" |
| | | @page-loaded="currentPage = $event" |
| | | @loaded="loadPdfHandler" |
| | | @error="pdfErrorHandler" |
| | | :style="{ |
| | | width: scale + '%', |
| | | transform: 'scale(' + scale / 100 + ')', |
| | | transformOrigin: '0 0' |
| | | }" |
| | | ></pdf> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 图片预览弹窗 --> |
| | | <el-dialog |
| | | :append-to-body="true" |
| | | :title="previewTitle" |
| | | :visible.sync="imagePreviewVisible" |
| | | width="60%" |
| | | top="10vh" |
| | | :close-on-click-modal="true" |
| | | > |
| | | <div class="image-preview-container"> |
| | | <img :src="previewUrl" alt="预览图片" class="preview-image" /> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 不支持预览的文件类型 --> |
| | | <el-dialog |
| | | :title="previewTitle" |
| | | :visible.sync="unsupportedPreviewVisible" |
| | | width="400px" |
| | | :close-on-click-modal="true" |
| | | > |
| | | <div class="unsupported-preview"> |
| | | <el-alert |
| | | title="该文件格式不支持在线预览,请下载后查看" |
| | | title="该案例需要转运,但尚未创建转运单" |
| | | type="warning" |
| | | description="请点击上方按钮创建转运单" |
| | | show-icon |
| | | :closable="false" |
| | | /> |
| | | <div style="text-align: center; margin-top: 20px;"> |
| | | <el-button type="primary" @click="handleDownload(currentFile)"> |
| | | <i class="el-icon-download"></i> 下载文件 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </el-card> |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="previewVisible" |
| | | :file="currentPreviewFile" |
| | | @close="previewVisible = false" |
| | | @download="handleDownload" |
| | | /> |
| | | |
| | | <div class="detail-footer" v-if="showtitle"> |
| | | <el-button @click="handleClose">关闭</el-button> |
| | |
| | | |
| | | <script> |
| | | import pdf from "vue-pdf"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | |
| | | export default { |
| | | name: "CaseDetail", |
| | | components: { |
| | | pdf |
| | | pdf, |
| | | FilePreviewDialog |
| | | }, |
| | | props: { |
| | | caseData: { |
| | |
| | | } |
| | | }, |
| | | dicts: ["sys_user_sex", "sys_BloodType"], |
| | | filters: { |
| | | statusFilter(status) { |
| | | const statusMap = { |
| | | "0": "warning", |
| | | "1": "success", |
| | | "2": "danger" |
| | | }; |
| | | return statusMap[status]; |
| | | }, |
| | | statusTextFilter(status) { |
| | | const statusMap = { |
| | | "0": "待审批", |
| | | "1": "已通过", |
| | | "2": "已驳回" |
| | | }; |
| | | return statusMap[status]; |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 预览相关数据(保持原有代码) |
| | | pdfPreviewVisible: false, |
| | | imagePreviewVisible: false, |
| | | unsupportedPreviewVisible: false, |
| | | pdfLoading: false, |
| | | pdfUrl: "", |
| | | currentPage: 1, |
| | | pageCount: 0, |
| | | scale: 100, |
| | | pageRotate: 0, |
| | | previewTitle: "", |
| | | previewUrl: "", |
| | | currentFile: null, |
| | | // 预览相关 |
| | | previewVisible: false, |
| | | currentPreviewFile: null, |
| | | |
| | | // 附件列表 |
| | | attachmentList: [] |
| | | // 图片预览相关 |
| | | imagePreviewUrls: [] |
| | | }; |
| | | }, |
| | | watch: { |
| | | caseData: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (newVal && newVal.annexfilesList) { |
| | | this.loadAttachments(newVal.annexfilesList); |
| | | computed: { |
| | | // 收集所有图片URL用于预览 |
| | | allImageUrls() { |
| | | if ( |
| | | !this.caseData.annexfilesList || |
| | | !Array.isArray(this.caseData.annexfilesList) |
| | | ) { |
| | | return []; |
| | | } |
| | | } |
| | | return this.caseData.annexfilesList |
| | | .filter(file => this.isImageFile(file.fileName || file.path)) |
| | | .map(file => this.getFileUrl(file)) |
| | | .filter(url => url); |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | this.$emit("close"); |
| | | }, |
| | | |
| | | // 加载附件 |
| | | loadAttachments(annexfilesList) { |
| | | if (!annexfilesList || !Array.isArray(annexfilesList)) { |
| | | this.attachmentList = []; |
| | | return; |
| | | } |
| | | |
| | | this.attachmentList = annexfilesList.map((file, index) => ({ |
| | | id: index + 1, |
| | | fileName: file.fileName || `附件${index + 1}`, |
| | | fileType: this.getFileExtension(file.fileUrl || ""), |
| | | fileSize: file.fileSize || 0, |
| | | uploadTime: file.uploadTime || this.formatDateTime(new Date()), |
| | | fileUrl: file.fileUrl || "" |
| | | })); |
| | | }, |
| | | |
| | | // 获取文件扩展名 |
| | | getFileExtension(filename) { |
| | | return ( |
| | | filename |
| | | .split(".") |
| | | .pop() |
| | | ?.toLowerCase() || "unknown" |
| | | ); |
| | | }, |
| | | |
| | | // 格式化日期时间 |
| | | formatDateTime(dateString) { |
| | | if (!dateString) return "-"; |
| | | return dateString.replace("T", " ").substring(0, 19); |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return "-"; |
| | | return dateTime.replace("T", " ").substring(0, 19); |
| | | }, |
| | | |
| | | // 格式化日期 |
| | |
| | | if (!dateString) return "-"; |
| | | return dateString.split("T")[0]; |
| | | }, |
| | | getTransportStatusTag(transport) { |
| | | if (!transport.transitStatus) return "info"; |
| | | switch (transport.transitStatus.toString()) { |
| | | case "1": |
| | | return "warning"; // 待转运 |
| | | case "2": |
| | | return "primary"; // 转运中 |
| | | case "3": |
| | | return "success"; // 转运完成 |
| | | case "4": |
| | | return "danger"; // 转运取消 |
| | | case "5": |
| | | return "info"; // 暂存 |
| | | default: |
| | | return "info"; |
| | | } |
| | | }, |
| | | |
| | | /** 获取转运状态文本 */ |
| | | getTransportStatusText(transport) { |
| | | if (!transport.transitStatus) return "未知"; |
| | | switch (transport.transitStatus.toString()) { |
| | | case "1": |
| | | return "待转运"; |
| | | case "2": |
| | | return "转运中"; |
| | | case "3": |
| | | return "转运完成"; |
| | | case "4": |
| | | return "转运取消"; |
| | | case "5": |
| | | return "暂存"; |
| | | default: |
| | | return "未知"; |
| | | } |
| | | }, |
| | | |
| | | /** 查看转运详情 */ |
| | | handleViewTransport() { |
| | | if ( |
| | | this.caseData.serviceTransport && |
| | | this.caseData.serviceTransport.length > 0 |
| | | ) { |
| | | const transport = this.caseData.serviceTransport[0]; |
| | | this.$router.push({ |
| | | path: "/business/transport/detail", |
| | | query: { |
| | | id: transport.id, |
| | | caseNo: this.caseData.caseNo |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | /** 创建转运单 */ |
| | | handleCreateTransport() { |
| | | this.$router.push({ |
| | | path: "/business/transport/create", |
| | | query: { |
| | | caseId: this.caseData.id, |
| | | caseNo: this.caseData.caseNo, |
| | | patName: this.caseData.name, |
| | | age: this.caseData.age, |
| | | sex: this.caseData.sex, |
| | | diagnosisname: this.caseData.diagnosisname, |
| | | treatmentHospitalName: this.caseData.treatmenthospitalname |
| | | } |
| | | }); |
| | | }, |
| | | // 获取完整户籍地址 |
| | | getFullRegisterAddress() { |
| | | const { |
| | |
| | | return typeMap[type] || type || "-"; |
| | | }, |
| | | |
| | | // 文件预览相关方法(保持原有代码) |
| | | // 文件处理相关方法 |
| | | isImageFile(fileName) { |
| | | if (!fileName) return false; |
| | | const imageExtensions = [ |
| | | "jpg", |
| | | "jpeg", |
| | | "png", |
| | | "gif", |
| | | "bmp", |
| | | "webp", |
| | | "svg" |
| | | ]; |
| | | const extension = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | return imageExtensions.includes(extension); |
| | | }, |
| | | |
| | | getFileUrl(file) { |
| | | return file.path || file.fileUrl || ""; |
| | | }, |
| | | |
| | | getImagePreviewList(file) { |
| | | // 返回所有图片的URL列表,实现点击任意图片查看所有图片 |
| | | return this.allImageUrls; |
| | | }, |
| | | |
| | | getFileIcon(fileName) { |
| | | if (!fileName) return "el-icon-document"; |
| | | const ext = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const iconMap = { |
| | | pdf: "el-icon-document", |
| | | doc: "el-icon-document", |
| | | docx: "el-icon-document", |
| | | xls: "el-icon-document", |
| | | xlsx: "el-icon-document", |
| | | jpg: "el-icon-picture", |
| | | jpeg: "el-icon-picture", |
| | | png: "el-icon-picture", |
| | | gif: "el-icon-picture" |
| | | }; |
| | | return iconMap[ext] || "el-icon-document"; |
| | | }, |
| | | |
| | | getFileTypeText(fileName) { |
| | | if (!fileName) return "文件"; |
| | | const ext = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const typeMap = { |
| | | pdf: "PDF文档", |
| | | doc: "Word文档", |
| | | docx: "Word文档", |
| | | xls: "Excel表格", |
| | | xlsx: "Excel表格", |
| | | jpg: "图片", |
| | | jpeg: "图片", |
| | | png: "图片", |
| | | gif: "图片" |
| | | }; |
| | | return typeMap[ext] || "文件"; |
| | | }, |
| | | |
| | | canPreview(fileName) { |
| | | if (!fileName) return false; |
| | | const previewableExtensions = ["pdf", "jpg", "jpeg", "png", "gif"]; |
| | | const extension = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | return previewableExtensions.includes(extension); |
| | | }, |
| | | |
| | | // 文件预览 |
| | | handlePreview(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.fileName, |
| | | fileUrl: this.getFileUrl(file), |
| | | fileType: this.getFileType(file.fileName) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | |
| | | getFileType(fileName) { |
| | | if (!fileName) return "other"; |
| | | const extension = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"]; |
| | | const pdfTypes = ["pdf"]; |
| | | const officeTypes = ["doc", "docx", "xls", "xlsx"]; |
| | | |
| | | if (imageTypes.includes(extension)) return "image"; |
| | | if (pdfTypes.includes(extension)) return "pdf"; |
| | | if (officeTypes.includes(extension)) return "office"; |
| | | return "other"; |
| | | }, |
| | | |
| | | handlePreview(file) { |
| | | this.currentFile = file; |
| | | this.previewTitle = `预览 - ${file.fileName}`; |
| | | this.previewUrl = file.fileUrl; |
| | | const fileType = this.getFileType(file.fileName); |
| | | |
| | | switch (fileType) { |
| | | case "pdf": |
| | | this.previewPdf(file); |
| | | break; |
| | | case "image": |
| | | this.previewImage(file); |
| | | break; |
| | | default: |
| | | this.previewUnsupported(file); |
| | | break; |
| | | } |
| | | }, |
| | | |
| | | previewPdf(file) { |
| | | this.pdfPreviewVisible = true; |
| | | this.pdfLoading = true; |
| | | this.currentPage = 1; |
| | | this.scale = 100; |
| | | this.pageRotate = 0; |
| | | this.pdfUrl = file.fileUrl; |
| | | }, |
| | | |
| | | loadPdfHandler() { |
| | | this.pdfLoading = false; |
| | | this.currentPage = 1; |
| | | }, |
| | | |
| | | pdfErrorHandler(error) { |
| | | console.error("PDF加载失败:", error); |
| | | this.pdfLoading = false; |
| | | this.$message.error("PDF文件加载失败,请尝试下载后查看"); |
| | | this.pdfPreviewVisible = false; |
| | | }, |
| | | |
| | | changePage(newPage) { |
| | | if (newPage < 1 || newPage > this.pageCount) return; |
| | | this.currentPage = newPage; |
| | | }, |
| | | |
| | | zoomIn() { |
| | | if (this.scale >= 200) return; |
| | | this.scale += 10; |
| | | }, |
| | | |
| | | zoomOut() { |
| | | if (this.scale <= 50) return; |
| | | this.scale -= 10; |
| | | }, |
| | | |
| | | resetZoom() { |
| | | this.scale = 100; |
| | | }, |
| | | |
| | | previewImage(file) { |
| | | this.imagePreviewVisible = true; |
| | | }, |
| | | |
| | | previewUnsupported(file) { |
| | | this.unsupportedPreviewVisible = true; |
| | | }, |
| | | |
| | | handlePdfDialogClose() { |
| | | this.pdfUrl = ""; |
| | | this.currentPage = 1; |
| | | this.pageCount = 0; |
| | | }, |
| | | |
| | | // 文件下载 |
| | | handleDownload(file) { |
| | | const fileUrl = this.getFileUrl(file); |
| | | const fileName = file.fileName; |
| | | |
| | | if (fileUrl) { |
| | | const link = document.createElement("a"); |
| | | link.href = file.fileUrl; |
| | | link.download = file.fileName; |
| | | link.href = fileUrl; |
| | | link.download = fileName; |
| | | link.style.display = "none"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | this.$message.success("开始下载文件"); |
| | | }, |
| | | |
| | | downloadPdf(file) { |
| | | this.handleDownload(file); |
| | | }, |
| | | |
| | | formatFileSize(bytes) { |
| | | if (bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(bytes) / Math.log(k)); |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | } else { |
| | | this.$message.warning("文件路径不存在,无法下载"); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | /* PDF预览对话框样式 */ |
| | | .pdf-preview-dialog { |
| | | margin-top: 5vh !important; |
| | | .detail-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .pdf-preview-dialog >>> .el-dialog { |
| | | min-height: 80vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .pdf-preview-dialog >>> .el-dialog__body { |
| | | flex: 1; |
| | | padding: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .pdf-preview-container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | } |
| | | |
| | | /* PDF工具栏样式 */ |
| | | .pdf-toolbar { |
| | | padding: 15px 20px; |
| | | background: #f5f7fa; |
| | | border-bottom: 1px solid #ebeef5; |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .zoom-controls { |
| | | margin: 0 15px; |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | /* PDF视图区域样式 */ |
| | | .pdf-viewport { |
| | | flex: 1; |
| | | overflow: auto; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | /* 附件样式 */ |
| | | .detail-attachments { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .attachment-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |
| | | gap: 16px; |
| | | } |
| | | |
| | | .attachment-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | /* 图片附件样式 */ |
| | | .image-attachment { |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .image-attachment:hover { |
| | | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .image-info { |
| | | text-align: center; |
| | | width: 100%; |
| | | } |
| | | |
| | | .image-info .file-name { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 4px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | max-width: 120px; |
| | | } |
| | | |
| | | .image-info .file-actions { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | gap: 8px; |
| | | } |
| | | |
| | | /* 图片预览样式 */ |
| | | .image-preview-container { |
| | | text-align: center; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .preview-image { |
| | | max-width: 100%; |
| | | max-height: 70vh; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .pdf-toolbar { |
| | | .image-loading, |
| | | .image-error { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 100%; |
| | | color: #909399; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .zoom-controls { |
| | | margin: 10px 0; |
| | | .image-loading i, |
| | | .image-error i { |
| | | font-size: 20px; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .pdf-preview-dialog { |
| | | width: 95% !important; |
| | | /* 文件卡片样式 */ |
| | | .file-card { |
| | | width: 100%; |
| | | min-height: 60px; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .file-content { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 8px; |
| | | } |
| | | |
| | | .file-icon { |
| | | font-size: 24px; |
| | | margin-right: 12px; |
| | | color: #409eff; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .file-info { |
| | | flex: 1; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .file-name { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | margin-bottom: 4px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .file-meta { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .file-actions { |
| | | text-align: center; |
| | | padding: 8px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | /* 备注样式 */ |
| | | .remark-content { |
| | | padding: 12px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-line; |
| | | } |
| | | |
| | | .detail-footer { |
| | |
| | | background-color: #f5f7fa; |
| | | font-weight: bold; |
| | | } |
| | | /* 转运信息样式 */ |
| | | .transport-info { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .transport-item { |
| | | margin-bottom: 8px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .transport-item strong { |
| | | display: inline-block; |
| | | width: 100px; |
| | | color: #606266; |
| | | } |
| | | </style> |
| | |
| | | </el-row> |
| | | |
| | | <!-- 数据表格 --> |
| | | <!-- 数据表格 --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="caseList" |
| | |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column |
| | | label="案例编号" |
| | | align="center" |
| | | prop="caseNo" |
| | | width="150" |
| | | fixed |
| | | /> |
| | | <el-table-column |
| | | label="上报时间" |
| | | align="center" |
| | | prop="reporttime" |
| | | width="160" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="捐献者姓名" |
| | | align="center" |
| | |
| | | width="100" |
| | | /> |
| | | <el-table-column label="性别" align="center" prop="sex" width="80"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="parseInt(scope.row.sex)" |
| | | /> |
| | | <template #default="scope"> |
| | | <dict-tag :options="dict.type.sys_user_sex" :value="scope.row.sex" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="年龄" align="center" prop="age" width="80" /> |
| | | <el-table-column label="血型" align="center" prop="bloodType" width="80"> |
| | | <template slot-scope="scope"> |
| | | <template #default="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BloodType" |
| | | :value="scope.row.bloodtype" |
| | | :value="scope.row.bloodType" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="GCS评分" |
| | | align="center" |
| | | prop="gscScore" |
| | | prop="gcsScore" |
| | | width="80" |
| | | show-overflow-tooltip |
| | | /> |
| | |
| | | prop="reportStatus" |
| | | width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.reportStatus | statusFilter"> |
| | | {{ scope.row.reportStatus | statusTextFilter }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="转运状态" align="center" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getTransportStatusTag(scope.row)"> |
| | | {{ getTransportStatusText(scope.row) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | align="center" |
| | | fixed="right" |
| | | class-name="small-padding fixed-width" |
| | | width="200" |
| | | width="350" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | |
| | | @click="handleDetail(scope.row)" |
| | | >详情</el-button |
| | | > |
| | | |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-edit" |
| | | @click="handleEdit(scope.row)" |
| | | v-if=" |
| | | scope.row.reportStatus !== '3' && |
| | | scope.row.reportStatus !== '4' && |
| | | scope.row.delFlag === 0 |
| | | " |
| | | >编辑</el-button |
| | | > |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-check" |
| | | @click="handleApprove(scope.row)" |
| | | v-if="scope.row.reportStatus === '2'" |
| | | v-if="scope.row.reportStatus === '2' && scope.row.delFlag === 0" |
| | | >审批</el-button |
| | | > |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-truck" |
| | | :type="shouldShowTransportButton(scope.row) ? 'primary' : 'text'" |
| | | @click="handleTransport(scope.row)" |
| | | v-if="shouldShowTransportButton(scope.row)" |
| | | :disabled="!canGoToTransport(scope.row)" |
| | | > |
| | | {{ getTransportButtonText(scope.row) }} |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <el-button type="primary" @click="submitApprove">确定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 新增/编辑案例弹框 --> |
| | | <el-dialog |
| | | :title="`${isEditing ? '编辑' : '新增'}案例`" |
| | | :visible.sync="editOpen" |
| | | width="68%" |
| | | append-to-body |
| | | :close-on-click-modal="false" |
| | | @close="handleEditClose" |
| | | > |
| | | <el-form |
| | | ref="editForm" |
| | | :model="editForm" |
| | | :rules="editRules" |
| | | label-width="120px" |
| | | > |
| | | <!-- 基本信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-user" |
| | | style="color: #409EFF; margin-right: 8px;" |
| | | ></i> |
| | | <span>基本信息</span> |
| | | </div> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="案例编号" prop="caseNo"> |
| | | <el-input |
| | | v-model="editForm.caseNo" |
| | | placeholder="请输入案例编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="捐献者姓名" prop="name"> |
| | | <el-input |
| | | v-model="editForm.name" |
| | | placeholder="请输入捐献者姓名" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="性别" prop="sex"> |
| | | <el-select |
| | | v-model="editForm.sex" |
| | | placeholder="请选择性别" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="男" value="0" /> |
| | | <el-option label="女" value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="年龄" prop="age"> |
| | | <el-input-number |
| | | v-model="editForm.age" |
| | | :min="0" |
| | | :max="120" |
| | | placeholder="请输入年龄" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="年龄单位" prop="ageunit"> |
| | | <el-select |
| | | v-model="editForm.ageunit" |
| | | placeholder="请选择年龄单位" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="岁" value="year" /> |
| | | <el-option label="月" value="month" /> |
| | | <el-option label="天" value="day" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="血型" prop="bloodType"> |
| | | <el-select |
| | | v-model="editForm.bloodType" |
| | | placeholder="请选择血型" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="A型" value="A" /> |
| | | <el-option label="B型" value="B" /> |
| | | <el-option label="O型" value="O" /> |
| | | <el-option label="AB型" value="AB" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="Rh阴性" prop="rhYin"> |
| | | <el-radio-group v-model="editForm.rhYin"> |
| | | <el-radio label="0">否</el-radio> |
| | | <el-radio label="1">是</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出生日期" prop="birthday"> |
| | | <el-date-picker |
| | | v-model="editForm.birthday" |
| | | type="date" |
| | | placeholder="选择出生日期" |
| | | value-format="yyyy-MM-dd" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="证件类型" prop="idcardtype"> |
| | | <el-select |
| | | v-model="editForm.idcardtype" |
| | | placeholder="请选择证件类型" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="身份证" value="1" /> |
| | | <el-option label="护照" value="2" /> |
| | | <el-option label="军官证" value="3" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="证件号码" prop="idcardno"> |
| | | <el-input |
| | | v-model="editForm.idcardno" |
| | | placeholder="请输入证件号码" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="民族" prop="nation"> |
| | | <el-input v-model="editForm.nation" placeholder="请输入民族" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="国籍" prop="nationality"> |
| | | <el-input |
| | | v-model="editForm.nationality" |
| | | placeholder="请输入国籍" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="籍贯" prop="nativeplace"> |
| | | <el-input |
| | | v-model="editForm.nativeplace" |
| | | placeholder="请输入籍贯" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="学历" prop="education"> |
| | | <el-input |
| | | v-model="editForm.education" |
| | | placeholder="请输入学历" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="职业" prop="occupation"> |
| | | <el-input |
| | | v-model="editForm.occupation" |
| | | placeholder="请输入职业" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系电话" prop="phone"> |
| | | <el-input |
| | | v-model="editForm.phone" |
| | | placeholder="请输入联系电话" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | |
| | | <!-- 地址信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-location-information" |
| | | style="color: #67C23A; margin-right: 8px;" |
| | | ></i> |
| | | <span>地址信息</span> |
| | | </div> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="户籍地址省"> |
| | | <el-input |
| | | v-model="editForm.registerprovincename" |
| | | placeholder="请输入户籍地址省" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="户籍地址市"> |
| | | <el-input |
| | | v-model="editForm.registercityname" |
| | | placeholder="请输入户籍地址市" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="户籍街道"> |
| | | <el-input |
| | | v-model="editForm.registertownname" |
| | | placeholder="请输入户籍街道" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="户籍社区"> |
| | | <el-input |
| | | v-model="editForm.registercommunityname" |
| | | placeholder="请输入户籍社区" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="户籍详细地址" prop="registeraddress"> |
| | | <el-input |
| | | v-model="editForm.registeraddress" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入详细的户籍地址" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-divider>现住地址</el-divider> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="现住地址省"> |
| | | <el-input |
| | | v-model="editForm.residenceprovincename" |
| | | placeholder="请输入现住地址省" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="现住地址市/区"> |
| | | <el-input |
| | | v-model="editForm.residencecountyname" |
| | | placeholder="请输入现住地址市/区" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="现住地址街道"> |
| | | <el-input |
| | | v-model="editForm.residencetownname" |
| | | placeholder="请输入现住地址街道" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="现住地址社区"> |
| | | <el-input |
| | | v-model="editForm.residencecommunityname" |
| | | placeholder="请输入现住地址社区" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="现住详细地址" prop="residenceaddress"> |
| | | <el-input |
| | | v-model="editForm.residenceaddress" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入详细的现住地址" |
| | | /> |
| | | </el-form-item> |
| | | </el-card> |
| | | |
| | | <!-- 医疗信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-first-aid-kit" |
| | | style="color: #E6A23C; margin-right: 8px;" |
| | | ></i> |
| | | <span>医疗信息</span> |
| | | </div> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="疾病诊断" prop="diagnosisname"> |
| | | <el-input |
| | | v-model="editForm.diagnosisname" |
| | | placeholder="请输入疾病诊断名称" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="GCS评分" prop="gcsScore"> |
| | | <el-input |
| | | v-model="editForm.gcsScore" |
| | | placeholder="请输入GCS评分" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="病情概况" prop="illnessoverview"> |
| | | <el-input |
| | | v-model="editForm.illnessoverview" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入病情概况" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="病人状况" prop="patientstate"> |
| | | <el-input |
| | | v-model="editForm.patientstate" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请输入病人状况" |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="传染病情况" prop="infectious"> |
| | | <el-input |
| | | v-model="editForm.infectious" |
| | | placeholder="请输入传染病情况" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="传染病其他说明"> |
| | | <el-input |
| | | v-model="editForm.infectiousOther" |
| | | placeholder="请输入传染病其他说明" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="是否需要转运" prop="isTransport"> |
| | | <el-radio-group v-model="editForm.isTransport"> |
| | | <el-radio label="1">不需要</el-radio> |
| | | <el-radio label="2">需要</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-card> |
| | | |
| | | <!-- 医院信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-office-building" |
| | | style="color: #909399; margin-right: 8px;" |
| | | ></i> |
| | | <span>医院信息</span> |
| | | </div> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="治疗医院" prop="treatmenthospitalname"> |
| | | <el-input |
| | | v-model="editForm.treatmenthospitalname" |
| | | placeholder="请输入治疗医院名称" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="治疗科室" prop="treatmentdeptname"> |
| | | <el-input |
| | | v-model="editForm.treatmentdeptname" |
| | | placeholder="请输入治疗科室名称" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="住院号" prop="inpatientno"> |
| | | <el-input |
| | | v-model="editForm.inpatientno" |
| | | placeholder="请输入住院号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="部门名称" prop="deptName"> |
| | | <el-input |
| | | v-model="editForm.deptName" |
| | | placeholder="请输入部门名称" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="部门编号" prop="deptNo"> |
| | | <el-input |
| | | v-model="editForm.deptNo" |
| | | placeholder="请输入部门编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="上报医院" prop="toHospital"> |
| | | <el-input |
| | | v-model="editForm.toHospital" |
| | | placeholder="请输入上报的医院" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | |
| | | <!-- 上报信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-s-data" |
| | | style="color: #F56C6C; margin-right: 8px;" |
| | | ></i> |
| | | <span>上报信息</span> |
| | | </div> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报告者姓名" prop="infoName"> |
| | | <el-input |
| | | v-model="editForm.infoName" |
| | | placeholder="请输入报告者姓名" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报告者编号" prop="infoNo"> |
| | | <el-input |
| | | v-model="editForm.infoNo" |
| | | placeholder="请输入报告者编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报告者电话" prop="reporterphone"> |
| | | <el-input |
| | | v-model="editForm.reporterphone" |
| | | placeholder="请输入报告者联系电话" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="协调员姓名" prop="coordinatorName"> |
| | | <el-input |
| | | v-model="editForm.coordinatorName" |
| | | placeholder="请输入协调员姓名" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="协调员编号" prop="coordinatorNo"> |
| | | <el-input |
| | | v-model="editForm.coordinatorNo" |
| | | placeholder="请输入协调员编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否终止案例" prop="terminationCase"> |
| | | <el-radio-group v-model="editForm.terminationCase"> |
| | | <el-radio label="0">进行中</el-radio> |
| | | <el-radio label="1">已终止</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="上报状态" prop="reportStatus"> |
| | | <el-select |
| | | v-model="editForm.reportStatus" |
| | | placeholder="请选择上报状态" |
| | | style="width: 100%" |
| | | :disabled="isEditing" |
| | | > |
| | | <el-option label="已上报" value="1" /> |
| | | <el-option label="已阅读" value="2" /> |
| | | <el-option label="已同意" value="3" /> |
| | | <el-option label="已驳回" value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-card> |
| | | |
| | | <!-- 附件信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-folder" |
| | | style="color: #409EFF; margin-right: 8px;" |
| | | ></i> |
| | | <span>附件信息</span> |
| | | </div> |
| | | |
| | | <div class="attachment-section"> |
| | | <div class="attachment-header"> |
| | | <i class="el-icon-paperclip"></i> |
| | | <span class="attachment-title">附件上传</span> |
| | | <span class="attachment-tip" |
| | | >支持上传病历、检验报告等文件 (最多{{ |
| | | attachmentLimit |
| | | }}个)</span |
| | | > |
| | | </div> |
| | | |
| | | <!-- 使用 UploadAttachment 组件 --> |
| | | <UploadAttachment |
| | | ref="uploadAttachment" |
| | | :file-list="attachmentFileList" |
| | | :limit="attachmentLimit" |
| | | :accept="attachmentAccept" |
| | | @change="handleAttachmentChange" |
| | | @upload-success="handleUploadSuccess" |
| | | @upload-error="handleUploadError" |
| | | @remove="handleAttachmentRemove" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- 附件列表 --> |
| | | <div |
| | | class="attachment-list" |
| | | v-if="editForm.annexfilesList && editForm.annexfilesList.length > 0" |
| | | > |
| | | <div class="list-title"> |
| | | 已上传附件 ({{ editForm.annexfilesList.length }}) |
| | | </div> |
| | | <el-table |
| | | :data="editForm.annexfilesList" |
| | | style="width: 100%" |
| | | size="small" |
| | | border |
| | | > |
| | | <el-table-column label="文件名" min-width="200"> |
| | | <template #default="scope"> |
| | | <i |
| | | class="el-icon-document" |
| | | style="margin-right: 8px; color: #409EFF;" |
| | | ></i> |
| | | <span class="file-name">{{ scope.row.fileName }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件类型" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag size="small">{{ |
| | | getFileType(scope.row.fileName) |
| | | }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="创建时间" width="160"> |
| | | <template #default="scope"> |
| | | <span>{{ formatDateTime(scope.row.createTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="备注" |
| | | min-width="150" |
| | | show-overflow-tooltip |
| | | > |
| | | <template #default="scope"> |
| | | <span>{{ scope.row.remart || "无" }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="200" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="primary" |
| | | @click="handlePreview(scope.row)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveAttachment(scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 备注信息 --> |
| | | <el-card class="form-section" shadow="never"> |
| | | <div slot="header" class="section-header"> |
| | | <i |
| | | class="el-icon-edit" |
| | | style="color: #67C23A; margin-right: 8px;" |
| | | ></i> |
| | | <span>备注信息</span> |
| | | </div> |
| | | <el-form-item prop="remark"> |
| | | <el-input |
| | | v-model="editForm.remark" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请输入备注信息" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-card> |
| | | </el-form> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="handleEditClose">取消</el-button> |
| | | <el-button type="primary" :loading="saveLoading" @click="handleSave" |
| | | >保存</el-button |
| | | > |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="previewVisible" |
| | | :file="currentPreviewFile" |
| | | @close="previewVisible = false" |
| | | @download="handleDownload" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import CaseDetail from "./caseDetail"; |
| | | import UploadAttachment from "@/components/UploadAttachment"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | import { |
| | | donateList, |
| | | donateInfo, |
| | | donateDel, |
| | | donateEdit |
| | | donateEdit, |
| | | donateAdd |
| | | } from "@/api/businessApi/index"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | export default { |
| | | name: "CaseList", |
| | | components: { CaseDetail }, |
| | | components: { |
| | | CaseDetail, |
| | | UploadAttachment, |
| | | FilePreviewDialog |
| | | }, |
| | | dicts: ["sys_user_sex", "sys_BloodType"], |
| | | data() { |
| | | return { |
| | | // 遮罩层 |
| | | loading: false, |
| | | saveLoading: false, |
| | | // 选中数组 |
| | | ids: [], |
| | | // 非单个禁用 |
| | |
| | | detailOpen: false, |
| | | // 审批弹框是否显示 |
| | | approveOpen: false, |
| | | // 编辑弹框是否显示 |
| | | editOpen: false, |
| | | // 编辑状态 |
| | | isEditing: false, |
| | | // 详情弹框标题 |
| | | detailTitle: "", |
| | | // 当前操作的案例 |
| | | currentCase: {}, |
| | | // 性别选项 |
| | | genderOptions: [ |
| | | { value: "0", label: "男" }, |
| | | { value: "1", label: "女" } |
| | | ], |
| | | // 血型选项 |
| | | bloodTypeOptions: [ |
| | | { value: "A", label: "A型" }, |
| | | { value: "B", label: "B型" }, |
| | | { value: "O", label: "O型" }, |
| | | { value: "AB", label: "AB型" } |
| | | ], |
| | | // 查询参数 |
| | | queryParams: { |
| | | pageNum: 1, |
| | |
| | | approveOpinion: [ |
| | | { required: true, message: "请输入审批意见", trigger: "blur" } |
| | | ] |
| | | } |
| | | }, |
| | | // 编辑表单 |
| | | editForm: this.getDefaultFormData(), |
| | | // 表单验证规则 |
| | | editRules: { |
| | | caseNo: [ |
| | | { required: true, message: "请输入案例编号", trigger: "blur" } |
| | | ], |
| | | name: [ |
| | | { required: true, message: "请输入捐献者姓名", trigger: "blur" } |
| | | ], |
| | | sex: [{ required: true, message: "请选择性别", trigger: "change" }], |
| | | age: [{ required: true, message: "请输入年龄", trigger: "blur" }], |
| | | diagnosisname: [ |
| | | { required: true, message: "请输入疾病诊断", trigger: "blur" } |
| | | ], |
| | | treatmenthospitalname: [ |
| | | { required: true, message: "请输入治疗医院", trigger: "blur" } |
| | | ], |
| | | reportStatus: [ |
| | | { required: true, message: "请选择上报状态", trigger: "change" } |
| | | ] |
| | | }, |
| | | // 附件相关配置 |
| | | attachmentLimit: 10, |
| | | attachmentAccept: ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx", |
| | | attachmentFileList: [], |
| | | // 预览相关 |
| | | previewVisible: false, |
| | | currentPreviewFile: null |
| | | }; |
| | | }, |
| | | filters: { |
| | |
| | | } catch (error) { |
| | | console.error("获取案例列表失败:", error); |
| | | this.$modal.msgError("获取案例列表失败"); |
| | | // 模拟数据 |
| | | this.caseList = this.getMockData(); |
| | | this.total = this.caseList.length; |
| | | this.caseList = []; |
| | | this.total = 0; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | /** 模拟数据 */ |
| | | getMockData() { |
| | | return [ |
| | | { |
| | | id: 1, |
| | | caseNo: "DON20241219001", |
| | | name: "张三", |
| | | sex: "0", |
| | | age: 38, |
| | | bloodType: "A", |
| | | gscScore: "1", |
| | | diagnosisname: |
| | | "脑外伤导致脑死亡,经抢救无效宣布脑死亡。家属同意器官捐献。", |
| | | treatmenthospitalname: "青岛大学附属医院", |
| | | reportStatus: "2", |
| | | reporttime: "2024-12-19 09:30:00", |
| | | reportername: "李医生", |
| | | idcardno: "370203198510123456", |
| | | nation: "汉族", |
| | | phone: "13800138000", |
| | | registeraddress: "山东省青岛市市南区香港中路100号", |
| | | inpatientno: "ZY20241219001", |
| | | treatmentdeptname: "神经外科", |
| | | doctorname: "王主任", |
| | | infectious: "无", |
| | | illnessoverview: |
| | | "患者因交通事故导致严重脑外伤,经抢救无效宣布脑死亡。", |
| | | hospitalLevel: "三级甲等", |
| | | contactperson: "张护士", |
| | | contactphone: "13900139000", |
| | | hospitalAddress: "山东省青岛市市南区江苏路1号" |
| | | // 转运------------------ |
| | | /** 判断是否需要显示转运按钮 */ |
| | | shouldShowTransportButton(row) { |
| | | // 只有已同意的案例才能进行转运操作 |
| | | // return row.reportStatus == "3" && row.delFlag == 0; |
| | | return row.reportStatus != "4"; |
| | | }, |
| | | { |
| | | id: 2, |
| | | caseNo: "DON20241218001", |
| | | name: "李四", |
| | | sex: "0", |
| | | age: 45, |
| | | bloodType: "O", |
| | | gscScore: "3", |
| | | diagnosisname: "急性心肌梗死,心脏功能衰竭", |
| | | treatmenthospitalname: "青岛市立医院", |
| | | reportStatus: "3", |
| | | reporttime: "2024-12-18 14:20:00", |
| | | approvetime: "2024-12-18 16:30:00", |
| | | reportername: "刘医生", |
| | | approvername: "审核专员A", |
| | | approveopinion: "资料齐全,符合捐献条件,同意通过。" |
| | | |
| | | /** 判断是否可以跳转到转运单 */ |
| | | canGoToTransport(row) { |
| | | // 需要转运(isTransport === "2")且没有转运信息(serviceTransport不存在或为空数组) |
| | | return row.isTransport == "2" && row.serviceTransport; |
| | | }, |
| | | |
| | | /** 获取转运按钮文本 */ |
| | | getTransportButtonText(row) { |
| | | if (row.isTransport == "2") { |
| | | if ( |
| | | row.serviceTransport && |
| | | Array.isArray(row.serviceTransport) && |
| | | row.serviceTransport.length > 0 |
| | | ) { |
| | | return "查看转运单"; |
| | | } else { |
| | | return "前往转运单"; |
| | | } |
| | | ]; |
| | | } |
| | | return "转运"; |
| | | }, |
| | | |
| | | /** 获取转运状态标签样式 */ |
| | | getTransportStatusTag(row) { |
| | | if (row.isTransport === "1") { |
| | | return "info"; // 不需要转运 |
| | | } |
| | | if ( |
| | | row.serviceTransport && |
| | | Array.isArray(row.serviceTransport) && |
| | | row.serviceTransport.length > 0 |
| | | ) { |
| | | // 根据转运单状态显示不同颜色 |
| | | const transport = row.serviceTransport[0]; |
| | | if (transport.transitStatus) { |
| | | switch (transport.transitStatus.toString()) { |
| | | case "1": |
| | | return "warning"; // 待转运 |
| | | case "2": |
| | | return "primary"; // 转运中 |
| | | case "3": |
| | | return "success"; // 转运完成 |
| | | case "4": |
| | | return "danger"; // 转运取消 |
| | | case "5": |
| | | return "info"; // 暂存 |
| | | default: |
| | | return "info"; |
| | | } |
| | | } |
| | | return "primary"; // 有转运信息但无状态 |
| | | } |
| | | return "danger"; // 需要转运但无转运信息 |
| | | }, |
| | | |
| | | /** 获取转运状态文本 */ |
| | | getTransportStatusText(row) { |
| | | if (row.isTransport === "1") { |
| | | return "无需转运"; |
| | | } |
| | | if ( |
| | | row.serviceTransport && |
| | | Array.isArray(row.serviceTransport) && |
| | | row.serviceTransport.length > 0 |
| | | ) { |
| | | const transport = row.serviceTransport[0]; |
| | | if (transport.transitStatus) { |
| | | switch (transport.transitStatus.toString()) { |
| | | case "1": |
| | | return "待转运"; |
| | | case "2": |
| | | return "转运中"; |
| | | case "3": |
| | | return "转运完成"; |
| | | case "4": |
| | | return "转运取消"; |
| | | case "5": |
| | | return "暂存"; |
| | | default: |
| | | return "有转运单"; |
| | | } |
| | | } |
| | | return "有转运单"; |
| | | } |
| | | return "需转运"; |
| | | }, |
| | | |
| | | /** 处理转运操作 */ |
| | | async handleTransport(row) { |
| | | try { |
| | | // 先获取最新的案例信息 |
| | | const caseData = row; |
| | | |
| | | if (caseData.isTransport == "2") { |
| | | if ( |
| | | caseData.serviceTransport && |
| | | Array.isArray(caseData.serviceTransport) && |
| | | caseData.serviceTransport.length > 0 |
| | | ) { |
| | | // 已有转运单,跳转到转运单详情页 |
| | | const transport = caseData.serviceTransport[0]; |
| | | this.goToTransportDetail(transport.id, row.caseNo); |
| | | } else { |
| | | // 没有转运单,跳转到创建转运单页面 |
| | | this.goToCreateTransport(row); |
| | | } |
| | | } else { |
| | | this.$message.warning("该案例不需要转运"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取案例信息失败:", error); |
| | | this.$message.error("获取案例信息失败"); |
| | | } |
| | | }, |
| | | |
| | | /** 跳转到创建转运单页面 */ |
| | | goToCreateTransport(caseData) { |
| | | // 这里可以跳转到创建转运单的页面 |
| | | // 方式1:在新页面打开 |
| | | this.$router.push({ |
| | | path: "/report/transfer", |
| | | query: { |
| | | autoCreate: "true", |
| | | caseId: caseData.id, |
| | | caseNo: caseData.caseNo, |
| | | patName: caseData.name, |
| | | age: caseData.age, |
| | | sex: caseData.sex, |
| | | diagnosisname: caseData.diagnosisname, |
| | | treatmentHospitalName: caseData.treatmenthospitalname |
| | | } |
| | | }); |
| | | |
| | | // 方式2:在当前页面打开弹框(推荐) |
| | | // this.openTransportDialog(caseData); |
| | | }, |
| | | |
| | | /** 打开转运单弹框 */ |
| | | openTransportDialog(caseData) { |
| | | this.$modal.confirm({ |
| | | title: "创建转运单", |
| | | message: `您将创建案例【${caseData.caseNo} - ${caseData.name}】的转运单,是否继续?`, |
| | | confirmButtonText: "前往创建", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | beforeClose: (action, instance, done) => { |
| | | if (action === "confirm") { |
| | | // 跳转到转运单创建页面 |
| | | this.$router.push({ |
| | | path: "/report/transfer", |
| | | query: { |
| | | caseId: caseData.id, |
| | | caseNo: caseData.caseNo, |
| | | patName: caseData.name, |
| | | age: caseData.age, |
| | | sex: caseData.sex, |
| | | diagnosisname: caseData.diagnosisname, |
| | | treatmentHospitalName: caseData.treatmenthospitalname |
| | | } |
| | | }); |
| | | done(); |
| | | } else { |
| | | done(); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** 跳转到转运单详情页 */ |
| | | goToTransportDetail(transportId, caseNo) { |
| | | this.$router.push({ |
| | | path: "/report/transfer", |
| | | query: { |
| | | id: transportId, |
| | | caseNo: caseNo |
| | | } |
| | | }); |
| | | }, |
| | | // ---------------------------------end |
| | | // 多选框选中数据 |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map(item => item.id); |
| | |
| | | |
| | | /** 重置按钮操作 */ |
| | | resetQuery() { |
| | | this.resetForm("queryForm"); |
| | | this.handleQuery(); |
| | | this.queryParams = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | caseNo: undefined, |
| | | name: undefined, |
| | | reportStatus: undefined |
| | | }; |
| | | this.getList(); |
| | | }, |
| | | |
| | | /** 详情按钮操作 */ |
| | | async handleDetail(row) { |
| | | try { |
| | | // 先获取案例详情 |
| | | const response = await donateInfo(row.id); |
| | | this.currentCase = response.data || response || row; |
| | | this.currentCase = row; |
| | | |
| | | // 如果状态是"已上报"(1),则使用完整数据更新为"已阅读"(2) |
| | | // 如果状态是"已上报"(1),则更新为"已阅读"(2) |
| | | if (this.currentCase.reportStatus === "1") { |
| | | try { |
| | | // 使用完整的案例数据作为更新基础,确保所有字段都被保留 |
| | | const updateData = { |
| | | ...this.currentCase, // 展开所有现有字段 |
| | | reportStatus: "2", // 更新状态为已阅读 |
| | | updateTime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19), |
| | | updateBy: "当前用户" // 添加更新人信息 |
| | | ...this.currentCase, |
| | | reportStatus: "2", |
| | | updateTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | updateBy: this.$store.state.user?.name || "当前用户" |
| | | }; |
| | | |
| | | await donateEdit(updateData); |
| | | |
| | | // 更新本地数据和当前显示的数据 |
| | | this.currentCase.reportStatus = "2"; |
| | | this.currentCase.updateTime = updateData.updateTime; |
| | | row.reportStatus = "2"; // 更新列表中的状态 |
| | | |
| | | row.reportStatus = "2"; |
| | | this.$modal.msgSuccess("状态已更新为已阅读"); |
| | | } catch (updateError) { |
| | | console.error("状态更新失败:", updateError); |
| | | this.$modal.msgError("状态更新失败,但将继续显示详情"); |
| | | // 更新失败时,继续使用原始状态显示详情 |
| | | } |
| | | } |
| | | |
| | | this.detailTitle = `案例详情 - ${this.currentCase.caseNo || |
| | | row.caseNo}`; |
| | | this.detailOpen = true; |
| | | console.log(this.currentCase, "this.currentCase"); |
| | | } catch (error) { |
| | | console.error("获取案例详情失败:", error); |
| | | // 如果获取详情失败,使用行数据作为后备 |
| | | this.currentCase = row; |
| | | this.detailTitle = `案例详情 - ${row.caseNo}`; |
| | | this.detailOpen = true; |
| | | } |
| | | }, |
| | | |
| | | // 即使获取详情失败,也尝试更新状态(使用行数据) |
| | | if (row.reportStatus === "1") { |
| | | /** 编辑按钮操作 */ |
| | | async handleEdit(row) { |
| | | try { |
| | | const updateData = { |
| | | id: row.id, |
| | | reportStatus: "2", |
| | | updateTime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19), |
| | | updateBy: "当前用户" |
| | | // 注意:这里只能传递部分字段,因为详情获取失败了 |
| | | }; |
| | | const response = await donateInfo(row.id); |
| | | if (response.code === 200 || response.data) { |
| | | this.isEditing = true; |
| | | const data = response.data || response; |
| | | |
| | | await donateEdit(updateData); |
| | | row.reportStatus = "2"; |
| | | this.currentCase.reportStatus = "2"; |
| | | this.$modal.msgSuccess("状态已更新为已阅读"); |
| | | } catch (updateError) { |
| | | console.error("状态更新失败:", updateError); |
| | | // 处理附件 |
| | | if (data.annexfilesList) { |
| | | this.attachmentFileList = this.parseAttachmentToFileList( |
| | | data.annexfilesList |
| | | ); |
| | | } else { |
| | | this.attachmentFileList = []; |
| | | } |
| | | |
| | | this.currentCase = data; |
| | | this.editForm = { ...data }; |
| | | this.editOpen = true; |
| | | this.$nextTick(() => { |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | | }); |
| | | } else { |
| | | this.$message.error(response.msg || "获取记录失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取记录失败:", error); |
| | | this.$modal.msgError("获取记录失败"); |
| | | } |
| | | }, |
| | | |
| | | /** 新增按钮操作 */ |
| | | handleAdd() { |
| | | this.isEditing = false; |
| | | this.editForm = this.getDefaultFormData(); |
| | | this.attachmentFileList = []; |
| | | this.editOpen = true; |
| | | this.$nextTick(() => { |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | | }); |
| | | }, |
| | | |
| | | /** 审批按钮操作 */ |
| | | async handleApprove(row) { |
| | | try { |
| | | // 先获取案例详情数据,确保有完整数据 |
| | | const response = await donateInfo(row.id); |
| | | this.currentCase = response.data || response || row; |
| | | |
| | |
| | | this.approveOpen = true; |
| | | } catch (error) { |
| | | console.error("获取案例详情失败:", error); |
| | | // 如果获取详情失败,使用行数据作为后备 |
| | | this.currentCase = row; |
| | | this.approveForm.id = row.id; |
| | | this.approveForm.approveResult = "3"; |
| | |
| | | try { |
| | | const valid = await this.$refs.approveForm.validate(); |
| | | if (valid) { |
| | | // 使用完整的案例数据作为基础,确保所有字段都被保留 |
| | | const approveData = { |
| | | ...this.currentCase, // 展开所有现有字段 |
| | | ...this.currentCase, |
| | | reportStatus: this.approveForm.approveResult, |
| | | approveOpinion: this.approveForm.approveOpinion, |
| | | approvername: "当前用户", // 实际项目中应该获取当前登录用户 |
| | | approvetime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19), |
| | | updateTime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19), |
| | | updateBy: "当前用户" |
| | | remark: this.approveForm.approveOpinion, |
| | | approvername: this.$store.state.user?.name || "当前用户", |
| | | approvetime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | updateTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | updateBy: this.$store.state.user?.name || "当前用户" |
| | | }; |
| | | |
| | | // 移除可能不需要的字段(根据实际API需求调整) |
| | | delete approveData.createTime; // 创建时间不应被更新 |
| | | delete approveData.createBy; // 创建人不应变 |
| | | |
| | | await donateEdit(approveData); |
| | | this.$modal.msgSuccess("审批成功"); |
| | | this.approveOpen = false; |
| | | this.getList(); // 重新加载列表 |
| | | this.getList(); |
| | | } |
| | | } catch (error) { |
| | | console.error("审批失败:", error); |
| | |
| | | this.$modal.msgError("审批失败"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** 新增按钮操作 */ |
| | | handleAdd() { |
| | | this.$router.push("/case/add"); |
| | | }, |
| | | |
| | | /** 删除按钮操作 */ |
| | |
| | | this.$modal.msgError("删除失败"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** 获取默认表单数据 */ |
| | | getDefaultFormData() { |
| | | return { |
| | | id: undefined, |
| | | caseNo: undefined, |
| | | name: undefined, |
| | | sex: undefined, |
| | | age: undefined, |
| | | ageunit: "year", |
| | | bloodType: undefined, |
| | | rhYin: "0", |
| | | birthday: undefined, |
| | | idcardtype: "1", |
| | | idcardno: undefined, |
| | | nation: undefined, |
| | | nationality: undefined, |
| | | nativeplace: undefined, |
| | | education: undefined, |
| | | occupation: undefined, |
| | | phone: undefined, |
| | | // 户籍地址 |
| | | registerprovincename: undefined, |
| | | registercityname: undefined, |
| | | registertownname: undefined, |
| | | registercommunityname: undefined, |
| | | registeraddress: undefined, |
| | | // 现住地址 |
| | | residenceprovincename: undefined, |
| | | residencecountyname: undefined, |
| | | residencetownname: undefined, |
| | | residencecommunityname: undefined, |
| | | residenceaddress: undefined, |
| | | // 医疗信息 |
| | | diagnosisname: undefined, |
| | | illnessoverview: undefined, |
| | | patientstate: undefined, |
| | | gcsScore: undefined, |
| | | infectious: undefined, |
| | | infectiousOther: undefined, |
| | | isTransport: "1", |
| | | // 医院信息 |
| | | treatmenthospitalname: undefined, |
| | | treatmentdeptname: undefined, |
| | | inpatientno: undefined, |
| | | deptName: undefined, |
| | | deptNo: undefined, |
| | | toHospital: undefined, |
| | | // 上报信息 |
| | | infoName: undefined, |
| | | infoNo: undefined, |
| | | reporterphone: undefined, |
| | | coordinatorName: undefined, |
| | | coordinatorNo: undefined, |
| | | terminationCase: "0", |
| | | reportStatus: "1", // 默认已上报 |
| | | // 附件 |
| | | annexfilesList: [], |
| | | // 其他 |
| | | remark: undefined, |
| | | createBy: undefined, |
| | | createTime: undefined, |
| | | updateBy: undefined, |
| | | updateTime: undefined, |
| | | delFlag: 0 |
| | | }; |
| | | }, |
| | | |
| | | /** 附件转换 */ |
| | | parseAttachmentToFileList(attachments) { |
| | | if (!attachments || !Array.isArray(attachments)) return []; |
| | | return attachments.map((item, index) => ({ |
| | | uid: item.id || `attachment-${index}-${Date.now()}`, |
| | | name: item.fileName, |
| | | url: item.path || item.fileUrl, |
| | | status: "success", |
| | | raw: item |
| | | })); |
| | | }, |
| | | |
| | | /** 附件变化处理 */ |
| | | handleAttachmentChange(fileList) { |
| | | this.attachmentFileList = fileList; |
| | | }, |
| | | |
| | | /** 附件上传成功处理 */ |
| | | handleUploadSuccess({ file, fileList, response }) { |
| | | if (response && response.code === 200) { |
| | | if (!this.editForm.annexfilesList) { |
| | | this.editForm.annexfilesList = []; |
| | | } |
| | | const attachmentObj = { |
| | | fileName: file.name, |
| | | path: response.data || file.url, |
| | | fileUrl: response.data || file.url, |
| | | type: this.getFileExtension(file.name), |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | remart: file.raw?.remart || "", |
| | | caseNo: this.editForm.caseNo |
| | | }; |
| | | |
| | | this.editForm.annexfilesList.push(attachmentObj); |
| | | this.$message.success("文件上传成功"); |
| | | } |
| | | }, |
| | | |
| | | /** 附件上传错误处理 */ |
| | | handleUploadError({ file, fileList, error }) { |
| | | console.error("附件上传失败:", error); |
| | | this.$message.error("文件上传失败,请重试"); |
| | | }, |
| | | |
| | | /** 附件移除处理 */ |
| | | handleAttachmentRemove(file) { |
| | | if (file.url && this.editForm.annexfilesList) { |
| | | const index = this.editForm.annexfilesList.findIndex( |
| | | item => item.path === file.url || item.fileUrl === file.url |
| | | ); |
| | | if (index > -1) { |
| | | this.editForm.annexfilesList.splice(index, 1); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** 手动删除附件 */ |
| | | handleRemoveAttachment(index) { |
| | | this.editForm.annexfilesList.splice(index, 1); |
| | | this.attachmentFileList.splice(index, 1); |
| | | this.$message.success("附件删除成功"); |
| | | }, |
| | | |
| | | /** 文件预览 */ |
| | | handlePreview(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.fileName, |
| | | fileUrl: file.path || file.fileUrl, |
| | | fileType: this.getFileType(file.fileName) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | |
| | | /** 文件下载 */ |
| | | handleDownload(file) { |
| | | const fileUrl = file.path || file.fileUrl; |
| | | const fileName = file.fileName; |
| | | |
| | | if (fileUrl) { |
| | | const link = document.createElement("a"); |
| | | link.href = fileUrl; |
| | | link.download = fileName; |
| | | link.style.display = "none"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | this.$message.success("开始下载文件"); |
| | | } else { |
| | | this.$message.warning("文件路径不存在,无法下载"); |
| | | } |
| | | }, |
| | | |
| | | /** 获取文件类型 */ |
| | | getFileType(fileName) { |
| | | if (!fileName) return "other"; |
| | | const extension = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"]; |
| | | const pdfTypes = ["pdf"]; |
| | | const officeTypes = ["doc", "docx", "xls", "xlsx"]; |
| | | |
| | | if (imageTypes.includes(extension)) return "image"; |
| | | if (pdfTypes.includes(extension)) return "pdf"; |
| | | if (officeTypes.includes(extension)) return "office"; |
| | | return "other"; |
| | | }, |
| | | |
| | | /** 获取文件扩展名 */ |
| | | getFileExtension(filename) { |
| | | if (!filename) return ""; |
| | | return filename |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | }, |
| | | |
| | | /** 日期时间格式化 */ |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return ""; |
| | | return dayjs(dateTime).format("YYYY-MM-DD HH:mm:ss"); |
| | | }, |
| | | |
| | | /** 关闭编辑对话框 */ |
| | | handleEditClose() { |
| | | this.editOpen = false; |
| | | this.currentCase = {}; |
| | | this.editForm = this.getDefaultFormData(); |
| | | this.attachmentFileList = []; |
| | | this.$nextTick(() => { |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | | }); |
| | | }, |
| | | |
| | | /** 保存表单 */ |
| | | async handleSave() { |
| | | try { |
| | | const valid = await this.$refs.editForm.validate(); |
| | | if (!valid) return; |
| | | |
| | | const pendingFiles = this.attachmentFileList.filter( |
| | | item => item.status !== "success" |
| | | ); |
| | | if (pendingFiles.length > 0) { |
| | | this.$message.warning( |
| | | "还有文件未上传完成,请先上传所有文件或移除未上传的文件" |
| | | ); |
| | | return; |
| | | } |
| | | |
| | | this.saveLoading = true; |
| | | |
| | | const requestData = { ...this.editForm }; |
| | | let response; |
| | | |
| | | if (this.isEditing) { |
| | | response = await donateEdit(requestData); |
| | | } else { |
| | | // 新增时设置创建信息 |
| | | requestData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | requestData.createBy = this.$store.state.user?.name || "当前用户"; |
| | | response = await donateAdd(requestData); |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | this.$message.success(this.isEditing ? "修改成功" : "新增成功"); |
| | | this.handleEditClose(); |
| | | this.getList(); |
| | | } else { |
| | | this.$message.error(response.msg || "操作失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("保存失败:", error); |
| | | this.$message.error("操作失败,请稍后重试"); |
| | | } finally { |
| | | this.saveLoading = false; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .filter-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .mb8 { |
| | | margin-bottom: 8px; |
| | | } |
| | | /* 详情页面样式优化 */ |
| | | .case-detail-container { |
| | | max-height: 70vh; |
| | | overflow-y: auto; |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .detail-section { |
| | | /* 表单区域样式 */ |
| | | .form-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | padding: 20px 0 0; |
| | | } |
| | | |
| | | /* 附件样式 */ |
| | | .attachment-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .attachment-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 16px; |
| | | padding: 8px 0; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .attachment-title { |
| | | font-weight: bold; |
| | | margin: 0 8px; |
| | | } |
| | | |
| | | .attachment-tip { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .attachment-list { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .list-title { |
| | | font-weight: bold; |
| | | margin-bottom: 12px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .file-name { |
| | | font-size: 13px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | /* 审批弹框样式 */ |
| | | .approve-dialog >>> .el-dialog__body { |
| | | padding: 0; |
| | |
| | | :close-on-click-modal="false" |
| | | @close="handleClose" |
| | | > |
| | | <!-- 案例信息展示区域 --> |
| | | <div v-if="selectedCase && !isEdit" class="selected-case-info"> |
| | | <el-alert |
| | | title="关联案例信息" |
| | | type="success" |
| | | :closable="false" |
| | | style="margin-bottom: 16px;" |
| | | /> |
| | | <el-card shadow="never" class="case-info-card"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="案例编号">{{ selectedCase.caseNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="患者姓名">{{ selectedCase.name }}</el-descriptions-item> |
| | | <el-descriptions-item label="性别"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="selectedCase.sex" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="年龄">{{ selectedCase.age }}</el-descriptions-item> |
| | | <el-descriptions-item label="疾病诊断">{{ selectedCase.diagnosisname }}</el-descriptions-item> |
| | | <el-descriptions-item label="治疗医院">{{ selectedCase.treatmenthospitalname }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <el-form |
| | | ref="editForm" |
| | | :model="formData" |
| | |
| | | <el-form-item label="案例编号" prop="caseNo"> |
| | | <el-input |
| | | v-model="formData.caseNo" |
| | | placeholder="请输入案例编号" |
| | | :disabled="true" |
| | | placeholder="自动从案例获取" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-form-item label="患者姓名" prop="patName"> |
| | | <el-input |
| | | v-model="formData.patName" |
| | | placeholder="请输入患者姓名" |
| | | :disabled="true" |
| | | placeholder="自动从案例获取" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-form-item label="性别" prop="sex"> |
| | | <el-select |
| | | v-model="formData.sex" |
| | | :disabled="true" |
| | | placeholder="请选择性别" |
| | | style="width: 100%" |
| | | > |
| | |
| | | v-model="formData.age" |
| | | :min="0" |
| | | :max="120" |
| | | placeholder="请输入年龄" |
| | | :disabled="true" |
| | | placeholder="自动从案例获取" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | |
| | | <el-form-item label="疾病诊断" prop="diagnosisname"> |
| | | <el-input |
| | | v-model="formData.diagnosisname" |
| | | placeholder="请输入疾病诊断名称" |
| | | :disabled="true" |
| | | placeholder="自动从案例获取" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-form-item label="治疗医院" prop="treatmentHospitalName"> |
| | | <el-input |
| | | v-model="formData.treatmentHospitalName" |
| | | placeholder="请输入治疗医院名称" |
| | | :disabled="true" |
| | | placeholder="自动从案例获取" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | UploadAttachment, |
| | | FilePreviewDialog |
| | | }, |
| | | dicts: ["sys_user_sex", "sys_BloodType"], |
| | | props: { |
| | | editOpen: { |
| | | type: Boolean, |
| | |
| | | isEdit: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | selectedCase: { |
| | | type: Object, |
| | | default: null |
| | | } |
| | | }, |
| | | data() { |
| | |
| | | watch: { |
| | | editOpen(val) { |
| | | if (val) { |
| | | this.formData = this.isEdit |
| | | ? { ...this.getDefaultFormData(), ...this.transportData } |
| | | : this.getDefaultFormData(); |
| | | if (this.isEdit) { |
| | | // 编辑模式,使用传入的转运单数据 |
| | | this.formData = { ...this.getDefaultFormData(), ...this.transportData }; |
| | | } else { |
| | | // 新增模式 |
| | | this.formData = this.getDefaultFormData(); |
| | | |
| | | // 如果有选中的案例,用案例信息填充表单 |
| | | if (this.selectedCase) { |
| | | this.fillFormWithCaseData(this.selectedCase); |
| | | } |
| | | } |
| | | |
| | | this.initAttachmentList(); |
| | | |
| | |
| | | this.$refs.editForm && this.$refs.editForm.clearValidate(); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | selectedCase: { |
| | | handler(newVal) { |
| | | if (newVal && !this.isEdit) { |
| | | this.fillFormWithCaseData(newVal); |
| | | } |
| | | }, |
| | | deep: true |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | updateBy: undefined, |
| | | updateTime: undefined, |
| | | delFlag: 0 |
| | | }; |
| | | }, |
| | | |
| | | /** 用案例数据填充表单 */ |
| | | fillFormWithCaseData(caseData) { |
| | | this.formData = { |
| | | ...this.formData, |
| | | caseNo: caseData.caseNo || '', |
| | | patName: caseData.name || '', |
| | | sex: caseData.sex || '', |
| | | age: caseData.age || '', |
| | | diagnosisname: caseData.diagnosisname || '', |
| | | treatmentHospitalName: caseData.treatmenthospitalname || '', |
| | | treatmentDeptName: caseData.treatmentdeptname || '', |
| | | // 可以设置一些默认值 |
| | | transportStartPlace: caseData.treatmenthospitalname || '', |
| | | contactPerson: caseData.coordinatorName || '' |
| | | }; |
| | | }, |
| | | |
| | |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .file-path { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | /* 案例信息展示样式 */ |
| | | .selected-case-info { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-card__header { |
| | | background: #f5f7fa; |
| | | border-bottom: 1px solid #ebeef5; |
| | | .case-info-card { |
| | | border-left: 4px solid #67c23a; |
| | | } |
| | | </style> |
| | |
| | | @close="detailOpen = false" |
| | | /> |
| | | </el-dialog> |
| | | |
| | | <!-- 案例选择对话框 --> |
| | | <el-dialog |
| | | title="选择转运案例" |
| | | :visible.sync="selectCaseOpen" |
| | | width="900px" |
| | | append-to-body |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="case-select-container"> |
| | | <el-card class="search-card"> |
| | | <el-form :model="caseQueryParams" inline> |
| | | <el-form-item label="案例编号"> |
| | | <el-input |
| | | v-model="caseQueryParams.caseNo" |
| | | placeholder="请输入案例编号" |
| | | clearable |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="患者姓名"> |
| | | <el-input |
| | | v-model="caseQueryParams.patName" |
| | | placeholder="请输入患者姓名" |
| | | clearable |
| | | style="width: 150px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="el-icon-search" @click="searchCaseList" |
| | | >搜索</el-button |
| | | > |
| | | <el-button icon="el-icon-refresh" @click="resetCaseSearch" |
| | | >重置</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <el-card> |
| | | <el-table |
| | | v-loading="caseLoading" |
| | | :data="availableCaseList" |
| | | @row-click="handleCaseSelect" |
| | | highlight-current-row |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column label="案例编号" prop="caseNo" width="150" align="center" /> |
| | | <el-table-column label="患者姓名" prop="name" width="120" align="center" /> |
| | | <el-table-column label="性别" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_user_sex" |
| | | :value="scope.row.sex" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="年龄" prop="age" width="80" align="center" /> |
| | | <el-table-column label="血型" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BloodType" |
| | | :value="scope.row.bloodType" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="疾病诊断" prop="diagnosisname" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column label="治疗医院" prop="treatmenthospitalname" width="150" /> |
| | | <el-table-column label="是否已转运" width="100" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="hasTransport(scope.row) ? 'danger' : 'success'" |
| | | size="small" |
| | | > |
| | | {{ hasTransport(scope.row) ? '已转运' : '可转运' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="80" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="selectCase(scope.row)" |
| | | :disabled="hasTransport(scope.row)" |
| | | > |
| | | 选择 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- 分页 --> |
| | | <pagination |
| | | v-show="caseTotal > 0" |
| | | :total="caseTotal" |
| | | :page.sync="caseQueryParams.pageNum" |
| | | :limit.sync="caseQueryParams.pageSize" |
| | | @pagination="searchCaseList" |
| | | /> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="selectCaseOpen = false">取消</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 新增:修改弹框 --> |
| | | <transport-edit |
| | | :edit-open="editOpen" |
| | | :transport-data="currentTransport" |
| | | :is-edit="isEditing" |
| | | :selected-case="selectedCase" |
| | | @update:edit-open="editOpen = $event" |
| | | @close="handleEditClose" |
| | | @save-success="handleSaveSuccess" |
| | |
| | | transportAdd, |
| | | transportEdit, |
| | | transportDelete, |
| | | transportInfo |
| | | transportInfo, |
| | | donateList |
| | | } from "@/api/businessApi/index"; |
| | | import TransportDetail from "./transportDetail"; |
| | | import TransportEdit from "./TransportEdit"; |
| | |
| | | dicts: ["sys_user_sex", "sys_BloodType"], |
| | | data() { |
| | | return { |
| | | |
| | | // 遮罩层 |
| | | loading: false, |
| | | // 选中数组 |
| | |
| | | showSearch: true, |
| | | // 总条数 |
| | | total: 0, |
| | | // 转运单表格数据 - 直接使用后端返回的数据结构 |
| | | // 转运单表格数据 |
| | | transportList: [], |
| | | // 详情弹框是否显示 |
| | | detailOpen: false, |
| | | // 案例选择弹框是否显示 |
| | | selectCaseOpen: false, |
| | | // 操作确认弹框是否显示 |
| | | actionOpen: false, |
| | | // 新增:修改弹框相关数据 |
| | |
| | | pendingTransports: 0, |
| | | completedTransports: 0 |
| | | }, |
| | | // 查询参数(完全适配后端接口) |
| | | // 查询参数 |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | caseNo: undefined, // 案例编号 |
| | | patName: undefined, // 患者姓名 |
| | | transitStatus: undefined, // 转运状态:1待转运 2转运中 3转运完成 4转运取消 5暂存 |
| | | searchValue: undefined, // 搜索值 |
| | | params: {} // 其他参数对象 |
| | | caseNo: undefined, |
| | | patName: undefined, |
| | | transitStatus: undefined, |
| | | searchValue: undefined, |
| | | params: {} |
| | | }, |
| | | // 案例选择相关 |
| | | caseLoading: false, |
| | | availableCaseList: [], |
| | | caseTotal: 0, |
| | | selectedCase: null, |
| | | caseQueryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | caseNo: undefined, |
| | | patName: undefined, |
| | | // 只查询已同意且需要转运的案例 |
| | | // reportStatus: "3", // 已同意 |
| | | isTransport: "2" // 需要转运 |
| | | } |
| | | }; |
| | | }, |
| | | created() { |
| | | this.getList(); |
| | | this.checkAutoCreate(); |
| | | }, |
| | | methods: { |
| | | /** 查询转运单列表 - 直接使用后端数据结构 */ |
| | | /** 查询转运单列表 */ |
| | | async getList() { |
| | | this.loading = true; |
| | | |
| | | try { |
| | | // 构建符合后端接口的请求参数 [1,2](@ref) |
| | | const requestParams = { |
| | | pageNum: this.queryParams.pageNum, |
| | | pageSize: this.queryParams.pageSize, |
| | |
| | | searchValue: this.queryParams.searchValue |
| | | }; |
| | | |
| | | // 处理时间范围参数 [5](@ref) |
| | | if (this.dateRange && this.dateRange.length === 2) { |
| | | requestParams.transportStartTime = this.dateRange.join(","); |
| | | } |
| | | |
| | | // 调用正式接口 [3](@ref) |
| | | const response = await transportList(requestParams); |
| | | |
| | | if (response.code === 200) { |
| | | // 直接使用后端返回的数据结构,不进行转换 [8](@ref) |
| | | this.transportList = response.rows || response.data || []; |
| | | this.total = response.total || 0; |
| | | |
| | | // 更新统计数据 |
| | | this.updateStats(); |
| | | } else { |
| | | this.$modal.msgError(response.msg || "获取转运单列表失败"); |
| | |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | checkAutoCreate() { |
| | | const query = this.$route.query; |
| | | if (query.autoCreate === 'true') { |
| | | // 自动打开案例选择弹框 |
| | | this.selectCaseOpen = true; |
| | | this.resetCaseSearch(); |
| | | |
| | | // 如果有特定的案例编号,可以预先搜索 |
| | | if (query.caseNo) { |
| | | this.caseQueryParams.caseNo = query.caseNo; |
| | | this.searchCaseList(); |
| | | } |
| | | } |
| | | }, |
| | | /** 搜索可用案例 */ |
| | | async searchCaseList() { |
| | | this.caseLoading = true; |
| | | try { |
| | | const response = await donateList(this.caseQueryParams); |
| | | if (response.code === 200) { |
| | | this.availableCaseList = response.rows || response.data || []; |
| | | this.caseTotal = response.total || 0; |
| | | } else { |
| | | this.$modal.msgError(response.msg || "获取案例列表失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取案例列表失败:", error); |
| | | this.$modal.msgError("获取案例列表失败"); |
| | | } finally { |
| | | this.caseLoading = false; |
| | | } |
| | | }, |
| | | |
| | | /** 重置案例搜索 */ |
| | | resetCaseSearch() { |
| | | this.caseQueryParams = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | caseNo: undefined, |
| | | patName: undefined, |
| | | // reportStatus: "3", |
| | | isTransport: "2" |
| | | }; |
| | | this.searchCaseList(); |
| | | }, |
| | | |
| | | /** 判断案例是否已有转运单 */ |
| | | hasTransport(caseData) { |
| | | // 检查案例是否有转运信息 |
| | | if (caseData.serviceTransport && |
| | | Array.isArray(caseData.serviceTransport) && |
| | | caseData.serviceTransport.length > 0) { |
| | | return true; |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | /** 选择案例 */ |
| | | selectCase(caseData) { |
| | | if (this.hasTransport(caseData)) { |
| | | this.$message.warning("该案例已有转运单,请选择其他案例"); |
| | | return; |
| | | } |
| | | |
| | | this.selectedCase = caseData; |
| | | this.selectCaseOpen = false; |
| | | |
| | | // 打开转运单编辑页面,并传入选中的案例 |
| | | this.currentTransport = this.convertCaseToTransport(caseData); |
| | | this.isEditing = false; |
| | | this.editOpen = true; |
| | | }, |
| | | |
| | | /** 将案例信息转换为转运单格式 */ |
| | | convertCaseToTransport(caseData) { |
| | | return { |
| | | caseNo: caseData.caseNo, |
| | | patName: caseData.name, |
| | | sex: caseData.sex, |
| | | age: caseData.age, |
| | | diagnosisname: caseData.diagnosisname, |
| | | treatmentHospitalName: caseData.treatmenthospitalname, |
| | | treatmentDeptName: caseData.treatmentdeptname, |
| | | // 其他字段可以根据需要从案例中获取 |
| | | transportStartPlace: caseData.treatmenthospitalname || '', |
| | | contactPerson: caseData.coordinatorName || '', |
| | | transitStatus: 1, // 默认待转运 |
| | | // 清空其他字段 |
| | | id: undefined, |
| | | reportId: undefined, |
| | | transportStartTime: undefined, |
| | | doctor: undefined, |
| | | doctorPhone: undefined, |
| | | nurse: undefined, |
| | | nursePhone: undefined, |
| | | driver: undefined, |
| | | driverPhone: undefined, |
| | | icuDoctor: undefined, |
| | | icuDoctorPhone: undefined, |
| | | annexfilesList: [], |
| | | remark: undefined |
| | | }; |
| | | }, |
| | | |
| | | /** 获取状态标签类型 */ |
| | |
| | | handleUpdate(row) { |
| | | this.currentTransport = row || {}; |
| | | this.isEditing = true; |
| | | this.selectedCase = null; // 编辑时不传入案例信息 |
| | | this.editOpen = true; |
| | | }, |
| | | |
| | | /** 新建转运单 */ |
| | | handleAdd() { |
| | | // 打开案例选择弹框 |
| | | this.selectCaseOpen = true; |
| | | this.selectedCase = null; |
| | | this.currentTransport = {}; |
| | | this.isEditing = false; |
| | | this.editOpen = true; |
| | | this.resetCaseSearch(); // 重置并搜索案例 |
| | | }, |
| | | |
| | | /** 修改弹框关闭处理 */ |
| | | handleEditClose() { |
| | | this.editOpen = false; |
| | | this.currentTransport = {}; |
| | | this.selectedCase = null; |
| | | }, |
| | | |
| | | /** 保存成功处理 */ |
| | |
| | | this.actionOpen = true; |
| | | }, |
| | | |
| | | /** 确认操作 - 使用后端原始数据结构 [4](@ref) */ |
| | | /** 确认操作 */ |
| | | async confirmAction() { |
| | | try { |
| | | let requestData = { |
| | |
| | | requestData.transitStatus = 3; // 设置为转运完成 |
| | | } |
| | | |
| | | // 直接传递后端需要的参数 [8](@ref) |
| | | const response = await transportEdit(requestData); |
| | | |
| | | if (response.code === 200) { |
| | | this.$modal.msgSuccess(`${this.actionText}转运成功`); |
| | | this.getList(); // 刷新列表 |
| | | this.getList(); |
| | | } else { |
| | | this.$modal.msgError(response.msg || `${this.actionText}转运失败`); |
| | | } |
| | |
| | | this.actionOpen = false; |
| | | }, |
| | | |
| | | /** 删除按钮操作 - 使用后端原始ID [1](@ref) */ |
| | | /** 删除按钮操作 */ |
| | | async handleDelete(row) { |
| | | const ids = row.reportId || row.id || this.ids; |
| | | |
| | |
| | | |
| | | if (response.code === 200) { |
| | | this.$modal.msgSuccess("删除成功"); |
| | | this.getList(); // 刷新列表 |
| | | this.getList(); |
| | | } else { |
| | | this.$modal.msgError(response.msg || "删除失败"); |
| | | } |
| | |
| | | |
| | | /** 导出按钮操作 */ |
| | | handleExport() { |
| | | // 直接使用后端参数结构进行导出 [5](@ref) |
| | | this.download( |
| | | "system/transport/export", |
| | | { |
| | |
| | | }, |
| | | `transport_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }, |
| | | |
| | | // 点击行选择案例 |
| | | handleCaseSelect(row) { |
| | | this.selectCase(row); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .case-select-container { |
| | | max-height: 600px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .filter-card { |
| | | margin-bottom: 20px; |
| | | } |