| | |
| | | import request from '@/utils/request' |
| | | |
| | | // 上报案例新增 |
| | | export function assessAdd(data) { |
| | | return request({ |
| | | url: '/project/assessbaseinforeport/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 案例列表及详情 |
| | | export function evaluateBaseInfolist(data) { |
| | | return request({ |
| | | url: '/project/medicalevaluation/evaluateBaseInfolist', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | // 上报案例列表 |
| | | export function assessList(data) { |
| | | return request({ |
| | | url: '/project/assessbaseinforeport/list', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 案例详情 |
| | | export function assessInfo(id) { |
| | | return request({ |
| | | url: '/project/assessbaseinforeport/getInfo/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | export function assessDel(id) { |
| | | return request({ |
| | | url: '/project/assessbaseinforeport/remove/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // 案例列表及详情 |
| | | export function queryDathInfoBaseInfo(data) { |
| | | return request({ |
| | | url: '/project/deathinfo/queryDathInfoBaseInfo', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | // 死亡信息修改 |
| | | export function deathinfoedit(data) { |
| | | return request({ |
| | | url: '/project/deathinfo/edit', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | // 死亡信息详情 |
| | | export function deathinfoInfo(id) { |
| | | return request({ |
| | | url: '/project/deathinfo/getInfo/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // 供者维护新增 |
| | | export function maintainAdd(data) { |
| | | return request({ |
| | | url: '/project/donatemaintenance/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | // 供者维护修改 |
| | | export function maintainedit(data) { |
| | | return request({ |
| | | url: '/project/donatemaintenance/edit', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 供者维护列表 |
| | | export function maintainList(data) { |
| | | return request({ |
| | | url: '/project/donatemaintenance/maintenanceBaseInfoList', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // 案例详情 |
| | | export function maintainInfo(id) { |
| | | return request({ |
| | | url: '/project/donatemaintenance/getInfo/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | export function maintainDel(id) { |
| | | return request({ |
| | | url: '/project/donatemaintenance/remove/' + id, |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | |
| | | 当前角色:{{ currentDepartment }}评估人员 |
| | | </span> |
| | | </div> |
| | | |
| | | <el-row> |
| | | <el-form-item label-width="100px" label="评估器官"> |
| | | <el-checkbox-group v-model="organdecision"> |
| | | <el-checkbox |
| | | v-for="item in organselection" |
| | | :key="item" |
| | | :label="item" |
| | | >{{ item }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | <el-input |
| | | v-if="organdecision.includes('其他')" |
| | | v-model="assessmentData.organdecisionOther" |
| | | placeholder="请输入其他捐献决定的具体内容" |
| | | style="margin-top: 10px; width: 300px;" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-row> |
| | | <el-table |
| | | :data="organAssessmentList" |
| | | v-loading="assessmentLoading" |
| | | style="width: 100%" |
| | | :row-class-name="getRowClassName" |
| | | :expand-row-keys="expandedRowKeys" |
| | | @expand-change="handleExpandChange" |
| | | row-key="organType" |
| | | > |
| | | <el-table-column type="expand" width="60"> |
| | | <template slot-scope="scope"> |
| | | <div class="organ-expand-content" v-if="scope.row.expanded"> |
| | | <el-tabs |
| | | v-model="scope.row.activeAssessmentTab" |
| | | type="card" |
| | | class="organ-detail-tabs" |
| | | > |
| | | <!-- 动态生成评估Tab --> |
| | | <el-tab-pane |
| | | v-for="(assessment, index) in scope.row.assessments" |
| | | :key="index" |
| | | :label="`第${index + 1}次评估`" |
| | | :name="`assessment_${index}`" |
| | | > |
| | | <organ-assessment-form |
| | | :organ-data="scope.row" |
| | | :assessment-data="assessment" |
| | | :assessment-index="index" |
| | | :readonly="!canAssessOrgan(scope.row)" |
| | | @save="handleSaveOrganAssessment" |
| | | @add-assessment="handleAddAssessment" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 添加评估按钮 --> |
| | | <el-tab-pane name="add" v-if="canAssessOrgan(scope.row)"> |
| | | <template slot="label"> |
| | | <el-button |
| | | type="text" |
| | | icon="el-icon-plus" |
| | | @click.stop="handleAddNewAssessment(scope.row)" |
| | | size="mini" |
| | | > |
| | | 新增评估 |
| | | </el-button> |
| | | </template> |
| | | <div class="add-assessment-prompt"> |
| | | <el-empty description="点击上方按钮添加新的评估"></el-empty> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 评估汇总Tab --> |
| | | <el-tab-pane label="评估汇总" name="summary"> |
| | | <div class="assessment-summary"> |
| | | <el-descriptions title="评估结果汇总" :column="2" border> |
| | | <el-descriptions-item label="器官类型">{{ |
| | | scope.row.organName |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="评估科室">{{ |
| | | scope.row.department |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="评估次数" :span="2"> |
| | | <el-tag type="info" |
| | | >{{ scope.row.assessments.length }}次</el-tag |
| | | > |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="最新评估时间" :span="2"> |
| | | {{ getLatestAssessmentTime(scope.row) || "-" }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <!-- 附件汇总 --> |
| | | <el-card header="所有评估附件" style="margin-top: 20px;"> |
| | | <el-table |
| | | :data="getAllAttachments(scope.row)" |
| | | size="small" |
| | | empty-text="暂无附件" |
| | | > |
| | | <el-table-column label="附件名称" prop="fileName" /> |
| | | <el-table-column label="评估阶段" width="120"> |
| | | <template slot-scope="{ row }"> |
| | | 第{{ row.assessmentIndex + 1 }}次评估 |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="上传时间" |
| | | prop="uploadTime" |
| | | width="180" |
| | | /> |
| | | <el-table-column label="操作" width="120"> |
| | | <template slot-scope="{ row }"> |
| | | <el-button |
| | | type="text" |
| | | @click="handlePreviewAttachment(row)" |
| | | >预览</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="器官类型" |
| | | align="center" |
| | |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="评估科室" |
| | | align="center" |
| | | prop="department" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="评估人员" |
| | | align="center" |
| | | prop="assessor" |
| | | |
| | | /> |
| | | <!-- 新增:第一次评估状态 --> |
| | | <el-table-column label="第一次评估" align="center" > |
| | | <el-table-column label="评估人员" align="center" prop="assessor" /> |
| | | |
| | | <!-- 动态显示评估状态列 --> |
| | | <el-table-column |
| | | v-for="(assessment, index) in getMaxAssessmentCount()" |
| | | :key="index" |
| | | :label="`第${index + 1}次评估`" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="getAssessmentTagType(scope.row.firstAssessment.status)" |
| | | v-if="scope.row.assessments[index]" |
| | | :type="getAssessmentTagType(scope.row.assessments[index].status)" |
| | | size="small" |
| | | > |
| | | {{ getAssessmentStatusText(scope.row.firstAssessment.status) }} |
| | | {{ getAssessmentStatusText(scope.row.assessments[index].status) }} |
| | | </el-tag> |
| | | <el-tag v-else type="info" size="small">未评估</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="整体状态" align="center" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="scope.row.assessmentStatus === '1' ? 'success' : 'primary'" |
| | | size="small" |
| | | > |
| | | {{ scope.row.assessmentStatus === "1" ? "已完成" : "评估中" }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- 新增:第二次评估状态 --> |
| | | <el-table-column label="第二次评估" align="center" > |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="getAssessmentTagType(scope.row.secondAssessment.status)" |
| | | size="small" |
| | | > |
| | | {{ getAssessmentStatusText(scope.row.secondAssessment.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="整体状态" align="center" > |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="scope.row.assessmentStatus === '1' ? 'success' : 'warning'" |
| | | size="small" |
| | | > |
| | | {{ scope.row.assessmentStatus === "1" ? "已评估" : "待评估" }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="操作" |
| | | align="center" |
| | | width="180" |
| | | width="150" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | <template slot-scope="scope"> |
| | |
| | | v-if="canAssessOrgan(scope.row)" |
| | | size="mini" |
| | | type="text" |
| | | @click="handleOrganAssess(scope.row)" |
| | | @click="handleToggleExpand(scope.row)" |
| | | > |
| | | 评估 |
| | | {{ |
| | | expandedRowKeys.includes(scope.row.organType) ? "收起" : "详情" |
| | | }} |
| | | </el-button> |
| | | <el-button v-else size="mini" type="text" disabled |
| | | >无权限</el-button |
| | | > |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | @click="handleViewOrganDetail(scope.row)" |
| | | > |
| | | 详情 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- 器官评估详情 - 改为Tab页形式 --> |
| | | <el-dialog |
| | | :title="`${currentOrgan.organName}评估详情`" |
| | | :visible.sync="organDetailVisible" |
| | | width="90%" |
| | | top="5vh" |
| | | class="organ-detail-dialog" |
| | | > |
| | | <el-tabs v-model="activeAssessmentTab" type="card"> |
| | | <!-- 第一次评估Tab --> |
| | | <el-tab-pane label="第一次评估" name="first"> |
| | | <organ-assessment-form |
| | | :organ-data="currentOrgan" |
| | | :assessment-data="currentOrgan.firstAssessment" |
| | | assessment-type="first" |
| | | :readonly="!canAssessOrgan(currentOrgan)" |
| | | @save="handleSaveOrganAssessment" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 第二次评估Tab --> |
| | | <el-tab-pane label="第二次评估" name="second"> |
| | | <organ-assessment-form |
| | | :organ-data="currentOrgan" |
| | | :assessment-data="currentOrgan.secondAssessment" |
| | | assessment-type="second" |
| | | :readonly="!canAssessOrgan(currentOrgan)" |
| | | @save="handleSaveOrganAssessment" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | <!-- 评估汇总Tab --> |
| | | <el-tab-pane label="评估汇总" name="summary"> |
| | | <div class="assessment-summary"> |
| | | <el-descriptions title="评估结果汇总" :column="2" border> |
| | | <el-descriptions-item label="器官类型"> |
| | | {{ currentOrgan.organName }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="评估科室"> |
| | | {{ currentOrgan.department }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="第一次评估状态"> |
| | | <el-tag :type="getAssessmentTagType(currentOrgan.firstAssessment.status)"> |
| | | {{ getAssessmentStatusText(currentOrgan.firstAssessment.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="第二次评估状态"> |
| | | <el-tag :type="getAssessmentTagType(currentOrgan.secondAssessment.status)"> |
| | | {{ getAssessmentStatusText(currentOrgan.secondAssessment.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="第一次评估时间" :span="2"> |
| | | {{ currentOrgan.firstAssessment.assessmentTime || '-' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="第二次评估时间" :span="2"> |
| | | {{ currentOrgan.secondAssessment.assessmentTime || '-' }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <!-- 附件汇总 --> |
| | | <el-card header="评估附件" style="margin-top: 20px;"> |
| | | <el-table :data="getAllAttachments(currentOrgan)" size="small"> |
| | | <el-table-column label="附件名称" prop="fileName" /> |
| | | <el-table-column label="评估阶段" > |
| | | <template slot-scope="{row}"> |
| | | {{ row.assessmentType === 'first' ? '第一次评估' : '第二次评估' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="上传时间" prop="uploadTime" width="180" /> |
| | | <el-table-column label="操作" width="120"> |
| | | <template slot-scope="{row}"> |
| | | <el-button type="text" @click="handlePreviewAttachment(row)">预览</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="organDetailVisible = false">关闭</el-button> |
| | | <el-button |
| | | v-if="canAssessOrgan(currentOrgan)" |
| | | type="primary" |
| | | @click="handleSaveAllAssessments" |
| | | > |
| | | 保存所有评估 |
| | | </el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </el-card> |
| | | |
| | | <!-- 附件预览弹窗 --> |
| | | <!-- <attachment-preview |
| | | :visible="attachmentVisible" |
| | | :attachment-list="attachmentList" |
| | | @close="attachmentVisible = false" |
| | | /> --> |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="attachmentVisible" |
| | | :file="attachmentList" |
| | | :file="currentPreviewFile" |
| | | @close="attachmentVisible = false" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getAssessment, updateOrganAssessment, completeAssessment } from "./mockAssessmentApi"; |
| | | import { |
| | | getAssessment, |
| | | updateOrganAssessment, |
| | | completeAssessment |
| | | } from "./mockAssessmentApi"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | import OrganAssessmentForm from "./components/OrganAssessmentForm.vue"; |
| | | |
| | |
| | | organAssessmentList: [], |
| | | attachmentList: [], |
| | | assessmentLoading: false, |
| | | |
| | | // 器官详情相关数据 |
| | | organDetailVisible: false, |
| | | currentOrgan: { |
| | | organType: '', |
| | | organName: '', |
| | | department: '', |
| | | firstAssessment: this.getDefaultAssessment(), |
| | | secondAssessment: this.getDefaultAssessment() |
| | | }, |
| | | activeAssessmentTab: 'first', |
| | | organdecision: [], |
| | | // 展开行相关 |
| | | expandedRowKeys: [], |
| | | currentPreviewFile: null, |
| | | attachmentVisible: false, |
| | | |
| | | currentUser: { |
| | | id: "001", |
| | | name: "张医生", |
| | | department: "心脏外科", |
| | | role: "department" |
| | | department: "协调员", |
| | | role: "coordinator" |
| | | }, |
| | | |
| | | attachmentVisible: false, |
| | | |
| | | //department:心脏、coordinator:协调员 |
| | | // 字典选项 |
| | | genderOptions: [ |
| | | { value: "0", label: "男" }, |
| | |
| | | { value: "intestine", label: "肠道" }, |
| | | { value: "cornea", label: "角膜" }, |
| | | { value: "skin", label: "皮肤" } |
| | | ], |
| | | organselection: [ |
| | | "肝脏", |
| | | "双肾", |
| | | "左肾", |
| | | "右肾", |
| | | "心脏", |
| | | "肺脏", |
| | | "胰腺", |
| | | "小肠", |
| | | "双眼组织", |
| | | "遗体", |
| | | "其他" |
| | | ] |
| | | }; |
| | | }, |
| | |
| | | return this.currentUser.department; |
| | | }, |
| | | allOrgansAssessed() { |
| | | return this.organAssessmentList.every(organ => |
| | | organ.firstAssessment.status === 'assessed' && |
| | | organ.secondAssessment.status === 'assessed' |
| | | return this.organAssessmentList.every( |
| | | organ => |
| | | organ.assessments && |
| | | organ.assessments.length > 0 && |
| | | organ.assessments.every( |
| | | assessment => assessment.status === "assessed" |
| | | ) |
| | | ); |
| | | } |
| | | }, |
| | |
| | | // 获取默认评估数据结构 |
| | | getDefaultAssessment() { |
| | | return { |
| | | status: 'pending', // pending, assessing, assessed |
| | | assessmentTime: '', |
| | | assessor: '', |
| | | functionStatus: '', |
| | | assessmentOpinion: '', |
| | | status: "pending", |
| | | assessmentTime: "", |
| | | assessor: "", |
| | | functionStatus: "", |
| | | assessmentOpinion: "", |
| | | attachments: [], |
| | | clinicalData: {}, |
| | | labResults: {} |
| | |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.assessmentData = response.data.caseInfo; |
| | | this.organAssessmentList = this.transformOrganData(response.data.organAssessments || []); |
| | | this.organAssessmentList = this.transformOrganData( |
| | | response.data.organAssessments || [] |
| | | ); |
| | | } |
| | | this.assessmentLoading = false; |
| | | }) |
| | |
| | | }); |
| | | }, |
| | | |
| | | // 转换器官数据格式,支持两次评估 |
| | | // 转换器官数据格式,支持多次评估 |
| | | transformOrganData(organList) { |
| | | return organList.map(organ => { |
| | | const organName = this.getOrganName(organ.organType); |
| | | |
| | | // 确保有两次评估的数据结构 |
| | | if (!organ.firstAssessment) { |
| | | organ.firstAssessment = this.getDefaultAssessment(); |
| | | // 转换为多次评估的数据结构 |
| | | const assessments = []; |
| | | if (organ.firstAssessment) { |
| | | assessments.push({ ...organ.firstAssessment, index: 0 }); |
| | | } |
| | | if (!organ.secondAssessment) { |
| | | organ.secondAssessment = this.getDefaultAssessment(); |
| | | if (organ.secondAssessment) { |
| | | assessments.push({ ...organ.secondAssessment, index: 1 }); |
| | | } |
| | | // 可以继续添加更多评估... |
| | | |
| | | // 设置器官名称 |
| | | // 设置器官名称和评估数据 |
| | | organ.organName = organName; |
| | | organ.assessments = assessments; |
| | | organ.activeAssessmentTab = |
| | | assessments.length > 0 ? "assessment_0" : "summary"; |
| | | organ.expanded = false; |
| | | |
| | | // 计算整体评估状态 |
| | | organ.assessmentStatus = this.calculateOverallStatus(organ); |
| | |
| | | }); |
| | | }, |
| | | |
| | | // 计算最大评估次数(用于表头显示) |
| | | getMaxAssessmentCount() { |
| | | const maxCount = Math.max( |
| | | ...this.organAssessmentList.map(organ => |
| | | organ.assessments ? organ.assessments.length : 0 |
| | | ) |
| | | ); |
| | | return Math.max(maxCount, 2); // 至少显示2列 |
| | | }, |
| | | |
| | | // 计算整体评估状态 |
| | | calculateOverallStatus(organ) { |
| | | const firstDone = organ.firstAssessment.status === 'assessed'; |
| | | const secondDone = organ.secondAssessment.status === 'assessed'; |
| | | if (!organ.assessments || organ.assessments.length === 0) return "0"; |
| | | |
| | | if (firstDone && secondDone) return '1'; // 已完成 |
| | | if (firstDone || secondDone) return '2'; // 部分完成 |
| | | return '0'; // 未开始 |
| | | const allAssessed = organ.assessments.every( |
| | | assessment => assessment.status === "assessed" |
| | | ); |
| | | const someAssessed = organ.assessments.some( |
| | | assessment => assessment.status === "assessed" |
| | | ); |
| | | |
| | | if (allAssessed) return "1"; |
| | | if (someAssessed) return "2"; |
| | | return "0"; |
| | | }, |
| | | |
| | | // 切换展开行 |
| | | handleToggleExpand(row) { |
| | | const key = row.organType; |
| | | const index = this.expandedRowKeys.indexOf(key); |
| | | |
| | | if (index > -1) { |
| | | this.expandedRowKeys.splice(index, 1); |
| | | row.expanded = false; |
| | | } else { |
| | | this.expandedRowKeys = [key]; |
| | | this.organAssessmentList.forEach(item => { |
| | | item.expanded = item.organType === key; |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // 展开行变化 |
| | | handleExpandChange(row, expandedRows) { |
| | | this.expandedRowKeys = expandedRows.map(item => item.organType); |
| | | this.organAssessmentList.forEach(item => { |
| | | item.expanded = this.expandedRowKeys.includes(item.organType); |
| | | }); |
| | | }, |
| | | |
| | | // 添加新评估 |
| | | handleAddNewAssessment(organ) { |
| | | const newAssessment = { |
| | | ...this.getDefaultAssessment(), |
| | | index: organ.assessments.length |
| | | }; |
| | | |
| | | organ.assessments.push(newAssessment); |
| | | organ.activeAssessmentTab = `assessment_${organ.assessments.length - 1}`; |
| | | |
| | | // 更新整体状态 |
| | | organ.assessmentStatus = this.calculateOverallStatus(organ); |
| | | |
| | | this.$message.success("已添加新的评估"); |
| | | }, |
| | | |
| | | // 处理添加评估事件 |
| | | handleAddAssessment(data) { |
| | | const { organData, currentIndex } = data; |
| | | this.handleAddNewAssessment(organData); |
| | | }, |
| | | |
| | | // 保存评估 |
| | | handleSaveOrganAssessment(saveData) { |
| | | const { organData, assessmentData, assessmentIndex } = saveData; |
| | | |
| | | const organToUpdate = { |
| | | ...organData, |
| | | assessments: organData.assessments.map((assessment, index) => |
| | | index === assessmentIndex |
| | | ? { |
| | | ...assessmentData, |
| | | status: "assessed", |
| | | assessmentTime: new Date().toISOString(), |
| | | assessor: this.currentUser.name |
| | | } |
| | | : assessment |
| | | ) |
| | | }; |
| | | |
| | | // 更新整体状态 |
| | | organToUpdate.assessmentStatus = this.calculateOverallStatus( |
| | | organToUpdate |
| | | ); |
| | | |
| | | updateOrganAssessment(organToUpdate) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success(`第${assessmentIndex + 1}次评估保存成功`); |
| | | this.getAssessmentDetail(); |
| | | |
| | | // 更新当前展开行的数据 |
| | | const index = this.organAssessmentList.findIndex( |
| | | item => item.organType === organData.organType |
| | | ); |
| | | if (index !== -1) { |
| | | this.organAssessmentList.splice(index, 1, organToUpdate); |
| | | } |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("保存评估失败:", error); |
| | | this.$message.error("保存失败"); |
| | | }); |
| | | }, |
| | | |
| | | // 获取最新评估时间 |
| | | getLatestAssessmentTime(organ) { |
| | | if (!organ.assessments || organ.assessments.length === 0) return null; |
| | | |
| | | const assessed = organ.assessments.filter(a => a.assessmentTime); |
| | | if (assessed.length === 0) return null; |
| | | |
| | | return assessed.sort( |
| | | (a, b) => new Date(b.assessmentTime) - new Date(a.assessmentTime) |
| | | )[0].assessmentTime; |
| | | }, |
| | | |
| | | // 获取所有附件 |
| | | getAllAttachments(organ) { |
| | | const attachments = []; |
| | | |
| | | if (organ.assessments) { |
| | | organ.assessments.forEach((assessment, index) => { |
| | | if (assessment.attachments) { |
| | | assessment.attachments.forEach(att => { |
| | | attachments.push({ |
| | | ...att, |
| | | assessmentIndex: index, |
| | | assessmentNumber: index + 1 |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | return attachments; |
| | | }, |
| | | |
| | | // 预览附件 |
| | | handlePreviewAttachment(attachment) { |
| | | this.currentPreviewFile = { |
| | | fileName: attachment.fileName, |
| | | fileUrl: attachment.path || attachment.fileUrl, |
| | | fileType: this.getFileType(attachment.fileName) |
| | | }; |
| | | this.attachmentVisible = 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", "ppt", "pptx"]; |
| | | |
| | | if (imageTypes.includes(extension)) return "image"; |
| | | if (pdfTypes.includes(extension)) return "pdf"; |
| | | if (officeTypes.includes(extension)) return "office"; |
| | | return "other"; |
| | | }, |
| | | |
| | | // 获取评估状态标签类型 |
| | | getAssessmentTagType(status) { |
| | | const typeMap = { |
| | | 'pending': 'info', |
| | | 'assessing': 'warning', |
| | | 'assessed': 'success' |
| | | pending: "warning", |
| | | assessing: "primary", |
| | | assessed: "success" |
| | | }; |
| | | return typeMap[status] || 'info'; |
| | | return typeMap[status] || "info"; |
| | | }, |
| | | |
| | | // 获取评估状态文本 |
| | | getAssessmentStatusText(status) { |
| | | const textMap = { |
| | | 'pending': '待评估', |
| | | 'assessing': '评估中', |
| | | 'assessed': '已评估' |
| | | }; |
| | | return textMap[status] || '未知'; |
| | | }, |
| | | |
| | | // 获取功能状态类型 |
| | | getFunctionStatusType(status) { |
| | | const typeMap = { |
| | | "1": "success", // 正常 |
| | | "2": "warning", // 轻度异常 |
| | | "3": "danger", // 重度异常 |
| | | "4": "info" // 无法评估 |
| | | }; |
| | | return typeMap[status] || "info"; |
| | | }, |
| | | |
| | | // 获取功能状态文本 |
| | | getFunctionStatusText(status) { |
| | | const textMap = { |
| | | "1": "正常", |
| | | "2": "轻度异常", |
| | | "3": "重度异常", |
| | | "4": "无法评估" |
| | | pending: "待评估", |
| | | assessing: "评估中", |
| | | assessed: "已评估" |
| | | }; |
| | | return textMap[status] || "未知"; |
| | | }, |
| | |
| | | // 获取行类名 |
| | | getRowClassName({ row }) { |
| | | return this.canAssessOrgan(row) ? "assessable-row" : "non-assessable-row"; |
| | | }, |
| | | |
| | | // 格式化时间 |
| | | formatTime(time) { |
| | | if (!time) return ''; |
| | | return new Date(time).toLocaleString(); |
| | | }, |
| | | |
| | | // 查看器官详情 |
| | | handleViewOrganDetail(organ) { |
| | | this.currentOrgan = JSON.parse(JSON.stringify(organ)); |
| | | this.activeAssessmentTab = 'first'; |
| | | this.organDetailVisible = true; |
| | | }, |
| | | |
| | | // 器官评估 |
| | | handleOrganAssess(organ) { |
| | | this.currentOrgan = JSON.parse(JSON.stringify(organ)); |
| | | this.activeAssessmentTab = 'first'; |
| | | this.organDetailVisible = true; |
| | | }, |
| | | |
| | | // 保存单个评估 |
| | | handleSaveOrganAssessment(assessmentData, assessmentType) { |
| | | const organToUpdate = { |
| | | ...this.currentOrgan, |
| | | [assessmentType === 'first' ? 'firstAssessment' : 'secondAssessment']: { |
| | | ...assessmentData, |
| | | status: 'assessed', |
| | | assessmentTime: new Date().toISOString(), |
| | | assessor: this.currentUser.name |
| | | } |
| | | }; |
| | | |
| | | // 更新整体状态 |
| | | organToUpdate.assessmentStatus = this.calculateOverallStatus(organToUpdate); |
| | | |
| | | updateOrganAssessment(organToUpdate) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success(`${assessmentType === 'first' ? '第一次' : '第二次'}评估保存成功`); |
| | | this.getAssessmentDetail(); |
| | | // 自动切换到下一个未完成的评估或汇总页 |
| | | this.autoSwitchTab(assessmentType); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("保存评估失败:", error); |
| | | this.$message.error("保存失败"); |
| | | }); |
| | | }, |
| | | |
| | | // 自动切换Tab页 |
| | | autoSwitchTab(currentType) { |
| | | if (currentType === 'first' && this.currentOrgan.secondAssessment.status === 'pending') { |
| | | this.activeAssessmentTab = 'second'; |
| | | } else if (currentType === 'second' || |
| | | (currentType === 'first' && this.currentOrgan.secondAssessment.status === 'assessed')) { |
| | | this.activeAssessmentTab = 'summary'; |
| | | } |
| | | }, |
| | | |
| | | // 保存所有评估 |
| | | handleSaveAllAssessments() { |
| | | this.$confirm("确认保存所有评估数据吗?", "确认保存", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }).then(() => { |
| | | const organToUpdate = JSON.parse(JSON.stringify(this.currentOrgan)); |
| | | |
| | | // 更新整体状态 |
| | | organToUpdate.assessmentStatus = this.calculateOverallStatus(organToUpdate); |
| | | |
| | | updateOrganAssessment(organToUpdate) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("所有评估数据保存成功"); |
| | | this.getAssessmentDetail(); |
| | | this.organDetailVisible = false; |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error("保存评估失败:", error); |
| | | this.$message.error("保存失败"); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // 获取所有附件 |
| | | getAllAttachments(organ) { |
| | | const attachments = []; |
| | | |
| | | if (organ.firstAssessment.attachments) { |
| | | organ.firstAssessment.attachments.forEach(att => { |
| | | attachments.push({ |
| | | ...att, |
| | | assessmentType: 'first' |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | if (organ.secondAssessment.attachments) { |
| | | organ.secondAssessment.attachments.forEach(att => { |
| | | attachments.push({ |
| | | ...att, |
| | | assessmentType: 'second' |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | return attachments; |
| | | }, |
| | | |
| | | // 预览附件 |
| | | handlePreviewAttachment(attachment) { |
| | | // 实现附件预览逻辑 |
| | | console.log('预览附件:', attachment); |
| | | this.$message.info('附件预览功能待实现'); |
| | | }, |
| | | |
| | | // 状态过滤器 |
| | |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .assessment-time { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | /* Tab页样式优化 */ |
| | | .organ-detail-dialog ::v-deep .el-dialog__body { |
| | | /* 展开行样式 */ |
| | | .organ-expand-content { |
| | | padding: 20px; |
| | | max-height: 70vh; |
| | | overflow-y: auto; |
| | | background: #fafafa; |
| | | border-radius: 4px; |
| | | margin: 10px 0; |
| | | } |
| | | |
| | | .organ-detail-dialog ::v-deep .el-tabs__content { |
| | | padding: 20px 0; |
| | | min-height: 400px; |
| | | .organ-detail-tabs { |
| | | background: white; |
| | | border-radius: 4px; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .add-assessment-prompt { |
| | | text-align: center; |
| | | padding: 40px 0; |
| | | } |
| | | |
| | | .assessment-summary { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | padding-top: 20px; |
| | | border-top: 1px solid #ebeef5; |
| | | } |
| | | |
| | | /* 响应式设计 */ |
| | | @media (max-width: 768px) { |
| | | .organ-detail-dialog { |
| | | width: 95% !important; |
| | | .assessment-detail { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .assessment-detail { |
| | | .organ-expand-content { |
| | | padding: 10px; |
| | | } |
| | | } |
| | |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | ::v-deep .el-descriptions__label { |
| | | width: 120px; |
| | | background-color: #f5f7fa; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .fixed-width .el-button { |
| | | margin: 0 2px; |
| | | } |
| | | |
| | | .jstitle { |
| | | float: right; |
| | | font-size: 18px !important; |
| | |
| | | font-size: 12px; |
| | | } |
| | | |
| | | /* Tab页激活状态样式 */ |
| | | ::v-deep .el-tabs__item.is-active { |
| | | color: #409EFF; |
| | | /* 表格展开图标样式 */ |
| | | ::v-deep .el-table__expand-icon { |
| | | cursor: pointer; |
| | | } |
| | | |
| | | ::v-deep .el-table__expanded-cell { |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | /* 确保描述列表标签宽度一致 */ |
| | | ::v-deep .el-descriptions__label { |
| | | width: 120px; |
| | | background-color: #f5f7fa; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | /* 评估表单样式 */ |
| | | .assessment-form-section { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .assessment-form-section h3 { |
| | | margin-bottom: 15px; |
| | | color: #303133; |
| | | border-left: 4px solid #409EFF; |
| | | padding-left: 10px; |
| | | .fixed-width .el-button { |
| | | margin: 0 2px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="organ-assessment-form"> |
| | | <el-form :model="organData" label-width="120px"> |
| | | <el-form :model="assessmentData" label-width="120px"> |
| | | <el-form-item label="功能状态"> |
| | | <el-select v-model="organData.functionStatus" :disabled="readonly"> |
| | | <el-select v-model="assessmentData.functionStatus" :disabled="readonly"> |
| | | <el-option label="正常" value="1" /> |
| | | <el-option label="轻度异常" value="2" /> |
| | | <el-option label="重度异常" value="3" /> |
| | |
| | | <el-form-item label="评估意见"> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="organData.assessmentOpinion" |
| | | v-model="assessmentData.assessmentOpinion" |
| | | :rows="4" |
| | | :disabled="readonly" |
| | | placeholder="请输入评估意见" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <!-- 器官级别附件管理 --> |
| | | <!-- 附件上传区域 --> |
| | | <el-form-item label="相关附件"> |
| | | <div class="attachment-section"> |
| | | <el-upload |
| | | v-if="!readonly" |
| | | class="attachment-upload" |
| | | action="/api/attachment/upload" |
| | | :headers="uploadHeaders" |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | :before-upload="beforeUpload" |
| | | :show-file-list="false" |
| | | :multiple="true" |
| | | > |
| | | <el-button size="small" type="primary" icon="el-icon-upload"> |
| | | 上传附件 |
| | | </el-button> |
| | | <div slot="tip" class="el-upload__tip"> |
| | | 支持图片、文档等格式,单个文件不超过10MB |
| | | </div> |
| | | </el-upload> |
| | | |
| | | <!-- 附件列表 --> |
| | | <div v-if="organData.attachments && organData.attachments.length > 0" class="attachment-list"> |
| | | <div v-for="file in organData.attachments" :key="file.id" class="attachment-item"> |
| | | <div class="file-info"> |
| | | <i :class="getFileIcon(file.fileType)" class="file-icon"></i> |
| | | <span class="file-name" :title="file.fileName">{{ file.fileName }}</span> |
| | | <span class="file-size">({{ formatFileSize(file.fileSize) }})</span> |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button type="text" size="mini" @click="handlePreview(file)">预览</el-button> |
| | | <el-button type="text" size="mini" @click="handleDownload(file)">下载</el-button> |
| | | <el-button |
| | | v-if="!readonly" |
| | | type="text" |
| | | size="mini" |
| | | style="color: #F56C6C;" |
| | | @click="handleDeleteFile(file)" |
| | | >删除</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="attachment-header"> |
| | | <i class="el-icon-paperclip"></i> |
| | | <span class="attachment-title">附件上传</span> |
| | | <span class="attachment-tip" |
| | | >支持上传检验报告单等文件 (最多{{ attachmentLimit }}个)</span |
| | | > |
| | | </div> |
| | | |
| | | <div v-else class="no-attachment"> |
| | | <el-empty description="暂无附件" :image-size="50"></el-empty> |
| | | <!-- 使用 UploadAttachment 组件 --> |
| | | <UploadAttachment |
| | | ref="uploadAttachment" |
| | | :file-list="attachmentFileList" |
| | | :limit="attachmentLimit" |
| | | :accept="attachmentAccept" |
| | | :multiple="true" |
| | | @change="handleAttachmentChange" |
| | | @upload-success="handleUploadSuccess" |
| | | @upload-error="handleUploadError" |
| | | @remove="handleAttachmentRemove" |
| | | /> |
| | | |
| | | <!-- 附件列表 --> |
| | | <div |
| | | class="attachment-list" |
| | | v-if=" |
| | | assessmentData.attachments && |
| | | assessmentData.attachments.length > 0 |
| | | " |
| | | > |
| | | <div class="list-title"> |
| | | 已上传附件 ({{ assessmentData.attachments.length }}) |
| | | </div> |
| | | <el-table |
| | | :data="assessmentData.attachments" |
| | | style="width: 100%" |
| | | size="small" |
| | | > |
| | | <el-table-column label="文件名" min-width="200"> |
| | | <template slot-scope="scope"> |
| | | <i |
| | | class="el-icon-document" |
| | | :style="{ color: getFileIconColor(scope.row.fileName) }" |
| | | ></i> |
| | | <span class="file-name">{{ scope.row.fileName }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="文件类型" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-tag |
| | | :type="getFileTagType(scope.row.fileName)" |
| | | size="small" |
| | | > |
| | | {{ getFileTypeText(scope.row.fileName) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="上传时间" width="160"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatDateTime(scope.row.uploadTime) }}</span> |
| | | </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="266" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="primary" |
| | | @click="handlePreview(scope.row)" |
| | | :disabled="!isPreviewable(scope.row.fileName)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | size="mini" |
| | | type="success" |
| | | @click="handleDownload(scope.row)" |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="!readonly" |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveAttachment(scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | |
| | | <el-form-item v-if="!readonly"> |
| | | <el-button type="primary" @click="handleSave">保存评估</el-button> |
| | | <el-button @click="handleCancel">取消</el-button> |
| | | <el-button |
| | | type="success" |
| | | @click="handleAddAssessment" |
| | | icon="el-icon-plus" |
| | | > |
| | | 新增评估记录 |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 附件预览弹窗 --> |
| | | <el-dialog |
| | | :title="`附件预览 - ${currentFile.fileName}`" |
| | | :visible.sync="previewVisible" |
| | | width="60%" |
| | | > |
| | | <div v-if="isImage(currentFile.fileType)" class="image-preview"> |
| | | <img :src="currentFile.fileUrl" alt="预览图片" style="max-width: 100%;" /> |
| | | </div> |
| | | <div v-else class="file-preview"> |
| | | <el-alert |
| | | title="该文件格式不支持在线预览,请下载后查看" |
| | | type="info" |
| | | show-icon |
| | | /> |
| | | <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> |
| | | <!-- 文件预览弹窗 --> |
| | | <FilePreviewDialog |
| | | :visible="previewVisible" |
| | | :file="currentPreviewFile" |
| | | @close="previewVisible = false" |
| | | @download="handleDownload" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getToken } from '@/utils/auth' |
| | | import UploadAttachment from "@/components/UploadAttachment"; |
| | | import FilePreviewDialog from "@/components/FilePreviewDialog"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | export default { |
| | | name: "OrganAssessmentForm", |
| | | components: { |
| | | UploadAttachment, |
| | | FilePreviewDialog |
| | | }, |
| | | props: { |
| | | organData: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | assessmentData: { |
| | | type: Object, |
| | | default: () => ({ |
| | | attachments: [] // 确保有附件数组 |
| | | functionStatus: "", |
| | | assessmentOpinion: "", |
| | | attachments: [] |
| | | }) |
| | | }, |
| | | assessmentIndex: { |
| | | type: Number, |
| | | default: 0 |
| | | }, |
| | | readonly: { |
| | | type: Boolean, |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | // 预览相关 |
| | | previewVisible: false, |
| | | currentFile: {}, |
| | | uploadHeaders: { |
| | | Authorization: 'Bearer ' + getToken() |
| | | } |
| | | currentPreviewFile: null, |
| | | |
| | | // 附件相关配置 |
| | | attachmentLimit: 10, |
| | | attachmentAccept: |
| | | ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt", |
| | | attachmentFileList: [] |
| | | }; |
| | | }, |
| | | watch: { |
| | | organData: { |
| | | handler(newVal, oldVal) { |
| | | // 只有当附件数据真正发生变化时才初始化 |
| | | if ( |
| | | !oldVal || |
| | | !oldVal.attachments || |
| | | JSON.stringify(newVal.attachments) !== |
| | | JSON.stringify(oldVal.attachments) |
| | | ) { |
| | | this.initAttachmentList(); |
| | | } |
| | | }, |
| | | immediate: true, |
| | | deep: true |
| | | } |
| | | }, |
| | | methods: { |
| | | /** 初始化附件列表 */ |
| | | initAttachmentList() { |
| | | if (this.organData.attachments && this.organData.attachments.length > 0) { |
| | | this.assessmentData.attachments = [...this.organData.attachments]; |
| | | this.attachmentFileList = this.organData.attachments.map(item => ({ |
| | | uid: item.id || Math.random(), |
| | | name: item.fileName, |
| | | url: item.path || item.fileUrl, |
| | | status: "success" |
| | | })); |
| | | } else { |
| | | this.assessmentData.attachments = []; |
| | | this.attachmentFileList = []; |
| | | } |
| | | }, |
| | | handleSave() { |
| | | this.$emit('save', { |
| | | ...this.organData, |
| | | assessmentTime: new Date().toISOString(), |
| | | assessor: '当前用户' |
| | | }); |
| | | const saveData = { |
| | | organData: this.organData, |
| | | assessmentData: this.assessmentData, |
| | | assessmentIndex: this.assessmentIndex |
| | | }; |
| | | this.$emit("save", saveData); |
| | | }, |
| | | |
| | | handleCancel() { |
| | | this.$emit('cancel'); |
| | | this.$emit("cancel"); |
| | | }, |
| | | |
| | | // 文件上传处理 |
| | | handleUploadSuccess(response, file) { |
| | | handleAddAssessment() { |
| | | this.$emit("add-assessment", { |
| | | organData: this.organData, |
| | | currentIndex: this.assessmentIndex |
| | | }); |
| | | }, |
| | | /** 附件变化处理 */ |
| | | handleAttachmentChange(fileList) { |
| | | this.attachmentFileList = fileList; |
| | | }, |
| | | |
| | | /** 附件移除处理 */ |
| | | handleAttachmentRemove(file) { |
| | | if (file.url) { |
| | | const index = this.assessmentData.attachments.findIndex( |
| | | item => item.path === file.url || item.fileUrl === file.url |
| | | ); |
| | | if (index > -1) { |
| | | this.assessmentData.attachments.splice(index, 1); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | /** 手动删除附件 */ |
| | | handleRemoveAttachment(index) { |
| | | this.assessmentData.attachments.splice(index, 1); |
| | | this.attachmentFileList.splice(index, 1); |
| | | this.$message.success("附件删除成功"); |
| | | }, |
| | | |
| | | /** 上传成功处理 */ |
| | | handleUploadSuccess({ file, fileList, response }) { |
| | | if (response.code === 200) { |
| | | // 将新文件添加到附件列表 |
| | | const newFile = { |
| | | id: response.data.fileId, |
| | | const attachmentObj = { |
| | | id: |
| | | response.data.fileId || |
| | | Math.random() |
| | | .toString(36) |
| | | .substr(2), |
| | | fileName: file.name, |
| | | path: response.data.fileUrl || file.url, |
| | | fileUrl: response.data.fileUrl || file.url, |
| | | fileType: this.getFileExtension(file.name), |
| | | fileSize: file.size, |
| | | fileUrl: response.data.fileUrl, |
| | | uploadTime: new Date().toISOString() |
| | | uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | assessmentType: this.assessmentType, |
| | | organType: this.organData.organType |
| | | }; |
| | | |
| | | if (!this.organData.attachments) { |
| | | this.organData.attachments = []; |
| | | } |
| | | this.organData.attachments.push(newFile); |
| | | |
| | | this.$message.success('文件上传成功'); |
| | | this.assessmentData.attachments.push(attachmentObj); |
| | | this.$message.success("文件上传成功"); |
| | | } |
| | | }, |
| | | |
| | | handleUploadError(error) { |
| | | console.error('文件上传失败:', error); |
| | | this.$message.error('文件上传失败'); |
| | | /** 上传错误处理 */ |
| | | handleUploadError({ file, fileList, error }) { |
| | | console.error("附件上传失败:", error); |
| | | this.$message.error("文件上传失败,请重试"); |
| | | }, |
| | | |
| | | beforeUpload(file) { |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | this.$message.error('文件大小不能超过 10MB'); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | |
| | | // 文件操作 |
| | | /** 文件预览 */ |
| | | handlePreview(file) { |
| | | this.currentFile = file; |
| | | this.currentPreviewFile = { |
| | | fileName: file.fileName, |
| | | fileUrl: file.path || file.fileUrl, |
| | | fileType: this.getFileType(file.fileName) |
| | | }; |
| | | this.previewVisible = true; |
| | | }, |
| | | |
| | | /** 文件下载 */ |
| | | handleDownload(file) { |
| | | // 模拟文件下载 |
| | | const link = document.createElement('a'); |
| | | link.href = file.fileUrl; |
| | | link.download = file.fileName; |
| | | link.click(); |
| | | this.$message.success('开始下载文件'); |
| | | 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("文件路径不存在,无法下载"); |
| | | } |
| | | }, |
| | | |
| | | handleDeleteFile(file) { |
| | | this.$confirm('确定要删除这个附件吗?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | const index = this.organData.attachments.findIndex(f => f.id === file.id); |
| | | if (index !== -1) { |
| | | this.organData.attachments.splice(index, 1); |
| | | this.$message.success('删除成功'); |
| | | } |
| | | }); |
| | | /** 获取文件类型 */ |
| | | 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"; |
| | | }, |
| | | |
| | | // 工具方法 |
| | | getFileIcon(fileType) { |
| | | 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' |
| | | /** 获取文件图标颜色 */ |
| | | getFileIconColor(fileName) { |
| | | const type = this.getFileType(fileName); |
| | | const colorMap = { |
| | | image: "#67C23A", |
| | | pdf: "#F56C6C", |
| | | office: "#409EFF", |
| | | other: "#909399" |
| | | }; |
| | | return iconMap[fileType] || 'el-icon-document'; |
| | | return colorMap[type] || "#909399"; |
| | | }, |
| | | |
| | | /** 获取文件标签类型 */ |
| | | getFileTagType(fileName) { |
| | | const type = this.getFileType(fileName); |
| | | const typeMap = { |
| | | image: "success", |
| | | pdf: "danger", |
| | | office: "primary", |
| | | other: "info" |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }, |
| | | |
| | | /** 获取文件类型文本 */ |
| | | getFileTypeText(fileName) { |
| | | const type = this.getFileType(fileName); |
| | | const textMap = { |
| | | image: "图片", |
| | | pdf: "PDF", |
| | | office: "文档", |
| | | other: "其他" |
| | | }; |
| | | return textMap[type] || "未知"; |
| | | }, |
| | | |
| | | /** 检查是否可预览 */ |
| | | isPreviewable(fileName) { |
| | | const type = this.getFileType(fileName); |
| | | return ["image", "pdf"].includes(type); |
| | | }, |
| | | |
| | | /** 获取文件扩展名 */ |
| | | getFileExtension(filename) { |
| | | return filename.split('.').pop().toLowerCase(); |
| | | return filename |
| | | .split(".") |
| | | .pop() |
| | | .toLowerCase(); |
| | | }, |
| | | |
| | | /** 格式化文件大小 */ |
| | | formatFileSize(bytes) { |
| | | if (bytes === 0) return '0 B'; |
| | | if (!bytes || bytes === 0) return "0 B"; |
| | | const k = 1024; |
| | | const sizes = ['B', 'KB', 'MB', 'GB']; |
| | | 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]; |
| | | return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; |
| | | }, |
| | | |
| | | isImage(fileType) { |
| | | const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp']; |
| | | return imageTypes.includes(fileType); |
| | | /** 日期时间格式化 */ |
| | | 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"); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}`; |
| | | } catch (error) { |
| | | return dateTime; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 4px; |
| | | padding: 15px; |
| | | background: #fafafa; |
| | | } |
| | | |
| | | .attachment-upload { |
| | | margin-bottom: 15px; |
| | | .attachment-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 16px; |
| | | padding-bottom: 8px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .attachment-title { |
| | | font-weight: bold; |
| | | margin: 0 8px; |
| | | color: #303133; |
| | | } |
| | | |
| | | .attachment-tip { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | margin-left: auto; |
| | | } |
| | | |
| | | .attachment-list { |
| | | max-height: 300px; |
| | | overflow-y: auto; |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .attachment-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 8px 12px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .attachment-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .file-info { |
| | | display: flex; |
| | | align-items: center; |
| | | flex: 1; |
| | | } |
| | | |
| | | .file-icon { |
| | | margin-right: 8px; |
| | | font-size: 16px; |
| | | color: #409EFF; |
| | | .list-title { |
| | | font-weight: bold; |
| | | margin-bottom: 12px; |
| | | color: #303133; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .file-name { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | margin-right: 8px; |
| | | font-size: 13px; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .file-size { |
| | | color: #909399; |
| | | ::v-deep .el-upload__tip { |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .file-actions { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .no-attachment { |
| | | text-align: center; |
| | | padding: 20px; |
| | | color: #909399; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | ::v-deep .el-table .cell { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | ::v-deep .el-button--mini { |
| | | padding: 5px 10px; |
| | | font-size: 12px; |
| | | } |
| | | </style> |
| | |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="业务人员" prop="assignee"> |
| | | <el-form-item label="业务人员" prop="coordinatorName"> |
| | | <el-input |
| | | v-model="queryParams.assignee" |
| | | v-model="queryParams.coordinatorName" |
| | | placeholder="请输入业务人员" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="评估状态" prop="assessmentStatus"> |
| | | <el-form-item label="评估状态" prop="firstAssessState"> |
| | | <el-select |
| | | v-model="queryParams.assessmentStatus" |
| | | v-model="queryParams.firstAssessState" |
| | | placeholder="请选择评估状态" |
| | | clearable |
| | | style="width: 200px" |
| | |
| | | </el-form-item> |
| | | <el-form-item label="申请时间" prop="applyTimeRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.applyTimeRange" |
| | | v-model="applyTimeRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | |
| | | </el-form-item> |
| | | <el-form-item label="评估时间" prop="assessmentTimeRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.assessmentTimeRange" |
| | | v-model="assessmentTimeRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | |
| | | <el-table-column |
| | | label="评估状态" |
| | | align="center" |
| | | prop="assessmentStatus" |
| | | prop="firstAssessState" |
| | | width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="statusFilter(scope.row.assessmentStatus)"> |
| | | {{ statusTextFilter(scope.row.assessmentStatus) }} |
| | | <el-tag :type="statusFilter(scope.row.firstAssessState)"> |
| | | {{ statusTextFilter(scope.row.firstAssessState) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="业务人员" |
| | | align="center" |
| | | prop="assignee" |
| | | prop="coordinatorName" |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | <!-- <el-table-column |
| | | label="评估类型" |
| | | align="center" |
| | | prop="assessmentType" |
| | |
| | | :value="parseInt(scope.row.assessmentType)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> --> |
| | | <el-table-column |
| | | label="操作" |
| | | align="center" |
| | |
| | | > |
| | | <el-button |
| | | v-if=" |
| | | scope.row.assessmentStatus === '0' || |
| | | scope.row.assessmentStatus === '1' |
| | | scope.row.firstAssessState === '0' || |
| | | scope.row.firstAssessState === '1' |
| | | " |
| | | size="mini" |
| | | type="text" |
| | |
| | | >评估</el-button |
| | | > |
| | | <el-button |
| | | v-if="scope.row.assessmentStatus === '2'" |
| | | v-if="scope.row.firstAssessState === '2'" |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-check" |
| | |
| | | delAssessment, |
| | | exportAssessment |
| | | } from "./mockAssessmentApi"; |
| | | |
| | | import { evaluateBaseInfolist } from "@/api/businessApi/index"; |
| | | import Pagination from "@/components/Pagination"; |
| | | |
| | | export default { |
| | |
| | | pageSize: 10, |
| | | donorName: undefined, |
| | | hospitalName: undefined, |
| | | assignee: undefined, |
| | | assessmentStatus: undefined, |
| | | applyTimeRange: [], |
| | | assessmentTimeRange: [] |
| | | coordinatorName: undefined, |
| | | firstAssessState: undefined, |
| | | |
| | | }, |
| | | applyTimeRange: [], |
| | | assessmentTimeRange: [], |
| | | // 性别选项 |
| | | genderOptions: [ |
| | | { value: "0", label: "男" }, |
| | |
| | | // 查询评估列表 |
| | | getList() { |
| | | this.loading = true; |
| | | evaluateBaseInfolist(this.queryParams); |
| | | listAssessment(this.queryParams) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | |
| | | > |
| | | 保存信息 |
| | | </el-button> |
| | | <el-button |
| | | v-else |
| | | type="primary" |
| | | style="float: right; padding: 3px 0" |
| | | @click="handleEdit" |
| | | > |
| | | 编辑信息 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <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-form-item label="捐献者编号" prop="donorno"> |
| | | <el-input |
| | | v-model="form.hospitalNo" |
| | | v-model="form.donorno" |
| | | :readonly="!isEdit" |
| | | placeholder="自动生成 D+数字" |
| | | placeholder="自动生成捐献者编号" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="捐献者姓名" prop="donorName"> |
| | | <el-input v-model="form.donorName" :readonly="!isEdit" /> |
| | | <el-form-item label="捐献者姓名" prop="name"> |
| | | <el-input v-model="form.name" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="性别" prop="gender"> |
| | | <el-form-item label="性别" prop="sex"> |
| | | <el-select |
| | | v-model="form.gender" |
| | | v-model="form.sex" |
| | | :disabled="!isEdit" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="男" value="0" /> |
| | | <el-option label="女" value="1" /> |
| | | <el-option label="男" value="1" /> |
| | | <el-option label="女" value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="疾病诊断" prop="diagnosis"> |
| | | <el-input v-model="form.diagnosis" :readonly="!isEdit" /> |
| | | <el-form-item label="疾病诊断" prop="diagnosisname"> |
| | | <el-input v-model="form.diagnosisname" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="死亡原因" prop="deathReason"> |
| | | <el-form-item label="死亡原因" prop="deathreason"> |
| | | <el-select |
| | | v-model="form.deathReason" |
| | | v-model="form.deathreason" |
| | | :disabled="!isEdit" |
| | | style="width: 100%" |
| | | > |
| | |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="死亡时间" prop="deathTime"> |
| | | <el-form-item label="死亡时间" prop="deathtime"> |
| | | <el-date-picker |
| | | v-model="form.deathTime" |
| | | v-model="form.deathtime" |
| | | 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="judgmentDoctor"> |
| | | <el-input v-model="form.judgmentDoctorone" :readonly="!isEdit" /> |
| | | <el-col :span="8"> |
| | | <el-form-item label="判定医生一" prop="deathjudgedocto"> |
| | | <el-input v-model="form.deathjudgedocto" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="判定医生二" prop="judgmentDoctor"> |
| | | <el-input v-model="form.judgmentDoctortwo" :readonly="!isEdit" /> |
| | | <el-form-item label="判定医生二" prop="deathjudgedoctt"> |
| | | <el-input v-model="form.deathjudgedoctt" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="登记人" prop="registrant"> |
| | | <el-input v-model="form.registrant" :readonly="!isEdit" /> |
| | | <el-form-item label="器官获取机构" prop="gainhospitalname"> |
| | | <el-input v-model="form.gainhospitalname" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="是否默哀缅怀" prop="isspendremember"> |
| | | <el-select |
| | | v-model="form.isspendremember" |
| | | :disabled="!isEdit" |
| | | 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="isrestoreremains"> |
| | | <el-select |
| | | v-model="form.isrestoreremains" |
| | | :disabled="!isEdit" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="是" :value="1" /> |
| | | <el-option label="否" :value="0" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="负责人" prop="responsibleusername"> |
| | | <el-input v-model="form.responsibleusername" :readonly="!isEdit" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="记录状态" prop="recordstate"> |
| | | <el-tag :type="getStatusTag(form.recordstate)"> |
| | | {{ getStatusText(form.recordstate) }} |
| | | </el-tag> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDeathJudgmentDetail, updateDeathJudgment } from "./mockDeathJudgmentApi"; |
| | | import { deathinfoedit, deathinfoInfo } from "@/api/businessApi"; |
| | | |
| | | export default { |
| | | name: "DeathJudgmentDetail", |
| | |
| | | // 表单数据 |
| | | form: { |
| | | id: undefined, |
| | | hospitalNo: "", |
| | | donorName: "", |
| | | gender: "", |
| | | infoid: undefined, |
| | | donorno: "", |
| | | name: "", |
| | | sex: "", |
| | | age: "", |
| | | diagnosis: "", |
| | | deathReason: "", |
| | | deathTime: "", |
| | | judgmentDoctor: "", |
| | | judgmentDescription: "", |
| | | registrant: "", |
| | | registrationTime: "" |
| | | diagnosisname: "", |
| | | deathreason: "", |
| | | deathtime: "", |
| | | deathjudgedocto: "", |
| | | deathjudgedoctt: "", |
| | | gainhospitalno: "", |
| | | gainhospitalname: "", |
| | | isspendremember: 0, |
| | | isrestoreremains: 0, |
| | | rememberannex: "", |
| | | responsibleuserid: "", |
| | | responsibleusername: "", |
| | | recordstate: "0", |
| | | judgmentDescription: "" |
| | | }, |
| | | // 表单验证规则 |
| | | rules: { |
| | | donorName: [ |
| | | name: [ |
| | | { required: true, message: "捐献者姓名不能为空", trigger: "blur" } |
| | | ], |
| | | deathReason: [ |
| | | deathreason: [ |
| | | { required: true, message: "死亡原因不能为空", trigger: "change" } |
| | | ], |
| | | deathTime: [ |
| | | deathtime: [ |
| | | { required: true, message: "死亡时间不能为空", trigger: "change" } |
| | | ], |
| | | judgmentDoctor: [ |
| | | { required: true, message: "判定医生不能为空", trigger: "blur" } |
| | | deathjudgedocto: [ |
| | | { required: true, message: "判定医生一不能为空", trigger: "blur" } |
| | | ] |
| | | }, |
| | | // 附件相关数据 |
| | |
| | | if (id && !this.$route.path.includes('/add')) { |
| | | this.getDetail(id); |
| | | } else if (this.$route.path.includes('/add')) { |
| | | this.generateHospitalNo(); |
| | | this.generateDonorNo(); |
| | | } |
| | | this.getAttachmentList(); |
| | | }, |
| | | methods: { |
| | | // 生成住院号 |
| | | generateHospitalNo() { |
| | | // 模拟生成住院号:D + 时间戳后6位 |
| | | // 生成捐献者编号 |
| | | generateDonorNo() { |
| | | const timestamp = Date.now().toString(); |
| | | this.form.hospitalNo = 'D' + timestamp.slice(-6); |
| | | this.form.donorno = 'DONOR' + timestamp.slice(-8); |
| | | }, |
| | | // 获取详情 |
| | | getDetail(id) { |
| | | getDeathJudgmentDetail(id).then(response => { |
| | | if (response.code === 200) { |
| | | this.form = response.data; |
| | | async getDetail(id) { |
| | | try { |
| | | const response = await deathinfoInfo({ id }); |
| | | let realData = {}; |
| | | |
| | | if (response && response.data) { |
| | | realData = response.data; |
| | | } else if (response) { |
| | | realData = response; |
| | | } |
| | | }); |
| | | |
| | | // 映射字段到表单 |
| | | this.form = { |
| | | ...this.form, |
| | | ...realData, |
| | | // 确保数值类型字段正确转换 |
| | | isspendremember: realData.isspendremember ? parseInt(realData.isspendremember) : 0, |
| | | isrestoreremains: realData.isrestoreremains ? parseInt(realData.isrestoreremains) : 0 |
| | | }; |
| | | |
| | | // 解析附件信息 |
| | | if (realData.rememberannex) { |
| | | this.parseAttachmentData(realData.rememberannex); |
| | | } |
| | | |
| | | } catch (error) { |
| | | console.error('获取死亡判定详情失败:', error); |
| | | this.$message.error('数据加载失败'); |
| | | } |
| | | }, |
| | | // 解析附件数据 |
| | | parseAttachmentData(attachmentJson) { |
| | | try { |
| | | if (attachmentJson) { |
| | | const attachments = JSON.parse(attachmentJson); |
| | | if (Array.isArray(attachments)) { |
| | | this.attachmentList = attachments; |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('解析附件数据失败:', error); |
| | | } |
| | | }, |
| | | // 构建附件JSON数据 |
| | | buildAttachmentJson() { |
| | | return JSON.stringify(this.attachmentList); |
| | | }, |
| | | // 获取状态标签样式 |
| | | getStatusTag(status) { |
| | | const statusMap = { |
| | | "0": "warning", // 维护中 |
| | | "1": "success", // 已完成 |
| | | "99": "danger" // 已终止 |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | // 获取状态文本 |
| | | getStatusText(status) { |
| | | const textMap = { |
| | | "0": "维护中", |
| | | "1": "已完成", |
| | | "99": "已终止" |
| | | }; |
| | | return textMap[status] || "未知状态"; |
| | | }, |
| | | // 获取附件列表 |
| | | getAttachmentList() { |
| | | this.attachmentLoading = true; |
| | | // 模拟附件数据 - 实际项目中从接口获取 |
| | | // 实际项目中从接口获取附件数据 |
| | | setTimeout(() => { |
| | | this.attachmentList = [ |
| | | { |
| | | id: 1, |
| | | type: "1", |
| | | typeName: "脑死亡判定表", |
| | | fileName: "脑死亡判定表_202512001.pdf", |
| | | fileSize: 2548321, |
| | | uploadTime: "2025-12-01 10:30:00", |
| | | uploader: "张医生", |
| | | fileUrl: "/attachments/brain_death_1.pdf" |
| | | }, |
| | | { |
| | | id: 2, |
| | | type: "2", |
| | | typeName: "脑电图评估表", |
| | | fileName: "脑电图评估表_202512001.docx", |
| | | fileSize: 512345, |
| | | uploadTime: "2025-12-01 14:20:00", |
| | | uploader: "李医生", |
| | | fileUrl: "/attachments/eeg_1.docx" |
| | | } |
| | | ]; |
| | | this.attachmentLoading = false; |
| | | }, 500); |
| | | }, |
| | |
| | | |
| | | const maxSize = 10 * 1024 * 1024; // 10MB |
| | | |
| | | // 校验文件类型 |
| | | const isTypeOk = allowedTypes.includes(file.type) || |
| | | file.name.endsWith('.pdf') || |
| | | file.name.endsWith('.jpg') || |
| | |
| | | return false; |
| | | } |
| | | |
| | | // 校验文件大小 |
| | | if (file.size > maxSize) { |
| | | this.$message.error('文件大小不能超过10MB'); |
| | | return false; |
| | |
| | | this.uploadLoading = true; |
| | | |
| | | try { |
| | | // 模拟上传过程 - 实际项目中调用上传接口 |
| | | for (const file of this.tempFileList) { |
| | | const newAttachment = { |
| | | id: Date.now() + Math.random(), |
| | |
| | | |
| | | this.attachmentList.push(newAttachment); |
| | | } |
| | | |
| | | // 更新附件JSON数据到表单 |
| | | this.form.rememberannex = this.buildAttachmentJson(); |
| | | |
| | | this.$message.success('文件上传成功'); |
| | | this.uploadDialogVisible = false; |
| | |
| | | const index = this.attachmentList.findIndex(item => item.id === attachment.id); |
| | | if (index !== -1) { |
| | | this.attachmentList.splice(index, 1); |
| | | // 更新附件JSON数据到表单 |
| | | this.form.rememberannex = this.buildAttachmentJson(); |
| | | this.$message.success('评估表删除成功'); |
| | | } |
| | | }).catch(() => {}); |
| | |
| | | }, |
| | | // 下载附件 |
| | | handleDownload(attachment) { |
| | | // 实际项目中调用下载接口 |
| | | const link = document.createElement('a'); |
| | | link.href = attachment.fileUrl; |
| | | link.download = attachment.fileName; |
| | | link.click(); |
| | | this.$message.success(`开始下载: ${attachment.fileName}`); |
| | | }, |
| | | // 编辑信息 |
| | | handleEdit() { |
| | | this.isEdit = true; |
| | | }, |
| | | // 保存信息 |
| | | handleSave() { |
| | | this.$refs.form.validate(valid => { |
| | | async handleSave() { |
| | | this.$refs.form.validate(async valid => { |
| | | if (valid) { |
| | | this.saveLoading = true; |
| | | |
| | | // 模拟保存过程 |
| | | updateDeathJudgment(this.form) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success('保存成功'); |
| | | if (this.$route.path.includes('/add')) { |
| | | this.$router.push('/case/deathJudgment'); |
| | | } else { |
| | | this.isEdit = false; |
| | | } |
| | | try { |
| | | // 构建提交数据 |
| | | const submitData = { |
| | | ...this.form, |
| | | // 确保附件数据最新 |
| | | rememberannex: this.buildAttachmentJson() |
| | | }; |
| | | |
| | | const response = await deathinfoedit(submitData); |
| | | |
| | | if (response.code === 200) { |
| | | this.$message.success('保存成功'); |
| | | this.isEdit = false; |
| | | |
| | | if (this.$route.path.includes('/add')) { |
| | | this.$router.push('/case/deathJudgment'); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('保存失败:', error); |
| | | this.$message.error('保存失败'); |
| | | }) |
| | | .finally(() => { |
| | | this.saveLoading = false; |
| | | }); |
| | | } else { |
| | | this.$message.error(response.message || '保存失败'); |
| | | } |
| | | } catch (error) { |
| | | console.error('保存失败:', error); |
| | | this.$message.error('保存失败'); |
| | | } finally { |
| | | this.saveLoading = false; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | |
| | | :inline="true" |
| | | label-width="100px" |
| | | > |
| | | <el-form-item label="住院号" prop="hospitalNo"> |
| | | <el-form-item label="住院号" prop="inpatientno"> |
| | | <el-input |
| | | v-model="queryParams.hospitalNo" |
| | | v-model="queryParams.inpatientno" |
| | | placeholder="请输入住院号" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="捐献者姓名" prop="donorName"> |
| | | <el-form-item label="捐献者姓名" prop="name"> |
| | | <el-input |
| | | v-model="queryParams.donorName" |
| | | v-model="queryParams.name" |
| | | placeholder="请输入捐献者姓名" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="死亡原因" prop="deathReason"> |
| | | <el-form-item label="死亡原因" prop="deathreason"> |
| | | <el-select |
| | | v-model="queryParams.deathReason" |
| | | v-model="queryParams.deathreason" |
| | | placeholder="请选择死亡原因" |
| | | clearable |
| | | style="width: 200px" |
| | |
| | | >修改</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | icon="el-icon-delete" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | >删除</el-button |
| | | > |
| | | <el-button |
| | | type="warning" |
| | | icon="el-icon-download" |
| | | @click="handleExport" |
| | |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column |
| | | label="案例编号" |
| | | align="center" |
| | | prop="caseNo" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="住院号" |
| | | align="center" |
| | | prop="hospitalNo" |
| | | prop="inpatientno" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="捐献者姓名" |
| | | align="center" |
| | | prop="donorName" |
| | | prop="name" |
| | | width="120" |
| | | /> |
| | | <el-table-column label="性别" align="center" prop="gender" width="80"> |
| | | <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.gender)" |
| | | :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="treatmenthospitalname" |
| | | width="180" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="疾病诊断" |
| | | align="center" |
| | | prop="diagnosis" |
| | | min-width="180" |
| | | prop="diagnosisname" |
| | | min-width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="死亡原因" |
| | | align="center" |
| | | prop="deathReason" |
| | | prop="deathreason" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="reasonFilter(scope.row.deathReason)"> |
| | | {{ reasonTextFilter(scope.row.deathReason) }} |
| | | <el-tag :type="reasonFilter(scope.row.deathreason)"> |
| | | {{ reasonTextFilter(scope.row.deathreason) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="死亡时间" |
| | | align="center" |
| | | prop="deathTime" |
| | | prop="deathtime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | scope.row.deathTime |
| | | ? parseTime(scope.row.deathTime, "{y}-{m}-{d} {h}:{i}") |
| | | scope.row.deathtime |
| | | ? parseTime(scope.row.deathtime, "{y}-{m}-{d} {h}:{i}") |
| | | : "-" |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="判定医生" |
| | | label="判定医生一" |
| | | align="center" |
| | | prop="judgmentDoctor" |
| | | prop="deathjudgedocto" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | <el-table-column |
| | | label="判定医生二" |
| | | align="center" |
| | | prop="judgmentDoctortwo" |
| | | prop="deathjudgedoctt" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="登记时间" |
| | | label="记录状态" |
| | | align="center" |
| | | prop="registrationTime" |
| | | prop="recordstate" |
| | | width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="statusFilter(scope.row.recordstate)"> |
| | | {{ statusTextFilter(scope.row.recordstate) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="创建时间" |
| | | align="center" |
| | | prop="createTime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | scope.row.registrationTime |
| | | ? parseTime(scope.row.registrationTime, "{y}-{m}-{d} {h}:{i}") |
| | | scope.row.createTime |
| | | ? parseTime(scope.row.createTime, "{y}-{m}-{d} {h}:{i}") |
| | | : "-" |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="登记人" |
| | | align="center" |
| | | prop="registrant" |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | label="操作" |
| | | align="center" |
| | | width="210" |
| | | width="180" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | <template slot-scope="scope"> |
| | |
| | | icon="el-icon-edit" |
| | | @click="handleUpdate(scope.row)" |
| | | >修改</el-button |
| | | > |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-delete" |
| | | style="color: #F56C6C" |
| | | @click="handleDelete(scope.row)" |
| | | >删除</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { listDeathJudgment, delDeathJudgment, exportDeathJudgment } from "./mockDeathJudgmentApi"; |
| | | import { queryDathInfoBaseInfo, deathinfoedit,deathinfoInfo } from "@/api/businessApi"; |
| | | import Pagination from "@/components/Pagination"; |
| | | |
| | | export default { |
| | |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | hospitalNo: undefined, |
| | | donorName: undefined, |
| | | deathReason: undefined, |
| | | inpatientno: undefined, |
| | | name: undefined, |
| | | deathreason: undefined, |
| | | deathTimeRange: [] |
| | | } |
| | | }, |
| | | // 所有数据(用于前端筛选) |
| | | allTableData: [] |
| | | }; |
| | | }, |
| | | created() { |
| | |
| | | // 死亡原因过滤器 |
| | | reasonFilter(reason) { |
| | | const reasonMap = { |
| | | "brain_death": "primary", // 脑死亡 |
| | | "heart_death": "danger", // 心死亡 |
| | | "other": "info" // 其他 |
| | | brain_death: "primary", |
| | | heart_death: "danger", |
| | | other: "info" |
| | | }; |
| | | return reasonMap[reason] || "info"; |
| | | }, |
| | | |
| | | reasonTextFilter(reason) { |
| | | const reasonMap = { |
| | | "brain_death": "脑死亡", |
| | | "heart_death": "心死亡", |
| | | "other": "其他" |
| | | brain_death: "脑死亡", |
| | | heart_death: "心死亡", |
| | | other: "其他" |
| | | }; |
| | | return reasonMap[reason] || "未知"; |
| | | }, |
| | | // 查询死亡判定列表 |
| | | getList() { |
| | | this.loading = true; |
| | | listDeathJudgment(this.queryParams) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.deathJudgmentList = response.data.rows; |
| | | this.total = response.data.total; |
| | | } else { |
| | | this.$message.error("获取数据失败"); |
| | | } |
| | | this.loading = false; |
| | | }) |
| | | .catch(error => { |
| | | console.error("获取死亡判定列表失败:", error); |
| | | this.loading = false; |
| | | this.$message.error("获取数据失败"); |
| | | }); |
| | | |
| | | // 记录状态过滤器 |
| | | statusFilter(status) { |
| | | const statusMap = { |
| | | "0": "warning", // 维护中 |
| | | "1": "success", // 已完成 |
| | | "99": "danger" // 已终止 |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }, |
| | | |
| | | statusTextFilter(status) { |
| | | const statusMap = { |
| | | "0": "维护中", |
| | | "1": "已完成", |
| | | "99": "已终止" |
| | | }; |
| | | return statusMap[status] || "未知状态"; |
| | | }, |
| | | |
| | | // 查询死亡判定列表 |
| | | async getList() { |
| | | this.loading = true; |
| | | try { |
| | | const response = await queryDathInfoBaseInfo(this.queryParams); |
| | | |
| | | // 根据实际接口返回结构调整 |
| | | let realData = []; |
| | | realData = response.data; |
| | | this.total = response.total; |
| | | // if (Array.isArray(response)) { |
| | | // realData = response; |
| | | // } else if (response && response.data) { |
| | | // realData = response.data; |
| | | // } else if (response && response.rows) { |
| | | // realData = response.rows; |
| | | // this.total = response.total || response.rows.length; |
| | | // } else if (response && response.code === 200) { |
| | | // realData = response.data.rows || response.data; |
| | | // this.total = response.data.total || realData.length; |
| | | // } else { |
| | | // realData = []; |
| | | // } |
| | | |
| | | // 存储所有数据用于前端筛选 |
| | | this.allTableData = realData; |
| | | |
| | | // 应用前端筛选条件 |
| | | let filteredData = this.applyFrontendFilter(realData); |
| | | |
| | | // 前端分页处理(如果接口不支持后端分页) |
| | | if (!response.total && !response.data) { |
| | | const startIndex = |
| | | (this.queryParams.pageNum - 1) * this.queryParams.pageSize; |
| | | const endIndex = startIndex + this.queryParams.pageSize; |
| | | this.deathJudgmentList = filteredData.slice(startIndex, endIndex); |
| | | this.total = filteredData.length; |
| | | } else { |
| | | // 接口已分页,直接使用返回数据 |
| | | this.deathJudgmentList = filteredData; |
| | | } |
| | | } catch (error) { |
| | | console.error("获取死亡判定数据失败:", error); |
| | | this.$message.error("数据加载失败"); |
| | | this.deathJudgmentList = []; |
| | | this.total = 0; |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // 应用前端筛选 |
| | | applyFrontendFilter(data) { |
| | | let filteredData = data; |
| | | |
| | | // 住院号筛选 |
| | | if (this.queryParams.inpatientno) { |
| | | filteredData = filteredData.filter( |
| | | item => |
| | | item.inpatientno && |
| | | item.inpatientno.includes(this.queryParams.inpatientno) |
| | | ); |
| | | } |
| | | |
| | | // 姓名筛选 |
| | | if (this.queryParams.name) { |
| | | filteredData = filteredData.filter( |
| | | item => item.name && item.name.includes(this.queryParams.name) |
| | | ); |
| | | } |
| | | |
| | | // 死亡原因筛选 |
| | | if (this.queryParams.deathreason) { |
| | | filteredData = filteredData.filter( |
| | | item => item.deathreason === this.queryParams.deathreason |
| | | ); |
| | | } |
| | | |
| | | // 死亡时间范围筛选 |
| | | if ( |
| | | this.queryParams.deathTimeRange && |
| | | this.queryParams.deathTimeRange.length === 2 |
| | | ) { |
| | | const [startDate, endDate] = this.queryParams.deathTimeRange; |
| | | filteredData = filteredData.filter(item => { |
| | | if (!item.deathtime) return false; |
| | | const deathTime = new Date(item.deathtime).getTime(); |
| | | const startTime = new Date(startDate).getTime(); |
| | | const endTime = new Date(endDate + " 23:59:59").getTime(); |
| | | return deathTime >= startTime && deathTime <= endTime; |
| | | }); |
| | | } |
| | | |
| | | return filteredData; |
| | | }, |
| | | |
| | | // 搜索按钮操作 |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // 重置按钮操作 |
| | | resetQuery() { |
| | | this.$refs.queryForm.resetFields(); |
| | | this.handleQuery(); |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // 多选框选中数据 |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map(item => item.id); |
| | | this.single = selection.length !== 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | |
| | | // 查看详情 |
| | | handleView(row) { |
| | | this.$router.push({ |
| | |
| | | query: { id: row.id } |
| | | }); |
| | | }, |
| | | |
| | | // 新增按钮操作 |
| | | handleCreate() { |
| | | this.$router.push("/case/DecideInfo"); |
| | | }, |
| | | |
| | | // 修改按钮操作 |
| | | handleUpdate(row) { |
| | | const id = row.id || this.ids[0]; |
| | |
| | | query: { id: id } |
| | | }); |
| | | }, |
| | | // 删除按钮操作 |
| | | handleDelete(row) { |
| | | const ids = row.id ? [row.id] : this.ids; |
| | | this.$confirm("是否确认删除选中的数据项?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning" |
| | | }) |
| | | .then(() => { |
| | | return delDeathJudgment(ids); |
| | | }) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("删除成功"); |
| | | this.getList(); |
| | | } |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // 导出按钮操作 |
| | | |
| | | // 导出按钮操作(模拟调用) |
| | | handleExport() { |
| | | const queryParams = this.queryParams; |
| | | this.$confirm("是否确认导出所有死亡判定数据?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | |
| | | }) |
| | | .then(() => { |
| | | this.loading = true; |
| | | return exportDeathJudgment(queryParams); |
| | | // 模拟导出操作 |
| | | return new Promise(resolve => { |
| | | setTimeout(() => { |
| | | resolve({ code: 200 }); |
| | | }, 1000); |
| | | }); |
| | | }) |
| | | .then(response => { |
| | | if (response.code === 200) { |
| | | this.$message.success("导出成功"); |
| | | // 实际项目中这里处理文件下载 |
| | | // 可以添加以下代码来触发文件下载 |
| | | // this.downloadFile(); |
| | | } |
| | | this.loading = false; |
| | | }) |
| | |
| | | this.loading = false; |
| | | }); |
| | | }, |
| | | |
| | | // 文件下载方法(预留) |
| | | downloadFile() { |
| | | // 实际项目中的文件下载逻辑 |
| | | const link = document.createElement("a"); |
| | | link.style.display = "none"; |
| | | link.href = "/api/export/death-judgment"; // 替换为实际导出接口 |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | }, |
| | | |
| | | // 时间格式化 |
| | | parseTime(time, pattern) { |
| | | if (!time) return ""; |
| | |
| | | .fixed-width .el-button { |
| | | margin: 0 5px; |
| | | } |
| | | |
| | | /* 表格样式优化 */ |
| | | ::v-deep .el-table .cell { |
| | | padding: 8px 4px; |
| | | } |
| | | |
| | | ::v-deep .el-table th { |
| | | background-color: #f5f7fa; |
| | | font-weight: bold; |
| | | } |
| | | </style> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="180" align="center" fixed="right"> |
| | | <el-table-column label="操作" width="280" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | |
| | | <span>{{ formatDateTime(scope.row.createTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="180"> |
| | | <el-table-column label="操作" width="266"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | |
| | | v-loading="loading" |
| | | :data="donatebaseinfoList" |
| | | border |
| | | :default-sort="{ prop: 'donatetime', order: 'descending' }" |
| | | :default-sort="{ prop: 'reporttime', order: 'descending' }" |
| | | style="width: 100%; margin-top: 20px;" |
| | | > |
| | | <el-table-column |
| | | label="上报时间" |
| | | align="center" |
| | | prop="donatetime" |
| | | prop="reporttime" |
| | | width="110" |
| | | fixed="left" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.donatetime, "{y}-{m}-{d}") }}</span> |
| | | <span>{{ parseTime(scope.row.reporttime, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="进度" |
| | | label="捐献状态" |
| | | align="center" |
| | | prop="coreteamassessconclusion" |
| | | prop="recordstate" |
| | | width="100" |
| | | fixed="left" |
| | | > |
| | |
| | | |
| | | <el-table-column label="性别" align="center" prop="sex" width="80"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.sex === 1 ? "男" : "女" }}</span> |
| | | <span>{{ scope.row.sex === "1" ? "男" : "女" }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="治疗医院" |
| | | align="center" |
| | | prop="treatmenthospitalname" |
| | | width="150" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="协调员" |
| | | align="center" |
| | | prop="reportername" |
| | | prop="coordinatorName" |
| | | width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="转为案例时间" |
| | | label="案例编号" |
| | | align="center" |
| | | prop="donatetime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.donatetime, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | prop="caseNo" |
| | | width="120" |
| | | /> |
| | | |
| | | <!-- 第一次医学评估 --> |
| | | <el-table-column |
| | | label="第一次评估结论" |
| | | align="center" |
| | | prop="coreteamassessconclusion" |
| | | prop="firstAssessState" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BaseAssessConclusion" |
| | | :value="scope.row.coreteamassessconclusion" |
| | | :value="scope.row.firstAssessState" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column |
| | | label="第一次评估时间" |
| | | align="center" |
| | | prop="coreteamassesstime" |
| | | prop="assessFirstTime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | parseTime(scope.row.coreteamassesstime, "{y}-{m}-{d}") |
| | | }}</span> |
| | | <span>{{ parseTime(scope.row.assessFirstTime, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | |
| | | <el-table-column |
| | | label="第二次评估结论" |
| | | align="center" |
| | | prop="coreteamassessconclusion" |
| | | prop="secondAssessState" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_BaseAssessConclusion" |
| | | :value="scope.row.coreteamassessconclusion" |
| | | :value="scope.row.secondAssessState" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column |
| | | label="第二次评估时间" |
| | | align="center" |
| | | prop="coreteamassesstime" |
| | | prop="assessSecondTime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | parseTime(scope.row.coreteamassesstime, "{y}-{m}-{d}") |
| | | parseTime(scope.row.assessSecondTime, "{y}-{m}-{d}") |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column |
| | | label="亲属确认时间" |
| | | align="center" |
| | | prop="signdate" |
| | | prop="signDate" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.signdate, "{y}-{m}-{d}") }}</span> |
| | | <span>{{ parseTime(scope.row.signDate, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="伦理审查结论" |
| | | align="center" |
| | | prop="expertconclusion" |
| | | prop="expertConclusion" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_EthicalReview" |
| | | :value="scope.row.expertconclusion" |
| | | :value="scope.row.expertConclusion" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column |
| | | label="伦理审查时间" |
| | | align="center" |
| | | prop="conclusiontime" |
| | | prop="expertTime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.conclusiontime, "{y}-{m}-{d}") }}</span> |
| | | <span>{{ parseTime(scope.row.expertTime, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="器官分配数量" |
| | | align="center" |
| | | prop="organcount" |
| | | prop="organCount" |
| | | width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="获取见证时间" |
| | | align="center" |
| | | prop="operationbegtime" |
| | | prop="operationBegTime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ |
| | | parseTime(scope.row.operationbegtime, "{y}-{m}-{d}") |
| | | parseTime(scope.row.operationBegTime, "{y}-{m}-{d}") |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <el-table-column |
| | | label="完成登记时间" |
| | | align="center" |
| | | prop="completetime" |
| | | prop="completeTime" |
| | | width="110" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.completetime, "{y}-{m}-{d}") }}</span> |
| | | <span>{{ parseTime(scope.row.completeTime, "{y}-{m}-{d}") }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- 捐献进度列 --> |
| | | <el-table-column |
| | | label="捐献进度" |
| | | align="center" |
| | | prop="workflow" |
| | | prop="recordstate" |
| | | width="120" |
| | | fixed="right" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <div v-if="!scope.row.terminationCase"> |
| | | <div v-if="scope.row.terminationCase == 0"> |
| | | <dict-tag |
| | | :options="dict.type.sys_donornode" |
| | | :value="scope.row.workflow" |
| | | :value="scope.row.recordstate" |
| | | /> |
| | | </div> |
| | | <div v-else> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- <el-table-column label="操作" align="center" width="120" fixed="right"> |
| | | <!-- 操作列:只保留终止和查看详情 --> |
| | | <el-table-column label="操作" align="center" width="150" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" type="text" @click="handleDetail(scope.row)" |
| | | >查看详情</el-button |
| | | > |
| | | <el-button |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-view" |
| | | @click="handleDetail(scope.row)" |
| | | >详情</el-button> |
| | | <el-button |
| | | v-if="scope.row.recordstate == 0" |
| | | size="mini" |
| | | type="text" |
| | | icon="el-icon-check" |
| | | @click="handleApprove(scope.row)" |
| | | >审核</el-button> |
| | | style="color: #f56c6c;" |
| | | @click="handleTerminate(scope.row)" |
| | | v-if=" |
| | | scope.row.terminationCase === 0 && scope.row.recordstate !== '99' |
| | | " |
| | | >终止</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | |
| | | |
| | | <!-- 详情弹框 --> |
| | | <el-dialog |
| | | :title="`捐献者详情 - ${currentRecord.name}`" |
| | | :title="`捐献者详情 - ${currentRecord.name || ''}`" |
| | | :visible.sync="detailVisible" |
| | | width="1000px" |
| | | append-to-body |
| | |
| | | <donor-detail :donorData="currentRecord" @close="detailVisible = false" /> |
| | | </el-dialog> |
| | | |
| | | <!-- 审核弹框 --> |
| | | <!-- 终止确认弹框 --> |
| | | <el-dialog |
| | | title="捐献者审核" |
| | | :visible.sync="approveVisible" |
| | | width="500px" |
| | | title="终止确认" |
| | | :visible.sync="terminateVisible" |
| | | width="400px" |
| | | append-to-body |
| | | > |
| | | <el-form ref="approveForm" :model="approveForm" label-width="100px"> |
| | | <el-form-item label="审核结果"> |
| | | <el-radio-group v-model="approveForm.approveResult"> |
| | | <el-radio label="1">通过</el-radio> |
| | | <el-radio label="2">驳回</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="审核意见"> |
| | | <el-input |
| | | type="textarea" |
| | | v-model="approveForm.approveOpinion" |
| | | placeholder="请输入审核意见" |
| | | :rows="4" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div style="margin-bottom: 20px;"> |
| | | <p> |
| | | 确定要终止捐献者 |
| | | <strong>{{ currentRecord.name }}</strong> 的捐献进程吗? |
| | | </p> |
| | | <p style="color: #f56c6c; font-size: 12px;"> |
| | | 此操作不可逆,请谨慎操作! |
| | | </p> |
| | | </div> |
| | | <div slot="footer"> |
| | | <el-button @click="approveVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="submitApprove">确定</el-button> |
| | | <el-button @click="terminateVisible = false">取消</el-button> |
| | | <el-button type="danger" @click="submitTerminate">确认终止</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | // 导入模拟数据生成工具 |
| | | import Mock from "mockjs"; |
| | | import { courselist } from "@/api/businessApi"; |
| | | import { courselist, terminateDonor } from "@/api/businessApi"; |
| | | |
| | | export default { |
| | | name: "Donatebaseinfo", |
| | |
| | | donatebaseinfoList: [], |
| | | // 详情弹框显示 |
| | | detailVisible: false, |
| | | // 审核弹框显示 |
| | | approveVisible: false, |
| | | // 终止确认弹框显示 |
| | | terminateVisible: false, |
| | | // 当前操作记录 |
| | | currentRecord: {}, |
| | | // 统计数据 |
| | |
| | | name: undefined, |
| | | idcardno: undefined, |
| | | recordstate: undefined |
| | | }, |
| | | // 审核表单 |
| | | approveForm: { |
| | | approveResult: "1", |
| | | approveOpinion: "" |
| | | } |
| | | }; |
| | | }, |
| | |
| | | this.getList(); |
| | | }, |
| | | methods: { |
| | | /** 生成模拟数据 */ |
| | | generateMockData() { |
| | | const mockTemplate = { |
| | | "list|15-30": [ |
| | | { |
| | | "id|+1": 1001, |
| | | name: "@cname", |
| | | "sex|1": [1, 2], // 1:男, 2:女 |
| | | "age|18-65": 1, |
| | | idcardno: /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/, |
| | | reportername: "@cname", |
| | | treatmenthospitalname: "@ctitle(3, 5)医院", |
| | | donatetime: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | "coreteamassessconclusion|1": ["1", "2", "3"], // 评估结论 |
| | | coreteamassesstime: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | signdate: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | "expertconclusion|1": ["1", "2", "3"], // 伦理审查结论 |
| | | conclusiontime: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | "organcount|0-5": 1, |
| | | operationbegtime: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | completetime: '@datetime("yyyy-MM-dd HH:mm:ss")', |
| | | "workflow|1": ["1", "2", "3", "4", "5"], // 工作流状态 |
| | | "recordstate|1": ["0", "1", "99"], // 0:待审核, 1:已审核, 99:已终止 |
| | | "terminationCase|1": [true, false] |
| | | } |
| | | ] |
| | | }; |
| | | |
| | | return Mock.mock(mockTemplate).list; |
| | | }, |
| | | |
| | | /** 查询捐献基础列表 */ |
| | | async getList() { |
| | | this.loading = true; |
| | | const response = await courselist(this.queryParams); |
| | | // 模拟API调用延迟 |
| | | setTimeout(() => { |
| | | // 生成模拟数据 |
| | | const mockData = this.generateMockData(); |
| | | try { |
| | | const response = await courselist(this.queryParams); |
| | | |
| | | // 应用筛选条件 |
| | | let filteredData = mockData; |
| | | if (this.queryParams.name) { |
| | | filteredData = filteredData.filter(item => |
| | | item.name.includes(this.queryParams.name) |
| | | ); |
| | | } |
| | | if (this.queryParams.idcardno) { |
| | | filteredData = filteredData.filter(item => |
| | | item.idcardno.includes(this.queryParams.idcardno) |
| | | ); |
| | | } |
| | | if (this.queryParams.recordstate) { |
| | | filteredData = filteredData.filter( |
| | | item => item.recordstate === this.queryParams.recordstate |
| | | ); |
| | | } |
| | | // 根据实际接口返回结构调整 |
| | | let realData = []; |
| | | realData = response.data.donatebaseinfoProgressDTOS; |
| | | this.total = response.total; |
| | | this.stats.pendingCount = response.data.terminationCase[0]; |
| | | this.stats.approvedCount = response.data.terminationCase[1]; |
| | | this.stats.terminatedCount = response.data.terminationCase[2]; |
| | | this.stats.totalCount = response.total; |
| | | // 存储所有数据用于前端筛选和分页 |
| | | this.allTableData = realData; |
| | | |
| | | // 分页处理 |
| | | const startIndex = |
| | | (this.queryParams.pageNum - 1) * this.queryParams.pageSize; |
| | | const endIndex = startIndex + this.queryParams.pageSize; |
| | | this.donatebaseinfoList = filteredData.slice(startIndex, endIndex); |
| | | this.total = filteredData.length; |
| | | // 应用前端筛选条件(如果接口不支持后端筛选) |
| | | let filteredData = this.applyFrontendFilter(realData); |
| | | |
| | | // 前端分页处理(如果接口不支持后端分页) |
| | | if (!response.total && !response.data) { |
| | | const startIndex = |
| | | (this.queryParams.pageNum - 1) * this.queryParams.pageSize; |
| | | const endIndex = startIndex + this.queryParams.pageSize; |
| | | this.donatebaseinfoList = filteredData.slice(startIndex, endIndex); |
| | | this.total = filteredData.length; |
| | | } else { |
| | | // 接口已分页,直接使用返回数据 |
| | | this.donatebaseinfoList = filteredData; |
| | | } |
| | | |
| | | // 更新统计数据 |
| | | this.updateStats(mockData); |
| | | // this.updateStats(realData); |
| | | } catch (error) { |
| | | console.error("获取数据失败:", error); |
| | | this.$message.error("数据加载失败"); |
| | | this.donatebaseinfoList = []; |
| | | this.total = 0; |
| | | // this.updateStats([]); |
| | | } finally { |
| | | this.loading = false; |
| | | }, 500); |
| | | } |
| | | }, |
| | | |
| | | /** 应用前端筛选 */ |
| | | applyFrontendFilter(data) { |
| | | let filteredData = data; |
| | | |
| | | if (this.queryParams.name) { |
| | | filteredData = filteredData.filter( |
| | | item => item.name && item.name.includes(this.queryParams.name) |
| | | ); |
| | | } |
| | | |
| | | if (this.queryParams.idcardno) { |
| | | filteredData = filteredData.filter( |
| | | item => |
| | | item.idcardno && item.idcardno.includes(this.queryParams.idcardno) |
| | | ); |
| | | } |
| | | |
| | | if (this.queryParams.recordstate) { |
| | | filteredData = filteredData.filter( |
| | | item => item.recordstate === this.queryParams.recordstate |
| | | ); |
| | | } |
| | | |
| | | return filteredData; |
| | | }, |
| | | |
| | | /** 更新统计数据 */ |
| | | updateStats(data) { |
| | | this.stats.totalCount = data.length; |
| | | this.stats.pendingCount = data.filter( |
| | | item => item.recordstate === "0" |
| | | item => item.recordstate === "0" || item.recordstate === 0 |
| | | ).length; |
| | | this.stats.approvedCount = data.filter( |
| | | item => item.recordstate === "1" |
| | | item => item.recordstate === "1" || item.recordstate === 1 |
| | | ).length; |
| | | this.stats.terminatedCount = data.filter( |
| | | item => item.recordstate === "99" |
| | | item => item.recordstate === "99" || item.recordstate === 99 |
| | | ).length; |
| | | }, |
| | | |
| | | /** 获取状态标签样式 */ |
| | | getStatusTag(status) { |
| | | const statusMap = { |
| | | "0": "warning", // 待审核 |
| | | "1": "success", // 已审核 |
| | | "0": "warning", // 维护中 |
| | | "1": "success", // 已完成 |
| | | "99": "danger" // 已终止 |
| | | }; |
| | | return statusMap[status] || "info"; |
| | |
| | | /** 时间格式化 */ |
| | | parseTime(time, format) { |
| | | if (!time) return "-"; |
| | | |
| | | // 处理时间戳和日期字符串 |
| | | const date = new Date(time); |
| | | if (isNaN(date.getTime())) return time; |
| | | |
| | | const year = date.getFullYear(); |
| | | const month = (date.getMonth() + 1).toString().padStart(2, "0"); |
| | | const day = date |
| | |
| | | |
| | | /** 重置按钮操作 */ |
| | | resetQuery() { |
| | | this.queryParams = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | name: undefined, |
| | | idcardno: undefined, |
| | | recordstate: undefined |
| | | }; |
| | | this.$refs.queryForm.resetFields(); |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | |
| | | this.detailVisible = true; |
| | | }, |
| | | |
| | | /** 审核操作 */ |
| | | handleApprove(row) { |
| | | /** 终止操作 */ |
| | | handleTerminate(row) { |
| | | this.currentRecord = { ...row }; |
| | | this.approveForm = { |
| | | approveResult: "1", |
| | | approveOpinion: "" |
| | | }; |
| | | this.approveVisible = true; |
| | | this.terminateVisible = true; |
| | | }, |
| | | |
| | | /** 提交审核 */ |
| | | submitApprove() { |
| | | // 模拟审核提交 |
| | | const index = this.donatebaseinfoList.findIndex( |
| | | item => item.id === this.currentRecord.id |
| | | ); |
| | | if (index !== -1) { |
| | | this.donatebaseinfoList[ |
| | | index |
| | | ].recordstate = this.approveForm.approveResult; |
| | | this.$message.success("审核成功"); |
| | | this.approveVisible = false; |
| | | this.getList(); // 重新加载更新统计 |
| | | /** 提交终止 */ |
| | | async submitTerminate() { |
| | | try { |
| | | // 调用终止接口 |
| | | await terminateDonor({ |
| | | id: this.currentRecord.id, |
| | | caseNo: this.currentRecord.caseNo, |
| | | terminationReason: "管理员手动终止" |
| | | }); |
| | | |
| | | this.$message.success("终止成功"); |
| | | this.terminateVisible = false; |
| | | this.getList(); // 重新加载更新数据 |
| | | } catch (error) { |
| | | this.$message.error("终止失败"); |
| | | console.error("终止错误:", error); |
| | | } |
| | | } |
| | | } |
| | |
| | | background-color: #f5f7fa; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | /* 操作按钮样式 */ |
| | | ::v-deep .el-button--text { |
| | | padding: 4px 8px; |
| | | } |
| | | </style> |