| | |
| | | <el-input |
| | | v-model="form.initiateTheme" |
| | | placeholder="请输入发起主题" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-input v-model="form.initiatePerson" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="审查状态" prop="status"> |
| | | <el-select |
| | | v-model="form.status" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | <el-option label="新建" value="0" /> |
| | | <el-option label="审查中" value="1" /> |
| | | <el-option label="结束" value="2" /> |
| | | <el-select v-model="form.status" style="width: 100%"> |
| | | <el-option |
| | | v-for="dict in dict.type.sys_ethical" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家类型" prop="expertType"> |
| | | <el-select |
| | | v-model="form.expertType" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | <el-select v-model="form.expertType" style="width: 100%"> |
| | | <el-option label="普通专家" value="normal" /> |
| | | <el-option label="主委专家" value="chief" /> |
| | | </el-select> |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家结论" prop="expertConclusion"> |
| | | <el-select |
| | | v-model="form.expertConclusion" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | <el-select v-model="form.expertConclusion" style="width: 100%"> |
| | | <el-option label="同意" value="1" /> |
| | | <el-option label="审查中" value="2" /> |
| | | <el-option label="不同意" value="0" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :min="1" |
| | | :max="20" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :rows="2" |
| | | v-model="form.expertOpinion" |
| | | placeholder="请输入专家意见" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :rows="3" |
| | | v-model="form.remark" |
| | | placeholder="请输入备注信息" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | </el-form> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="attachment-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="detail-title">相关附件</span> |
| | | <el-button type="primary" size="mini" @click="handleUploadAttachment"> |
| | | <!-- <el-button type="primary" size="mini" @click="openUploadDialog"> |
| | | 上传附件 |
| | | </el-button> |
| | | </el-button> --> |
| | | </div> |
| | | |
| | | <el-table :data="attachments" style="width: 100%"> |
| | | <el-table-column label="文件名称" min-width="200"> |
| | | <!-- 使用 UploadAttachment 组件 --> |
| | | <UploadAttachment |
| | | ref="uploadAttachment" |
| | | :file-list="attachmentFileList" |
| | | :limit="10" |
| | | accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx" |
| | | @change="handleAttachmentChange" |
| | | @upload-success="handleUploadSuccess" |
| | | @upload-error="handleUploadError" |
| | | @remove="handleAttachmentRemove" |
| | | /> |
| | | |
| | | <!-- 附件列表 --> |
| | | <div |
| | | class="attachment-list" |
| | | v-if="form.annexfilesList && form.annexfilesList.length > 0" |
| | | > |
| | | <div class="list-title"> |
| | | 已上传附件 ({{ form.annexfilesList.length }}) |
| | | </div> |
| | | <el-table |
| | | :data="form.annexfilesList" |
| | | style="width: 100%" |
| | | size="small" |
| | | > |
| | | <el-table-column label="文件名" min-width="200"> |
| | | <template slot-scope="scope"> |
| | | <div class="file-info"> |
| | | <i |
| | | class="el-icon-document" |
| | | style="margin-right: 8px; color: #409EFF;" |
| | | ></i> |
| | | <span>{{ scope.row.fileName }}</span> |
| | | </div> |
| | | <span class="file-name">{{ scope.row.fileName }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="文件类型" width="100" align="center"> |
| | | <el-table-column label="文件类型" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-tag size="small">{{ getFileType(scope.row.fileName) }}</el-tag> |
| | | <el-tag size="small">{{ |
| | | getFileType(scope.row.fileName) |
| | | }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="文件大小" width="100" align="center"> |
| | | <el-table-column label="创建时间" width="160"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatFileSize(scope.row.fileSize) }}</span> |
| | | <span>{{ formatDateTime(scope.row.createTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="上传时间" width="160" align="center"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.uploadTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="上传人" width="100" align="center"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.uploader }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="120" align="center"> |
| | | <el-table-column label="操作" width="266"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-view" |
| | | @click="handlePreviewAttachment(scope.row)" |
| | | >预览</el-button |
| | | type="primary" |
| | | @click="handlePreview(scope.row)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-download" |
| | | @click="handleDownloadAttachment(scope.row)" |
| | | >下载</el-button |
| | | type="success" |
| | | @click="handleDownload(scope.row)" |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveAttachment(scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- 空状态 --> |
| | | <div v-if="!form.annexfilesList || form.annexfilesList.length === 0" class="empty-attachment"> |
| | | <i class="el-icon-folder-opened" style="font-size: 60px; color: #C0C4CC; margin-bottom: 20px;"></i> |
| | | <p style="color: #909399; font-size: 14px;">暂无附件,请上传相关文件</p> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 专家审查情况 --> |
| | |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 上传附件对话框 --> |
| | | <el-dialog |
| | | title="上传附件" |
| | | :visible.sync="uploadDialogVisible" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-upload |
| | | ref="uploadRef" |
| | | class="upload-demo" |
| | | drag |
| | | :action="uploadAction" |
| | | :headers="headers" |
| | | multiple |
| | | :file-list="tempFileList" |
| | | :before-upload="beforeUpload" |
| | | :on-change="handleFileChange" |
| | | :on-remove="handleTempRemove" |
| | | :on-success="handleUploadSuccess" |
| | | :auto-upload="false" |
| | | > |
| | | <i class="el-icon-upload"></i> |
| | | <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> |
| | | <div class="el-upload__tip" slot="tip"> |
| | | 支持上传pdf、jpg、png、doc、docx、xls、xlsx格式文件,单个文件不超过10MB |
| | | </div> |
| | | </el-upload> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="uploadDialogVisible = false">取消</el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="submitUpload" |
| | | :loading="uploadLoading" |
| | | :disabled="tempFileList.length === 0" |
| | | > |
| | | 确认上传 |
| | | </el-button> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="previewVisible" |
| | | :file="currentPreviewFile" |
| | | @close="previewVisible = false" |
| | | @download="handleDownload" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { |
| | | reviewinitiateBaseInfoList, |
| | | ethicalreviewedit, |
| | | ethicalreviewadd |
| | | ethicalreviewadd, |
| | | ethicalreviewInfo |
| | | } from "@/api/businessApi"; |
| | | import CaseBasicInfo from "@/components/CaseBasicInfo"; |
| | | import UploadAttachment from "@/components/UploadAttachment"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | export default { |
| | | name: "EthicsReviewDetail", |
| | | components: { CaseBasicInfo }, |
| | | components: { CaseBasicInfo, UploadAttachment, FilePreviewDialog }, |
| | | dicts: ["sys_user_sex", "sys_ethical"], |
| | | |
| | | data() { |
| | | return { |
| | |
| | | isEdit: false, |
| | | // 基本信息 |
| | | infoid: undefined, |
| | | id: undefined, |
| | | caseId: null, |
| | | caseNo: "", |
| | | |
| | |
| | | // 备注 |
| | | remark: "", |
| | | |
| | | // 附件信息 |
| | | annexfilesList: [], |
| | | filePatch: "", |
| | | |
| | | // 系统字段 |
| | | createBy: "", |
| | | createTime: "", |
| | |
| | | rules: { |
| | | initiateTheme: [ |
| | | { required: true, message: "发起主题不能为空", trigger: "blur" }, |
| | | { min: 2, max: 100, message: "长度在 2 到 100 个字符", trigger: "blur" } |
| | | { |
| | | min: 2, |
| | | max: 100, |
| | | message: "长度在 2 到 100 个字符", |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | initiatePerson: [ |
| | | { required: true, message: "发起人不能为空", trigger: "blur" } |
| | |
| | | // 保存加载状态 |
| | | saveLoading: false, |
| | | |
| | | // 附件数据 |
| | | attachments: [], |
| | | // 附件相关 |
| | | attachmentFileList: [], |
| | | |
| | | // 预览相关 |
| | | previewVisible: false, |
| | | currentPreviewFile: null, |
| | | |
| | | // 专家审查数据 |
| | | expertReviews: [ |
| | | // 专家(18位)- 初始状态为申请中 |
| | |
| | | content: "" |
| | | }, |
| | | |
| | | // 上传相关 |
| | | uploadDialogVisible: false, |
| | | uploadLoading: false, |
| | | tempFileList: [], |
| | | uploadAction: process.env.VUE_APP_BASE_API + "/common/upload", |
| | | headers: { |
| | | Authorization: "Bearer " + getToken() |
| | | }, |
| | | |
| | | // 可用专家列表 |
| | | availableExperts: [ |
| | | { id: 1, name: "陶昊", type: "normal" }, |
| | |
| | | }, |
| | | created() { |
| | | this.infoid = this.$route.query.infoid; |
| | | this.id = this.$route.query.id; |
| | | this.caseId = this.$route.query.infoid; |
| | | // const id = this.$route.query.id; |
| | | this.getDetail(this.infoid); |
| | | |
| | | // if (id && !this.$route.path.includes("/add")) { |
| | | // this.getDetail(this.infoid); |
| | | // } else if (this.$route.path.includes("/add") && this.infoid) { |
| | | // this.initNewData(); |
| | | // } |
| | | this.getDetail(this.infoid, this.id); |
| | | }, |
| | | methods: { |
| | | // 初始化新增数据 |
| | |
| | | }, |
| | | |
| | | // 获取详情 |
| | | async getDetail(infoid) { |
| | | async getDetail(infoid, id) { |
| | | try { |
| | | this.expertLoading = true; |
| | | const response = await reviewinitiateBaseInfoList({ infoid: infoid }); |
| | | let response = {}; |
| | | if (id) { |
| | | response = await ethicalreviewInfo(id); |
| | | } else if (infoid) { |
| | | response = await reviewinitiateBaseInfoList({ infoid: infoid }); |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | let detailData = {}; |
| | | |
| | | if (response.data) { |
| | | if (response.data && id) { |
| | | this.form = response.data; |
| | | // 解析 filePatch 字段 |
| | | this.parseFilePatch(this.form.filePatch); |
| | | this.initAttachmentFileList(); |
| | | } else if (response.data && infoid) { |
| | | this.form = response.data[0]; |
| | | // 解析 filePatch 字段 |
| | | this.parseFilePatch(this.form.filePatch); |
| | | this.initAttachmentFileList(); |
| | | } |
| | | console.log(this.form, "this.form "); |
| | | |
| | |
| | | } |
| | | }, |
| | | |
| | | // 解析 filePatch 字段 |
| | | parseFilePatch(filePatch) { |
| | | if (!filePatch) { |
| | | this.form.annexfilesList = []; |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | this.form.annexfilesList = JSON.parse(filePatch); |
| | | } catch (error) { |
| | | console.error("解析 filePatch 字段失败:", error); |
| | | this.form.annexfilesList = []; |
| | | } |
| | | }, |
| | | |
| | | // 初始化附件文件列表 |
| | | initAttachmentFileList() { |
| | | if (this.form.annexfilesList && this.form.annexfilesList.length > 0) { |
| | | this.attachmentFileList = this.form.annexfilesList.map(item => ({ |
| | | uid: item.id || Math.random().toString(36).substr(2, 9), |
| | | name: item.fileName, |
| | | url: item.path || item.fileUrl, |
| | | status: "success" |
| | | })); |
| | | } else { |
| | | this.attachmentFileList = []; |
| | | } |
| | | }, |
| | | |
| | | // 构建 filePatch 字段 |
| | | buildFilePatch() { |
| | | if (!this.form.annexfilesList || this.form.annexfilesList.length === 0) { |
| | | return ""; |
| | | } |
| | | return JSON.stringify(this.form.annexfilesList); |
| | | }, |
| | | |
| | | // 附件变化处理 |
| | | handleAttachmentChange(fileList) { |
| | | this.attachmentFileList = fileList; |
| | | }, |
| | | |
| | | // 附件移除处理 |
| | | handleAttachmentRemove(file) { |
| | | if (file.url) { |
| | | const index = this.form.annexfilesList.findIndex( |
| | | item => item.path === file.url || item.fileUrl === file.url |
| | | ); |
| | | if (index > -1) { |
| | | this.form.annexfilesList.splice(index, 1); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 手动删除附件 |
| | | handleRemoveAttachment(index) { |
| | | this.form.annexfilesList.splice(index, 1); |
| | | this.attachmentFileList.splice(index, 1); |
| | | this.$message.success("附件删除成功"); |
| | | }, |
| | | |
| | | // 上传成功处理 |
| | | handleUploadSuccess({ file, fileList, response }) { |
| | | if (response.code === 200) { |
| | | 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"), |
| | | infoid: this.infoid, |
| | | delFlag: 0 |
| | | }; |
| | | |
| | | this.form.annexfilesList.push(attachmentObj); |
| | | this.$message.success("文件上传成功"); |
| | | } |
| | | }, |
| | | |
| | | // 上传错误处理 |
| | | handleUploadError({ file, fileList, error }) { |
| | | console.error("附件上传失败:", error); |
| | | this.$message.error("文件上传失败,请重试"); |
| | | }, |
| | | |
| | | // 打开上传对话框 |
| | | openUploadDialog() { |
| | | this.$refs.uploadAttachment.openUpload(); |
| | | }, |
| | | |
| | | // 文件预览 |
| | | 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", "ppt", "pptx"]; |
| | | |
| | | if (imageTypes.includes(extension)) return "image"; |
| | | if (pdfTypes.includes(extension)) return "pdf"; |
| | | if (officeTypes.includes(extension)) return "office"; |
| | | return "other"; |
| | | }, |
| | | |
| | | // 获取文件扩展名 |
| | | getFileExtension(filename) { |
| | | return filename |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | }, |
| | | |
| | | // 日期时间格式化 |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return ""; |
| | | |
| | | try { |
| | | const date = new Date(dateTime); |
| | | if (isNaN(date.getTime())) return dateTime; |
| | | |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | const hours = String(date.getHours()).padStart(2, "0"); |
| | | const minutes = String(date.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(date.getSeconds()).padStart(2, "0"); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } catch (error) { |
| | | return dateTime; |
| | | } |
| | | }, |
| | | |
| | | // 获取专家审查列表 |
| | | getExpertReviews(ethicsReviewId) { |
| | | this.expertLoading = true; |
| | | // 模拟数据 - 实际项目中从接口获取 |
| | | setTimeout(() => { |
| | | this.expertLoading = false; |
| | | }, 500); |
| | | }, |
| | | |
| | | // 获取附件列表 |
| | | getAttachments(ethicsReviewId) { |
| | | this.attachmentLoading = true; |
| | | // 模拟获取附件 |
| | | setTimeout(() => { |
| | | this.attachmentLoading = false; |
| | | }, 500); |
| | | }, |
| | | |
| | |
| | | ...this.form, |
| | | // 确保必要字段 |
| | | infoid: this.infoid, |
| | | caseNo: this.caseNo |
| | | caseNo: this.caseNo, |
| | | // 构建 filePatch 字段 |
| | | filePatch: this.buildFilePatch() |
| | | }; |
| | | |
| | | let response = null; |
| | |
| | | return; |
| | | } |
| | | |
| | | // 模拟发送 |
| | | this.$message.success("发送成功"); |
| | | this.sendDialogVisible = false; |
| | | |
| | | // 更新专家状态 |
| | | this.sendForm.expertIds.forEach(expertId => { |
| | | const index = this.expertReviews.findIndex( |
| | | expert => expert.id === expertId |
| | |
| | | } |
| | | }) |
| | | .then(({ value }) => { |
| | | // 模拟更新专家审查 |
| | | const index = this.expertReviews.findIndex(e => e.id === expert.id); |
| | | if (index !== -1) { |
| | | this.expertReviews[index].expertOpinion = value; |
| | |
| | | ); |
| | | }, |
| | | |
| | | // 上传附件相关方法 |
| | | handleUploadAttachment() { |
| | | this.uploadDialogVisible = true; |
| | | }, |
| | | |
| | | // 上传前校验 |
| | | beforeUpload(file) { |
| | | const allowedTypes = [ |
| | | "application/pdf", |
| | | "image/jpeg", |
| | | "image/png", |
| | | "application/msword", |
| | | "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | "application/vnd.ms-excel", |
| | | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" |
| | | ]; |
| | | |
| | | const maxSize = 10 * 1024 * 1024; |
| | | |
| | | const isTypeOk = |
| | | allowedTypes.includes(file.type) || |
| | | file.name.endsWith(".pdf") || |
| | | file.name.endsWith(".jpg") || |
| | | file.name.endsWith(".jpeg") || |
| | | file.name.endsWith(".png") || |
| | | file.name.endsWith(".doc") || |
| | | file.name.endsWith(".docx") || |
| | | file.name.endsWith(".xls") || |
| | | file.name.endsWith(".xlsx"); |
| | | |
| | | if (!isTypeOk) { |
| | | this.$message.error("文件格式不支持"); |
| | | return false; |
| | | } |
| | | |
| | | if (file.size > maxSize) { |
| | | this.$message.error("文件大小不能超过10MB"); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | }, |
| | | |
| | | // 文件选择变化 |
| | | handleFileChange(file, fileList) { |
| | | this.tempFileList = fileList; |
| | | }, |
| | | |
| | | // 移除临时文件 |
| | | handleTempRemove(file, fileList) { |
| | | this.tempFileList = fileList; |
| | | }, |
| | | |
| | | // 上传成功处理 |
| | | handleUploadSuccess(response, file, fileList) { |
| | | if (response.code === 200) { |
| | | this.$message.success("文件上传成功"); |
| | | this.uploadDialogVisible = false; |
| | | this.tempFileList = []; |
| | | } else { |
| | | this.$message.error(response.msg || "文件上传失败"); |
| | | } |
| | | }, |
| | | |
| | | // 提交上传 |
| | | async submitUpload() { |
| | | if (this.tempFileList.length === 0) { |
| | | this.$message.warning("请先选择要上传的文件"); |
| | | return; |
| | | } |
| | | this.$refs.uploadRef.submit(); |
| | | this.uploadLoading = true; |
| | | }, |
| | | |
| | | // 预览附件 |
| | | handlePreviewAttachment(attachment) { |
| | | if (attachment.fileName.endsWith(".pdf")) { |
| | | window.open(attachment.fileUrl, "_blank"); |
| | | } else if (attachment.fileName.match(/\.(jpg|jpeg|png)$/i)) { |
| | | this.$alert( |
| | | `<img src="${attachment.fileUrl}" style="max-width: 100%;" alt="${attachment.fileName}">`, |
| | | "图片预览", |
| | | { |
| | | dangerouslyUseHTMLString: true, |
| | | customClass: "image-preview-dialog" |
| | | } |
| | | ); |
| | | } else { |
| | | this.$message.info("该文件类型暂不支持在线预览,请下载后查看"); |
| | | } |
| | | }, |
| | | |
| | | // 下载附件 |
| | | handleDownloadAttachment(attachment) { |
| | | const link = document.createElement("a"); |
| | | link.href = attachment.fileUrl; |
| | | link.download = attachment.fileName; |
| | | link.click(); |
| | | this.$message.success(`开始下载: ${attachment.fileName}`); |
| | | }, |
| | | |
| | | // 获取文件类型 |
| | | getFileType(fileName) { |
| | | const ext = fileName |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | const typeMap = { |
| | | pdf: "PDF", |
| | | doc: "DOC", |
| | | docx: "DOCX", |
| | | xls: "XLS", |
| | | xlsx: "XLSX", |
| | | jpg: "JPG", |
| | | jpeg: "JPEG", |
| | | png: "PNG" |
| | | }; |
| | | return typeMap[ext] || ext.toUpperCase(); |
| | | }, |
| | | |
| | | // 文件大小格式化 |
| | | formatFileSize(size) { |
| | | if (size === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ["B", "KB", "MB", "GB"]; |
| | | const i = Math.floor(Math.log(size) / Math.log(k)); |
| | | return parseFloat((size / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }, |
| | | |
| | | // 时间格式化 |
| | | parseTime(time) { |
| | | if (!time) return ""; |
| | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | |
| | | |
| | | <style scoped> |
| | | .ethics-review-detail { |
| | |
| | | .sent-button { |
| | | color: #67c23a !important; |
| | | } |
| | | .form-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | 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; |
| | | } |
| | | |
| | | /* 案例信息展示样式 */ |
| | | .selected-case-info { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .case-info-card { |
| | | border-left: 4px solid #67c23a; |
| | | } |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .ethics-review-detail { |