| | |
| | | <template> |
| | | <div class="ethics-review-detail"> |
| | | <case-basic-info :case-id="caseId" :show-attachment="true" /> |
| | | |
| | | <el-card class="detail-card"> |
| | | <!-- 基础信息 --> |
| | | <!-- 伦理审查基本信息 --> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="detail-title">伦理审查基本信息</span> |
| | | <div style="float: right;"> |
| | |
| | | <el-button |
| | | type="warning" |
| | | @click="handleEndReview" |
| | | :disabled="form.ethicsConclusion === 'terminated'" |
| | | :disabled="form.status === '2'" |
| | | > |
| | | 结束审查 |
| | | </el-button> |
| | |
| | | <el-form :model="form" ref="form" :rules="rules" label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="住院号" prop="hospitalNo"> |
| | | <el-input v-model="form.hospitalNo" readonly /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="捐献者姓名" prop="donorName"> |
| | | <el-input v-model="form.donorName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="性别" prop="gender"> |
| | | <el-select v-model="form.gender" style="width: 100%"> |
| | | <el-option label="男" value="0" /> |
| | | <el-option label="女" value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="发起主题" prop="initiateTheme"> |
| | | <el-input |
| | | v-model="form.initiateTheme" |
| | | placeholder="请输入发起主题" |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="年龄" prop="age"> |
| | | <el-input v-model="form.age" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="16"> |
| | | <el-form-item label="疾病诊断" prop="diagnosis"> |
| | | <el-input v-model="form.diagnosis" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="伦理结论" prop="ethicsConclusion"> |
| | | <el-select v-model="form.ethicsConclusion" style="width: 100%"> |
| | | <el-option label="审查中" value="reviewing" /> |
| | | <el-option label="同意" value="approved" /> |
| | | <el-option |
| | | label="修改后同意" |
| | | value="approved_with_modifications" |
| | | /> |
| | | <el-option label="修改后重审" value="re-review" /> |
| | | <el-option label="不同意" value="disapproved" /> |
| | | <el-option label="终止审查" value="terminated" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="审查时间" prop="reviewTime"> |
| | | <el-date-picker |
| | | v-model="form.reviewTime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="登记人" prop="registrant"> |
| | | <el-input v-model="form.registrant" /> |
| | | <el-form-item label="发起人" prop="initiatePerson"> |
| | | <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> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="发起时间" prop="startTime"> |
| | | <el-date-picker |
| | | v-model="form.startTime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="截止时间" prop="cutOffTime"> |
| | | <el-date-picker |
| | | v-model="form.cutOffTime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 专家相关信息 --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家姓名" prop="expertName"> |
| | | <el-input v-model="form.expertName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家编号" prop="expertNo"> |
| | | <el-input v-model="form.expertNo" /> |
| | | </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-option label="普通专家" value="normal" /> |
| | | <el-option label="主委专家" value="chief" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家结论" prop="expertConclusion"> |
| | | <el-select |
| | | v-model="form.expertConclusion" |
| | | style="width: 100%" |
| | | |
| | | > |
| | | <el-option label="同意" value="1" /> |
| | | <el-option label="不同意" value="0" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家结论时间" prop="expertTime"> |
| | | <el-date-picker |
| | | v-model="form.expertTime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="专家排队序号" prop="orderNo"> |
| | | <el-input-number |
| | | v-model="form.orderNo" |
| | | :min="1" |
| | | :max="20" |
| | | style="width: 100%" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="伦理意见" prop="ethicsOpinion"> |
| | | <el-form-item label="专家意见" prop="expertOpinion"> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="3" |
| | | v-model="form.ethicsOpinion" |
| | | placeholder="请输入伦理审查意见" |
| | | :rows="2" |
| | | v-model="form.expertOpinion" |
| | | placeholder="请输入专家意见" |
| | | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="登记时间" prop="registrationTime"> |
| | | <el-date-picker |
| | | v-model="form.registrationTime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input |
| | | type="textarea" |
| | | :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"> |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <!-- 专家审查情况 --> |
| | | <el-card class="expert-card"> |
| | | <div slot="header" class="clearfix"> |
| | | <span class="detail-title" |
| | | >专家审查情况 (18位专家 + 1位主委专家)</span |
| | | > |
| | | <span class="detail-title">专家审查情况 (18位专家 + 1位主委专家)</span> |
| | | <div style="float: right;"> |
| | | <el-button |
| | | size="mini" |
| | |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <!-- 专家统计信息 --> |
| | | |
| | | <!-- 专家统计信息 --> |
| | | <div |
| | | class="expert-stats" |
| | | style="margin-top: 20px; padding: 15px; background: #f5f7fa; border-radius: 4px;" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- 专家审查表格 --> |
| | | <el-table |
| | | :data="expertReviews" |
| | | v-loading="expertLoading" |
| | | style="width: 100%" |
| | | heiht="300" |
| | | height="800" |
| | | :row-class-name="getExpertRowClassName" |
| | | > |
| | | <el-table-column label="序号" width="60" align="center" type="index" /> |
| | |
| | | <el-table-column label="发送时间" width="160" align="center"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | scope.row.reviewTime ? parseTime(scope.row.reviewTime) : "未发送" |
| | | scope.row.sendTime ? parseTime(scope.row.sendTime) : "未发送" |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | |
| | | </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> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getToken } from "@/utils/auth"; |
| | | import { |
| | | getEthicsReviewDetail, |
| | | updateEthicsReview, |
| | | sendExpertReview, |
| | | endEthicsReview, |
| | | uploadAttachment, |
| | | deleteAttachment, |
| | | getAttachments |
| | | } from "./ethicsReview"; |
| | | reviewinitiateBaseInfoList, |
| | | ethicalreviewedit, |
| | | ethicalreviewadd |
| | | } from "@/api/businessApi"; |
| | | import CaseBasicInfo from "@/components/CaseBasicInfo"; |
| | | |
| | | export default { |
| | | name: "EthicsReviewDetail", |
| | | components: { CaseBasicInfo }, |
| | | |
| | | data() { |
| | | return { |
| | | // 页面模式 |
| | | isEdit: false, |
| | | // 基本信息 |
| | | infoid: undefined, |
| | | caseId: null, |
| | | caseNo: "", |
| | | |
| | | // 表单数据 |
| | | form: { |
| | | // 基础信息 |
| | | id: undefined, |
| | | hospitalNo: "", |
| | | donorName: "", |
| | | gender: "", |
| | | age: "", |
| | | diagnosis: "", |
| | | ethicsConclusion: "reviewing", |
| | | ethicsOpinion: "", |
| | | reviewTime: "", |
| | | registrant: "", |
| | | registrationTime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19) |
| | | infoid: undefined, |
| | | caseNo: "", |
| | | initiateTheme: "", |
| | | initiatePerson: "", |
| | | |
| | | // 状态和时间 |
| | | status: "0", // 0:新建, 1:审查中, 2:结束 |
| | | startTime: "", |
| | | cutOffTime: "", |
| | | endTime: "", |
| | | |
| | | // 专家信息 |
| | | expertName: "", |
| | | expertNo: "", |
| | | expertType: "normal", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | expertTime: "", |
| | | orderNo: 1, |
| | | |
| | | // 备注 |
| | | remark: "", |
| | | |
| | | // 系统字段 |
| | | createBy: "", |
| | | createTime: "", |
| | | updateBy: "", |
| | | updateTime: "", |
| | | delFlag: "0" |
| | | }, |
| | | // 表单验证规则 |
| | | rules: { |
| | | donorName: [ |
| | | { required: true, message: "捐献者姓名不能为空", trigger: "blur" } |
| | | ], |
| | | ethicsConclusion: [ |
| | | { required: true, message: "伦理结论不能为空", trigger: "change" } |
| | | ], |
| | | reviewTime: [ |
| | | { required: true, message: "审查时间不能为空", trigger: "change" } |
| | | ] |
| | | }, |
| | | rules: { |
| | | initiateTheme: [ |
| | | { required: true, message: "发起主题不能为空", trigger: "blur" }, |
| | | { min: 2, max: 100, message: "长度在 2 到 100 个字符", trigger: "blur" } |
| | | ], |
| | | initiatePerson: [ |
| | | { required: true, message: "发起人不能为空", trigger: "blur" } |
| | | ], |
| | | status: [ |
| | | { required: true, message: "审查状态不能为空", trigger: "change" } |
| | | ], |
| | | startTime: [ |
| | | { required: true, message: "发起时间不能为空", trigger: "change" } |
| | | ], |
| | | cutOffTime: [ |
| | | { required: true, message: "截止时间不能为空", trigger: "change" } |
| | | ], |
| | | expertName: [ |
| | | { max: 50, message: "长度不能超过 50 个字符", trigger: "blur" } |
| | | ], |
| | | expertNo: [ |
| | | { max: 50, message: "长度不能超过 50 个字符", trigger: "blur" } |
| | | ], |
| | | expertConclusion: [ |
| | | { max: 2, message: "长度不能超过 2 个字符", trigger: "change" } |
| | | ], |
| | | remark: [ |
| | | { max: 500, message: "长度不能超过 500 个字符", trigger: "blur" } |
| | | ] |
| | | }, |
| | | // 保存加载状态 |
| | | saveLoading: false, |
| | | |
| | | // 附件数据 |
| | | attachments: [], |
| | | expertReviews: [ |
| | | // 专家审查数据 |
| | | expertReviews: [ |
| | | // 专家(18位)- 初始状态为申请中 |
| | | { |
| | | id: 1, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 2, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 3, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 4, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 5, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 6, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 7, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 8, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 9, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 10, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 11, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 12, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 13, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 14, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 15, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 16, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 17, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | { |
| | | id: 18, |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | }, |
| | | // 主委专家(1位) |
| | | { |
| | |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | reviewTime: "", |
| | | sendTime: "" |
| | | } |
| | | ], |
| | | expertLoading: false, |
| | | attachmentLoading: false, |
| | | |
| | | // 发送对话框 |
| | | sendDialogVisible: false, |
| | | sendForm: { |
| | |
| | | expertIds: [], |
| | | 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" }, |
| | | { id: 2, name: "李教授", type: "normal" }, |
| | | { id: 3, name: "王教授", type: "normal" }, |
| | | { id: 4, name: "赵主委", type: "chief" } |
| | | { id: 1, name: "陶昊", type: "normal" }, |
| | | { id: 2, name: "刘斌", type: "normal" }, |
| | | { id: 3, name: "于海初", type: "normal" }, |
| | | { id: 4, name: "王红梅", type: "normal" }, |
| | | { id: 5, name: "王春光", type: "normal" }, |
| | | { id: 6, name: "王静", type: "normal" }, |
| | | { id: 7, name: "边文超", type: "normal" }, |
| | | { id: 8, name: "闫志勇", type: "normal" }, |
| | | { id: 9, name: "许凤", type: "normal" }, |
| | | { id: 10, name: "许传屾", type: "normal" }, |
| | | { id: 11, name: "张红岩", type: "normal" }, |
| | | { id: 12, name: "杨苏民", type: "normal" }, |
| | | { id: 13, name: "宋玉强", type: "normal" }, |
| | | { id: 14, name: "周传利", type: "normal" }, |
| | | { id: 15, name: "荆凡波", type: "normal" }, |
| | | { id: 16, name: "矫文捷", type: "normal" }, |
| | | { id: 17, name: "董震", type: "normal" }, |
| | | { id: 18, name: "蔡金贞", type: "normal" }, |
| | | { id: 19, name: "孔心涓", type: "chief" } |
| | | ] |
| | | }; |
| | | }, |
| | |
| | | .length > 0 |
| | | ); |
| | | }, |
| | | // 是否可以发送专家审查 |
| | | canSendToExperts() { |
| | | return this.form.id && this.form.ethicsConclusion === "reviewing"; |
| | | }, |
| | | // 当前用户信息 |
| | | currentUser() { |
| | | return JSON.parse(sessionStorage.getItem("user") || "{}"); |
| | | } |
| | | }, |
| | | created() { |
| | | const id = this.$route.query.id; |
| | | if (id) { |
| | | this.getDetail(id); |
| | | this.getAttachments(id); |
| | | // 不再需要从接口获取专家列表,使用固定的expertReviews数据 |
| | | } else if (this.$route.path.includes("/add")) { |
| | | this.generateHospitalNo(); |
| | | this.form.registrant = this.currentUser.username || "当前用户"; |
| | | } |
| | | this.infoid = this.$route.query.infoid; |
| | | 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(); |
| | | // } |
| | | }, |
| | | methods: { |
| | | // 生成住院号 |
| | | generateHospitalNo() { |
| | | const timestamp = Date.now().toString(); |
| | | this.form.hospitalNo = "D" + timestamp.slice(-6); |
| | | // 初始化新增数据 |
| | | initNewData() { |
| | | this.form.infoid = this.infoid; |
| | | this.form.caseNo = this.$route.query.caseNo || ""; |
| | | this.form.initiatePerson = this.currentUser.username || "当前用户"; |
| | | this.form.startTime = new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19); |
| | | this.form.createBy = this.currentUser.username || "admin"; |
| | | }, |
| | | getExpertRowClassName({ row }) { |
| | | return row.isChief ? "chief-expert-row" : "normal-expert-row"; |
| | | }, |
| | | |
| | | // 获取详情 |
| | | getDetail(id) { |
| | | getEthicsReviewDetail(id) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.form = response.data; |
| | | async getDetail(infoid) { |
| | | try { |
| | | this.expertLoading = true; |
| | | const response = await reviewinitiateBaseInfoList({ infoid: infoid }); |
| | | |
| | | if (response.code === 200) { |
| | | let detailData = {}; |
| | | |
| | | if (response.data) { |
| | | this.form = response.data[0]; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("获取伦理审查详情失败:", error); |
| | | this.$message.error("获取详情失败"); |
| | | }); |
| | | console.log(this.form, "this.form "); |
| | | |
| | | this.infoid = detailData.infoid || this.infoid; |
| | | this.caseNo = detailData.caseNo || ""; |
| | | |
| | | this.$message.success("数据加载成功"); |
| | | } else { |
| | | this.$message.error("获取详情失败:" + (response.msg || "未知错误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取伦理审查详情失败:", error); |
| | | this.$message.error("数据加载失败"); |
| | | } finally { |
| | | this.expertLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // 获取专家审查列表 |
| | |
| | | this.expertLoading = true; |
| | | // 模拟数据 - 实际项目中从接口获取 |
| | | setTimeout(() => { |
| | | this.expertReviews = [ |
| | | // 专家(18位) |
| | | { |
| | | id: 1, |
| | | expertName: "张教授", |
| | | isChief: false, |
| | | reviewStatus: "submitted", |
| | | expertConclusion: "approved", |
| | | expertOpinion: "符合伦理要求", |
| | | reviewTime: "2025-12-01 10:30:00" |
| | | }, |
| | | { |
| | | id: 2, |
| | | expertName: "李教授", |
| | | isChief: false, |
| | | reviewStatus: "submitted", |
| | | expertConclusion: "approved", |
| | | expertOpinion: "方案设计合理", |
| | | reviewTime: "2025-12-01 11:20:00" |
| | | }, |
| | | { |
| | | id: 3, |
| | | expertName: "王教授", |
| | | isChief: false, |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | }, |
| | | // 主委专家(1位) |
| | | { |
| | | id: 19, |
| | | expertName: "赵主委", |
| | | isChief: true, |
| | | reviewStatus: "applying", |
| | | expertConclusion: "", |
| | | expertOpinion: "", |
| | | reviewTime: "" |
| | | } |
| | | ]; |
| | | this.expertLoading = false; |
| | | }, 500); |
| | | }, |
| | |
| | | // 获取附件列表 |
| | | getAttachments(ethicsReviewId) { |
| | | this.attachmentLoading = true; |
| | | getAttachments(ethicsReviewId) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.attachments = response.data; |
| | | } |
| | | this.attachmentLoading = false; |
| | | }) |
| | | .catch(error => { |
| | | console.error("获取附件列表失败:", error); |
| | | this.attachmentLoading = false; |
| | | }); |
| | | // 模拟获取附件 |
| | | setTimeout(() => { |
| | | this.attachmentLoading = false; |
| | | }, 500); |
| | | }, |
| | | |
| | | // 专家行样式 |
| | | getExpertRowClassName({ row }) { |
| | | return row.isChief ? "chief-expert-row" : "normal-expert-row"; |
| | | }, |
| | | |
| | | // 状态过滤器 |
| | |
| | | }, |
| | | |
| | | // 保存信息 |
| | | handleSave() { |
| | | this.$refs.form.validate(valid => { |
| | | async handleSave() { |
| | | this.$refs.form.validate(async valid => { |
| | | if (valid) { |
| | | this.saveLoading = true; |
| | | const apiMethod = this.form.id ? updateEthicsReview : addEthicsReview; |
| | | try { |
| | | const submitData = { |
| | | ...this.form, |
| | | // 确保必要字段 |
| | | infoid: this.infoid, |
| | | caseNo: this.caseNo |
| | | }; |
| | | |
| | | apiMethod(this.form) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("保存成功"); |
| | | if (!this.form.id) { |
| | | this.form.id = response.data.id; |
| | | this.$router.replace({ |
| | | query: { ...this.$route.query, id: this.form.id } |
| | | }); |
| | | } |
| | | let response = null; |
| | | |
| | | if (submitData.id) { |
| | | response = await ethicalreviewedit(submitData); |
| | | } else { |
| | | response = await ethicalreviewadd(submitData); |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | this.$message.success("保存成功"); |
| | | this.isEdit = false; |
| | | if (!this.form.id && response.data && response.data.id) { |
| | | this.form.id = response.data.id; |
| | | this.$router.replace({ |
| | | query: { ...this.$route.query, id: this.form.id } |
| | | }); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("保存失败:", error); |
| | | this.$message.error("保存失败"); |
| | | }) |
| | | .finally(() => { |
| | | this.saveLoading = false; |
| | | }); |
| | | } else { |
| | | this.$message.error("保存失败:" + (response.msg || "未知错误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("保存失败:", error); |
| | | this.$message.error("保存失败,请重试"); |
| | | } finally { |
| | | this.saveLoading = false; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 发送专家审查 |
| | | handleSendToExperts() { |
| | | this.sendDialogVisible = true; |
| | | // 结束审查 |
| | | async handleEndReview() { |
| | | this.$confirm( |
| | | "确定要结束本次伦理审查吗?结束后将无法修改专家审查结果。", |
| | | "提示", |
| | | { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | } |
| | | ) |
| | | .then(async () => { |
| | | try { |
| | | const updateData = { |
| | | ...this.form, |
| | | status: "2", |
| | | endTime: new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19) |
| | | }; |
| | | |
| | | const response = await ethicalreviewedit(updateData); |
| | | |
| | | if (response.code === 200) { |
| | | this.$message.success("审查已结束"); |
| | | this.form.status = "2"; |
| | | this.form.endTime = updateData.endTime; |
| | | } else { |
| | | this.$message.error("操作失败:" + (response.msg || "未知错误")); |
| | | } |
| | | } catch (error) { |
| | | console.error("结束审查失败:", error); |
| | | this.$message.error("结束审查失败"); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | |
| | | // 发送给专家 |
| | |
| | | return; |
| | | } |
| | | |
| | | sendExpertReview({ |
| | | ethicsReviewId: this.form.id, |
| | | expertIds: this.sendForm.expertIds, |
| | | content: this.sendForm.content |
| | | }) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("发送成功"); |
| | | this.sendDialogVisible = false; |
| | | this.getExpertReviews(this.form.id); |
| | | this.sendForm = { |
| | | expertType: "normal", |
| | | expertIds: [], |
| | | content: "" |
| | | }; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("发送失败:", error); |
| | | this.$message.error("发送失败"); |
| | | }); |
| | | }, |
| | | // 模拟发送 |
| | | this.$message.success("发送成功"); |
| | | this.sendDialogVisible = false; |
| | | |
| | | // 结束审查 |
| | | handleEndReview() { |
| | | this.$confirm( |
| | | "确定要结束本次伦理审查吗?结束后将无法修改专家审查结果。", |
| | | "提示", |
| | | { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | // 更新专家状态 |
| | | this.sendForm.expertIds.forEach(expertId => { |
| | | const index = this.expertReviews.findIndex( |
| | | expert => expert.id === expertId |
| | | ); |
| | | if (index !== -1) { |
| | | this.expertReviews[index].reviewStatus = "submitted"; |
| | | this.expertReviews[index].sendTime = new Date() |
| | | .toISOString() |
| | | .replace("T", " ") |
| | | .substring(0, 19); |
| | | } |
| | | ) |
| | | .then(() => { |
| | | endEthicsReview(this.form.id) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("审查已结束"); |
| | | this.form.ethicsConclusion = "terminated"; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("结束审查失败:", error); |
| | | this.$message.error("结束审查失败"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }); |
| | | |
| | | this.sendForm = { |
| | | expertType: "normal", |
| | | expertIds: [], |
| | | content: "" |
| | | }; |
| | | }, |
| | | |
| | | // 编辑专家审查 |
| | |
| | | ); |
| | | }, |
| | | |
| | | // 上传附件 |
| | | // 上传附件相关方法 |
| | | handleUploadAttachment() { |
| | | this.uploadDialogVisible = true; |
| | | }, |
| | |
| | | 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 || "文件上传失败"); |
| | | } |
| | | }, |
| | | |
| | | // 提交上传 |
| | | submitUpload() { |
| | | async submitUpload() { |
| | | if (this.tempFileList.length === 0) { |
| | | this.$message.warning("请先选择要上传的文件"); |
| | | return; |
| | | } |
| | | |
| | | this.$refs.uploadRef.submit(); |
| | | this.uploadLoading = true; |
| | | |
| | | const uploadPromises = this.tempFileList.map(file => { |
| | | const formData = new FormData(); |
| | | formData.append("file", file.raw); |
| | | formData.append("ethicsReviewId", this.form.id); |
| | | |
| | | return uploadAttachment(formData); |
| | | }); |
| | | |
| | | Promise.all(uploadPromises) |
| | | .then(responses => { |
| | | this.$message.success("文件上传成功"); |
| | | this.uploadDialogVisible = false; |
| | | this.tempFileList = []; |
| | | this.getAttachments(this.form.id); |
| | | }) |
| | | .catch(error => { |
| | | console.error("上传失败:", error); |
| | | this.$message.error("文件上传失败"); |
| | | }) |
| | | .finally(() => { |
| | | this.uploadLoading = false; |
| | | }); |
| | | }, |
| | | |
| | | // 预览附件 |
| | |
| | | link.download = attachment.fileName; |
| | | link.click(); |
| | | this.$message.success(`开始下载: ${attachment.fileName}`); |
| | | }, |
| | | |
| | | // 删除附件 |
| | | handleRemoveAttachment(attachment) { |
| | | this.$confirm("确定要删除这个附件吗?", "提示", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }) |
| | | .then(() => { |
| | | deleteAttachment(attachment.id) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("附件删除成功"); |
| | | this.getAttachments(this.form.id); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("删除附件失败:", error); |
| | | this.$message.error("删除附件失败"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | |
| | | // 获取文件类型 |
| | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .ethics-review-detail { |
| | | padding: 20px; |
| | |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .upload-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding: 10px; |
| | | background-color: #f8f9fa; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .upload-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .file-info { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | color: #909399; |
| | | } |
| | | |
| | | /* 表单样式优化 */ |
| | | :deep(.el-form-item__label) { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-input__inner) { |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-textarea__inner) { |
| | | border-radius: 4px; |
| | | resize: vertical; |
| | | } |
| | | |
| | | /* 表格样式优化 */ |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | color: #606266; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-table .cell) { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | /* 按钮样式优化 */ |
| | | :deep(.el-button--primary) { |
| | | background: linear-gradient(135deg, #409eff 0%, #3375e0 100%); |
| | | border: none; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-button--success) { |
| | | background: linear-gradient(135deg, #67c23a 0%, #529b2f 100%); |
| | | border: none; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-button--warning) { |
| | | background: linear-gradient(135deg, #e6a23c 0%, #d18c2a 100%); |
| | | border: none; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | :deep(.el-button--danger) { |
| | | background: linear-gradient(135deg, #f56c6c 0%, #e05b5b 100%); |
| | | border: none; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | /* 标签样式 */ |
| | | :deep(.el-tag) { |
| | | border-radius: 12px; |
| | | border: none; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* 对话框样式优化 */ |
| | | :deep(.el-dialog) { |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | :deep(.el-dialog__header) { |
| | | background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%); |
| | | border-bottom: 1px solid #e4e7ed; |
| | | padding: 15px 20px; |
| | | } |
| | | |
| | | :deep(.el-dialog__title) { |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | /* 上传组件样式 */ |
| | | :deep(.el-upload-dragger) { |
| | | border: 2px dashed #dcdfe6; |
| | | border-radius: 6px; |
| | | background-color: #fafafa; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | :deep(.el-upload-dragger:hover) { |
| | | border-color: #409eff; |
| | | background-color: #f0f7ff; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .ethics-review-detail { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .expert-stats .el-col { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .upload-header { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | |
| | | /* 动画效果 */ |
| | | .fade-enter-active, |
| | | .fade-leave-active { |
| | | transition: opacity 0.3s ease; |
| | | } |
| | | |
| | | .fade-enter, |
| | | .fade-leave-to { |
| | | opacity: 0; |
| | | } |
| | | |
| | | /* 加载状态 */ |
| | | .loading-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 200px; |
| | | } |
| | | /* 专家类型样式 */ |
| | | .normal-expert { |
| | | color: #409eff; |
| | |
| | | color: #67c23a !important; |
| | | } |
| | | |
| | | /* 表格行悬停效果 */ |
| | | :deep(.el-table__row:hover) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s ease; |
| | | } |
| | | /* 自定义滚动条 */ |
| | | :deep(::-webkit-scrollbar) { |
| | | width: 6px; |
| | | height: 6px; |
| | | } |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .ethics-review-detail { |
| | | padding: 10px; |
| | | } |
| | | |
| | | :deep(::-webkit-scrollbar-track) { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | :deep(::-webkit-scrollbar-thumb) { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | :deep(::-webkit-scrollbar-thumb:hover) { |
| | | background: #a8a8a8; |
| | | } |
| | | |
| | | /* 专家审查表格特殊样式 */ |
| | | .expert-table-special :deep(.el-table__row) { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .expert-table-special :deep(.el-table__row:hover) { |
| | | background-color: #f0f7ff; |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | /* 主委专家行高亮 */ |
| | | :deep(.chief-expert-row) { |
| | | background-color: #fff7e6 !important; |
| | | } |
| | | |
| | | :deep(.chief-expert-row:hover) { |
| | | background-color: #ffecc2 !important; |
| | | .expert-stats .el-col { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | </style> |