From c4599aa279fd2f90b741608392e056fbae2282d5 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期四, 20 八月 2026 17:16:54 +0800
Subject: [PATCH] 各表单布局调整
---
src/views/business/course/components/OrganUtilizationStage.vue | 1929 ++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 1,198 insertions(+), 731 deletions(-)
diff --git a/src/views/business/course/components/OrganUtilizationStage.vue b/src/views/business/course/components/OrganUtilizationStage.vue
index aa76231..a3e8163 100644
--- a/src/views/business/course/components/OrganUtilizationStage.vue
+++ b/src/views/business/course/components/OrganUtilizationStage.vue
@@ -1,812 +1,1279 @@
<template>
- <base-stage :stage-data="stageData" :case-info="caseInfo">
- <!-- 澶撮儴璀﹀憡淇℃伅 -->
- <template #header>
- <el-alert
- :title="`鍣ㄥ畼鍒╃敤 - ${getStatusText()}`"
- :type="getAlertType()"
- :description="getAlertDescription()"
- show-icon
- :closable="false"
- />
- </template>
+ <div class="organ-procurement-detail">
+ <!-- <case-basic-info :case-id="caseId" :show-attachment="true":column="3" /> -->
- <!-- 缁熻姒傝琛� -->
- <el-row :gutter="20" style="margin-top: 20px;">
- <el-col :span="6">
- <el-card>
- <div slot="header" class="card-header">
- <span>鍒╃敤姒傚喌</span>
- </div>
- <div class="utilization-overview">
- <div class="overview-item">
- <div class="overview-icon" style="color: #67C23A;">
- <i class="el-icon-success"></i>
- </div>
- <div class="overview-content">
- <div class="value">{{ utilizationStats.transplanted }}</div>
- <div class="label">宸茬Щ妞嶅櫒瀹�</div>
- </div>
- </div>
- <div class="overview-item">
- <div class="overview-icon" style="color: #E6A23C;">
- <i class="el-icon-time"></i>
- </div>
- <div class="overview-content">
- <div class="value">{{ utilizationStats.inProgress }}</div>
- <div class="label">绉绘涓�</div>
- </div>
- </div>
- <div class="overview-item">
- <div class="overview-icon" style="color: #F56C6C;">
- <i class="el-icon-warning"></i>
- </div>
- <div class="overview-content">
- <div class="value">{{ utilizationStats.failed }}</div>
- <div class="label">绉绘澶辫触</div>
- </div>
- </div>
- </div>
- </el-card>
- </el-col>
-
- <el-col :span="6">
- <el-card>
- <div slot="header" class="card-header">
- <span>鎴愬姛鐜囩粺璁�</span>
- </div>
- <div class="success-stats">
- <div class="success-item">
- <span class="label">绉绘鎴愬姛鐜�:</span>
- <el-progress
- :percentage="utilizationStats.successRate"
- :status="utilizationStats.successRate > 85 ? 'success' : 'warning'"
- />
- </div>
- <div class="success-item">
- <span class="label">鍣ㄥ畼鍒╃敤鐜�:</span>
- <el-progress
- :percentage="utilizationStats.utilizationRate"
- status="success"
- />
- </div>
- <div class="success-item">
- <span class="label">鎮h�呭瓨娲荤巼:</span>
- <el-progress
- :percentage="utilizationStats.survivalRate"
- status="success"
- />
- </div>
- </div>
- </el-card>
- </el-col>
-
- <el-col :span="6">
- <el-card>
- <div slot="header" class="card-header">
- <span>鏃堕棿璺熻釜</span>
- </div>
- <div class="time-tracking">
- <div class="time-item">
- <span class="label">鑾峰彇鍒扮Щ妞�:</span>
- <span class="value">{{ timeTracking.procurementToTransplant }}</span>
- </div>
- <div class="time-item">
- <span class="label">鍐风己琛�鏃堕棿:</span>
- <span class="value">{{ timeTracking.coldIschemiaTime }}</span>
- </div>
- <div class="time-item">
- <span class="label">鎵嬫湳鏃堕暱:</span>
- <span class="value">{{ timeTracking.surgeryDuration }}</span>
- </div>
- <div class="time-item">
- <span class="label">ICU鍋滅暀:</span>
- <span class="value">{{ timeTracking.icuStay }}</span>
- </div>
- </div>
- </el-card>
- </el-col>
-
- <el-col :span="6">
- <el-card>
- <div slot="header" class="card-header">
- <span>璐ㄩ噺璇勪及</span>
- </div>
- <div class="quality-assessment">
- <div class="quality-item">
- <span class="label">鍣ㄥ畼璐ㄩ噺璇勫垎:</span>
- <el-rate
- v-model="qualityStats.organQuality"
- disabled
- show-score
- text-color="#ff9900"
- score-template="{value}"
- />
- </div>
- <div class="quality-item">
- <span class="label">鎵嬫湳璐ㄩ噺:</span>
- <el-rate
- v-model="qualityStats.surgeryQuality"
- disabled
- show-score
- text-color="#ff9900"
- score-template="{value}"
- />
- </div>
- <div class="quality-item">
- <span class="label">闅忚瀹屾垚鐜�:</span>
- <el-progress
- :percentage="qualityStats.followupCompletionRate"
- status="success"
- />
- </div>
- </div>
- </el-card>
- </el-col>
- </el-row>
-
- <!-- 鏁版嵁鍙鍖栭儴鍒� -->
- <el-row :gutter="20" style="margin-top: 20px;">
- <!-- 鍣ㄥ畼鍒╃敤鍒嗗竷鍥� -->
- <el-col :span="12">
- <el-card>
- <div slot="header" class="card-header">
- <span>鍣ㄥ畼鍒╃敤鍒嗗竷</span>
- <el-radio-group v-model="chartView" size="small" @change="updateCharts">
- <el-radio-button label="bar">鏌辩姸鍥�</el-radio-button>
- <el-radio-button label="pie">楗煎浘</el-radio-button>
- </el-radio-group>
- </div>
- <div class="chart-container">
- <div ref="organDistributionChart" style="width: 100%; height: 300px;"></div>
- </div>
- </el-card>
- </el-col>
-
- <!-- 鎴愬姛鐜囪秼鍔垮浘 -->
- <el-col :span="12">
- <el-card>
- <div slot="header" class="card-header">
- <span>绉绘鎴愬姛鐜囪秼鍔�</span>
- </div>
- <div class="chart-container">
- <div ref="successTrendChart" style="width: 100%; height: 300px;"></div>
- </div>
- </el-card>
- </el-col>
- </el-row>
-
- <el-row :gutter="20" style="margin-top: 20px;">
- <!-- 闅忚鏁版嵁缁熻 -->
- <el-col :span="12">
- <el-card>
- <div slot="header" class="card-header">
- <span>闅忚鏁版嵁缁熻</span>
- </div>
- <div class="chart-container">
- <div ref="followupStatsChart" style="width: 100%; height: 300px;"></div>
- </div>
- </el-card>
- </el-col>
-
- <!-- 骞跺彂鐥囧垎鏋� -->
- <el-col :span="12">
- <el-card>
- <div slot="header" class="card-header">
- <span>骞跺彂鐥囧垎鏋�</span>
- </div>
- <div class="chart-container">
- <div ref="complicationChart" style="width: 100%; height: 300px;"></div>
- </div>
- </el-card>
- </el-col>
- </el-row>
-
- <!-- 璇︾粏鏁版嵁琛ㄦ牸 -->
- <el-card style="margin-top: 20px;">
- <div slot="header" class="card-header">
- <span>鍣ㄥ畼鍒╃敤璇︽儏</span>
- <el-button type="primary" size="small" @click="exportData">
- 瀵煎嚭鏁版嵁
- </el-button>
+ <!-- 鍩烘湰淇℃伅 -->
+ <el-card class="detail-card">
+ <div slot="header" class="clearfix">
+ <span class="detail-title">鍣ㄥ畼鑾峰彇鍩烘湰淇℃伅</span>
</div>
- <el-table :data="organUtilizationData" v-loading="loading" border>
- <el-table-column label="鍣ㄥ畼鍚嶇О" prop="organName" width="120" align="center" />
- <el-table-column label="绉绘鐘舵��" width="100" align="center">
- <template slot-scope="scope">
- <el-tag :type="getTransplantStatusTag(scope.row.status)">
- {{ scope.row.status }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="鍙椾綋淇℃伅" width="150">
- <template slot-scope="scope">
- <div>{{ scope.row.recipientName }}</div>
- <div style="font-size: 12px; color: #909399;">{{ scope.row.recipientAge }}宀�/{{ scope.row.recipientGender }}</div>
- </template>
- </el-table-column>
- <el-table-column label="绉绘鍖婚櫌" prop="hospital" min-width="180" />
- <el-table-column label="绉绘鏃堕棿" width="160" align="center">
- <template slot-scope="scope">
- {{ formatTime(scope.row.transplantTime) }}
- </template>
- </el-table-column>
- <el-table-column label="闅忚娆℃暟" width="100" align="center">
- <template slot-scope="scope">
- <el-tag :type="scope.row.followupCount > 0 ? 'success' : 'info'">
- {{ scope.row.followupCount }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="褰撳墠鐘舵��" width="120" align="center">
- <template slot-scope="scope">
- <el-tag :type="getRecipientStatusTag(scope.row.recipientStatus)">
- {{ scope.row.recipientStatus }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="鎿嶄綔" width="150" align="center">
- <template slot-scope="scope">
- <el-button type="text" size="small" @click="handleViewDetails(scope.row)">
- 鏌ョ湅璇︽儏
- </el-button>
- <el-button type="text" size="small" @click="handleAddFollowup(scope.row)">
- 娣诲姞闅忚
- </el-button>
- </template>
- </el-table-column>
- </el-table>
+ <el-descriptions title="鎵嬫湳淇℃伅" :column="descriptionColumn" border size="small">
+ <el-descriptions-item label="鎵嬫湳鍖荤敓">{{ form.operationdoctor || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鎵嬫湳寮�濮嬫椂闂�">{{ form.operationbegtime || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鎵嬫湳缁撴潫鏃堕棿">{{ form.operationendtime || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鑵逛富鍔ㄨ剦鎻掔鏃堕棿">{{ form.abdominalaortacannulatime || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鑵逛富鍔ㄨ剦鐏屾敞鏃堕棿">{{ form.abdominalaortaperfusiontime || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="闂ㄩ潤鑴夋彃绠℃椂闂�">{{ form.portalveincannulatime || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="闂ㄩ潤鑴夌亴娉ㄦ椂闂�">{{ form.portalveinperfusiontime || '-' }}</el-descriptions-item>
+ </el-descriptions>
+
+ <el-descriptions title="鍗忚皟鍛樹俊鎭�" :column="descriptionColumn" border size="small">
+ <el-descriptions-item label="杩涙墜鏈鏃堕棿">{{ form.coordinatorInOperating || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍑烘墜鏈鏃堕棿">{{ form.coordinatorOutOperating || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鏄惁榛樺搥缂呮��">{{ form.isspendremember === 1 ? '鏄�' : form.isspendremember === 0 ? '鍚�' : '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鎭㈠閬椾綋浠">{{ form.isrestoreremains === 1 ? '鏄�' : form.isrestoreremains === 0 ? '鍚�' : '-' }}</el-descriptions-item>
+ </el-descriptions>
+
+ <el-descriptions title="璐熻矗浜轰俊鎭�" :column="descriptionColumn" border size="small">
+ <el-descriptions-item label="璐熻矗浜哄鍚�">{{ form.responsibleusername || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍗忚皟鍛樹竴">{{ form.coordinatedusernameo || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鍗忚皟鍛樹簩">{{ form.coordinatedusernamet || '-' }}</el-descriptions-item>
+ </el-descriptions>
+
+ <el-descriptions title="鑾峰彇鏈烘瀯淇℃伅" :column="descriptionColumn" border size="small">
+ <el-descriptions-item label="鑾峰彇鏈烘瀯鍚嶇О">{{ form.gainhospitalname || '-' }}</el-descriptions-item>
+ </el-descriptions>
</el-card>
- <!-- 琛屽姩鎸夐挳 -->
- <template #footer>
- <div class="action-buttons" style="margin-top: 20px; text-align: center;">
- <el-button type="primary" @click="handleGenerateReport">
- 鐢熸垚鍒╃敤鎶ュ憡
- </el-button>
- <el-button type="success" @click="handleCompleteUtilization">
- 瀹屾垚鍣ㄥ畼鍒╃敤
- </el-button>
- <el-button type="warning" @click="handleStatistics">
- 缁熻鏁版嵁鍒嗘瀽
- </el-button>
+ <!-- 鍣ㄥ畼鑾峰彇璁板綍閮ㄥ垎 -->
+ <el-card class="procurement-card">
+ <div slot="header" class="clearfix">
+ <span class="detail-title">鍣ㄥ畼鑾峰彇璁板綍</span>
+ <div style="float: right;">
+ <dict-tag
+ :options="dict.type.Obtain_status"
+ :value="form.witnessState"
+ />
+ </div>
</div>
- </template>
- </base-stage>
+
+ <el-descriptions title="鎹愮尞鍣ㄥ畼" :column="1" border size="small" style="margin-bottom: 16px;">
+ <el-descriptions-item label="鎹愮尞鍣ㄥ畼">
+ <template v-if="selectedOrgans && selectedOrgans.length">
+ <span v-for="(v, i) in selectedOrgans" :key="v">
+ {{ getOrganLabel(v) }}<span v-if="i < selectedOrgans.length - 1">銆�</span>
+ </span>
+ </template>
+ <template v-else>-</template>
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <el-table :data="displayOrgans" v-loading="loading" border style="width: 100%">
+ <el-table-column label="鍣ㄥ畼鍚嶇О" align="center" prop="organname" />
+ <el-table-column label="鑾峰彇寮�濮嬫椂闂�" align="center" prop="organStartTime" />
+ <el-table-column label="鍣ㄥ畼绂讳綋鏃堕棿" align="center" prop="organgettime" />
+ <el-table-column label="鑾峰彇鍖婚櫌" align="center" prop="gainhospitalname" show-overflow-tooltip />
+ <el-table-column label="鑾峰彇鍖诲笀" align="center" prop="organgetdoct" />
+ <el-table-column label="璇存槑" align="center" prop="notgetreason" min-width="200" show-overflow-tooltip />
+ </el-table>
+
+ <div v-if="!displayOrgans.length" class="empty-procurement">
+ <el-empty description="鏆傛棤鑾峰彇璁板綍" :image-size="80" />
+ </div>
+ </el-card>
+
+ <!-- 闄勪欢绠$悊閮ㄥ垎 - 鍒嗙被Tab灞曠ず -->
+ <el-card class="attachment-card">
+ <div slot="header" class="clearfix">
+ <span class="detail-title">鐩稿叧闄勪欢</span>
+ </div>
+
+ <!-- 闄勪欢鍒楄〃 - 鍒嗙被Tab灞曠ず -->
+ <el-tabs v-model="activeTab" type="border-card">
+ <el-tab-pane
+ v-for="category in categories"
+ :key="category"
+ :label="category + '(' + getCategoryCount(category) + ')'"
+ :name="category"
+ >
+ <el-table
+ :data="getCategoryFiles(category)"
+ style="width: 100%"
+ size="small"
+ border
+ >
+ <el-table-column label="鏂囦欢鍚�" min-width="180">
+ <template #default="scope">
+ <i
+ class="el-icon-document"
+ style="margin-right: 8px; color: #409EFF;"
+ ></i>
+ <span class="file-name">{{ scope.row.fileName }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒嗙被" width="150">
+ <template #default="scope">
+ <span>{{ scope.row.fileType || '鏈垎绫�' }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏂囦欢绫诲瀷" width="100">
+ <template #default="scope">
+ <el-tag size="small">{{
+ getFileTypeText(scope.row.fileName)
+ }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column label="涓婁紶鏃堕棿" width="160">
+ <template #default="scope">
+ <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鏂囦欢澶у皬" width="100">
+ <template #default="scope">
+ <span>{{ formatFileSize(scope.row.fileSize) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="100" fixed="right">
+ <template #default="scope">
+ <el-button
+ size="mini"
+ type="primary"
+ @click="handlePreview(scope.row)"
+ >棰勮</el-button
+ >
+ </template>
+ </el-table-column>
+ </el-table>
+ <div
+ v-if="getCategoryFiles(category).length === 0"
+ style="text-align:center; padding:20px; color:#909399;"
+ >
+ 鏆傛棤闄勪欢
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+ </el-card>
+ <!-- 鏂囦欢棰勮寮圭獥 -->
+ <FilePreviewDialog
+ :visible="previewVisible"
+ :file="currentPreviewFile"
+ @close="previewVisible = false"
+ @download="handleDownload"
+ />
+ </div>
</template>
<script>
-import BaseStage from './BaseStage.vue';
-import * as echarts from 'echarts';
+import { witnessList, witnessadd, witnessedit } from "@/api/businessApi";
+import FilePreviewDialog from "@/components/FilePreviewDialog";
+import CaseBasicInfo from "@/components/CaseBasicInfo";
+import { getToken } from "@/utils/auth";
+import dayjs from "dayjs";
+import readonlyDescriptionsMixin from "./readonlyDescriptionsMixin";
export default {
- name: 'OrganUtilizationStage',
- components: { BaseStage },
+ name: "OrganProcurementDetail",
+ components: {
+ FilePreviewDialog,
+ CaseBasicInfo
+ },
+ mixins: [readonlyDescriptionsMixin],
+ dicts: [
+ "sys_BloodType",
+ "Geta_hospital",
+ "sys_DonationCategory",
+ "sys_Organ",
+ "Obtain_status"
+ ],
props: {
- stageData: {
- type: Object,
- default: () => ({})
- },
- caseInfo: {
- type: Object,
- default: () => ({})
+ infoid: {
+ type: String,
+ default: true
}
},
data() {
return {
- chartView: 'bar',
+ caseId: null,
+ // 琛ㄥ崟鏁版嵁
+ form: {
+ id: undefined,
+ infoid: undefined,
+ name: "",
+ inpatientno: "",
+ witnessState: "2",
+ caseNo: "",
+ donorno: "",
+ treatmenthospitalname: "",
+ treatmenthospitalno: "",
+ sex: "",
+ age: "",
+ bloodtype: "",
+ idcardno: "",
+ diagnosisname: "",
+ coordinatorName: "",
+ gainhospitalno: "",
+ gainhospitalname: "",
+ deathtime: "",
+ deathreason: "",
+ deathjudgedocto: "",
+ deathjudgedoctt: "",
+ deathjudgeannex: "",
+ operationbegtime: "",
+ operationendtime: "",
+ operationdoctor: "",
+ isspendremember: 1,
+ isrestoreremains: 1,
+ rememberannex: "",
+ responsibleuserid: "",
+ responsibleusername: "",
+ coordinateduserido: "",
+ coordinatedusernameo: "",
+ coordinateduseridt: "",
+ coordinatedusernamet: "",
+ abdominalaortacannulatime: "",
+ abdominalaortaperfusiontime: "",
+ portalveincannulatime: "",
+ portalveinperfusiontime: "",
+ pulmonaryarterycannulatime: "",
+ pulmonaryarteryperfusiontime: "",
+ aortacannulatime: "",
+ aortaperfusiontime: "",
+ organdonation: "",
+ organdonationOther: "",
+ donationcategory: "",
+ coordinatorInOperating: "",
+ coordinatorOutOperating: "",
+ coordinatorSign: "",
+ coordinatorSignTime: "",
+ attachments: []
+ },
+ activeTab: "鍘熻〃鎷嶇収", // 褰撳墠婵�娲荤殑闄勪欢鍒嗙被Tab
+ presetCategories: [
+ "鍘熻〃鎷嶇収",
+ "浼︾悊瀹℃煡鏉愭枡",
+ "姝讳骸鍒ゅ畾鏉愭枡",
+ "榛樺搥浠紡鐓х墖",
+ "鎹愮尞瑙佽瘉瑙嗛"
+ ], // 棰勮鍒嗙被
+ organExpansionMap: {
+ C64: { subItems: ["C64L", "C64R"], subNames: ["宸﹁偩", "鍙宠偩"] },
+ C34: { subItems: ["C34L", "C34R"], subNames: ["宸﹁偤", "鍙宠偤"] }
+ },
+ // 琛ㄥ崟楠岃瘉瑙勫垯
+ rules: {
+ name: [
+ { required: true, message: "鎹愮尞鑰呭鍚嶄笉鑳戒负绌�", trigger: "blur" }
+ ],
+ diagnosisname: [
+ { required: true, message: "鐤剧梾璇婃柇涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ donationcategory: [
+ { required: true, message: "鎹愮尞绫诲埆涓嶈兘涓虹┖", trigger: "change" }
+ ],
+ operationdoctor: [
+ { required: true, message: "鎵嬫湳鍖荤敓涓嶈兘涓虹┖", trigger: "blur" }
+ ]
+ },
+ // 鑾峰彇璁板綍楠岃瘉瑙勫垯
+ procurementRules: {},
+ // 淇濆瓨鍔犺浇鐘舵��
+ saveLoading: false,
+ confirmLoading: false,
+ // 鍔犺浇鐘舵��
loading: false,
- utilizationStats: {
- transplanted: 3,
- inProgress: 0,
- failed: 0,
- successRate: 95,
- utilizationRate: 100,
- survivalRate: 92
+ // 閫変腑鐨勫櫒瀹�
+ selectedOrgans: [],
+ // 鍖婚櫌鍒楄〃
+ hospitalList: [],
+ // 鑾峰彇璁板綍鏁版嵁
+ procurementData: {
+ serviceDonationwitnessorgans: []
},
- timeTracking: {
- procurementToTransplant: '4.5灏忔椂',
- coldIschemiaTime: '鑲濊剰:6h,鑲捐剰:8h,蹇冭剰:3h',
- surgeryDuration: '鑲濊剰:4h,鑲捐剰:3h,蹇冭剰:5h',
- icuStay: '鑲濊剰:3澶�,鑲捐剰:2澶�,蹇冭剰:5澶�'
+ // 闄勪欢鏁版嵁
+ attachments: [],
+ // 涓婁紶鐩稿叧
+ uploadAction: process.env.VUE_APP_BASE_API + "/common/upload",
+ headers: {
+ Authorization: "Bearer " + getToken()
},
- qualityStats: {
- organQuality: 4.5,
- surgeryQuality: 4.8,
- followupCompletionRate: 85
- },
- organUtilizationData: [
- {
- organName: '鑲濊剰',
- status: '绉绘鎴愬姛',
- recipientName: '鐜嬪厛鐢�',
- recipientAge: 45,
- recipientGender: '鐢�',
- hospital: '鍖椾含鍗忓拰鍖婚櫌绉绘涓績',
- transplantTime: '2025-12-04 16:00:00',
- followupCount: 3,
- recipientStatus: '鎭㈠鑹ソ'
- },
- {
- organName: '鑲捐剰',
- status: '绉绘鎴愬姛',
- recipientName: '鏉庡コ澹�',
- recipientAge: 38,
- recipientGender: '濂�',
- hospital: '涓婃捣鐟為噾鍖婚櫌绉绘涓績',
- transplantTime: '2025-12-04 17:30:00',
- followupCount: 2,
- recipientStatus: '绋冲畾鎭㈠'
- },
- {
- organName: '蹇冭剰',
- status: '绉绘鎴愬姛',
- recipientName: '闄堝厛鐢�',
- recipientAge: 52,
- recipientGender: '鐢�',
- hospital: '骞垮窞涓北鍖婚櫌蹇冭剰涓績',
- transplantTime: '2025-12-04 18:15:00',
- followupCount: 1,
- recipientStatus: '瀵嗗垏瑙傚療'
- }
- ],
- // 鍥捐〃瀹炰緥
- organDistributionChart: null,
- successTrendChart: null,
- followupStatsChart: null,
- complicationChart: null
+ uploadDialogVisible: false,
+ uploadLoading: false,
+ tempFileList: [],
+ currentUploadCategory: "",
+ // 缂栬緫瀵硅瘽妗�
+ editDialogVisible: false,
+ currentRecord: {},
+ currentEditIndex: -1,
+ // 鏂囦欢棰勮鐩稿叧
+ previewVisible: false,
+ currentPreviewFile: null
};
},
- mounted() {
- this.$nextTick(() => {
- this.initCharts();
- });
+ computed: {
+ // 褰撳墠鐢ㄦ埛淇℃伅
+ currentUser() {
+ return JSON.parse(sessionStorage.getItem("user") || "{}");
+ },
+ displayOrgans() {
+ return (this.procurementData.serviceDonationwitnessorgans || []).filter(
+ item => item.delFlag !== 1
+ );
+ },
+ categories() {
+ // 濮嬬粓杩斿洖鎵�鏈夐璁惧垎绫� + 鏈垎绫伙紝鏃犺鏄惁鏈夋暟鎹�
+ return [
+ "鍘熻〃鎷嶇収",
+ "浼︾悊瀹℃煡鏉愭枡",
+ "姝讳骸鍒ゅ畾鏉愭枡",
+ "榛樺搥浠紡鐓х墖",
+ "鎹愮尞瑙佽瘉瑙嗛",
+ "鏈垎绫�"
+ ];
+ },
+ organReverseMap() {
+ const map = {};
+ for (const key in this.organExpansionMap) {
+ const { subItems } = this.organExpansionMap[key];
+ subItems.forEach(item => {
+ map[item] = key;
+ });
+ }
+ return map;
+ },
+ // 涓嶅畬鏁寸殑璁板綍鏁伴噺
+ incompleteRecords() {
+ if (!this.procurementData.serviceDonationwitnessorgans) return 0;
+ return this.procurementData.serviceDonationwitnessorgans.filter(
+ record =>
+ !record.organStartTime ||
+ !record.organgettime ||
+ !record.gainhospitalno ||
+ !record.organgetdoct
+ ).length;
+ },
+ // 鍞竴鍖婚櫌鏁伴噺
+ uniqueHospitals() {
+ if (!this.procurementData.serviceDonationwitnessorgans) return 0;
+ const hospitals = this.procurementData.serviceDonationwitnessorgans
+ .map(record => record.gainhospitalno)
+ .filter(Boolean);
+ return new Set(hospitals).size;
+ },
+ // 鑾峰彇鍣ㄥ畼瀛楀吀
+ organDict() {
+ return this.dict.type.sys_Organ || [];
+ }
},
- beforeDestroy() {
- // 閿�姣佸浘琛ㄥ疄渚�
- if (this.organDistributionChart) {
- this.organDistributionChart.dispose();
- }
- if (this.successTrendChart) {
- this.successTrendChart.dispose();
- }
- if (this.followupStatsChart) {
- this.followupStatsChart.dispose();
- }
- if (this.complicationChart) {
- this.complicationChart.dispose();
- }
+ created() {
+ this.caseId = this.infoid;
+
+ this.initData();
},
methods: {
- // 鍒濆鍖栧浘琛�
- initCharts() {
- this.initOrganDistributionChart();
- this.initSuccessTrendChart();
- this.initFollowupStatsChart();
- this.initComplicationChart();
+ // 鏍规嵁瀛楀吀value鑾峰彇label
+ getOrganLabel(organValue) {
+ const dictItem = this.organDict.find(item => item.value === organValue);
+ return dictItem ? dictItem.label : organValue;
},
- // 鍒濆鍖栧櫒瀹樺垎甯冨浘琛�
- initOrganDistributionChart() {
- this.organDistributionChart = echarts.init(this.$refs.organDistributionChart);
- const option = {
- tooltip: {
- trigger: 'item',
- formatter: '{a} <br/>{b}: {c} ({d}%)'
- },
- legend: {
- orient: 'vertical',
- right: 10,
- top: 'center',
- data: ['鑲濊剰', '鑲捐剰', '蹇冭剰', '鑲鸿剰', '瑙掕啘', '鍏朵粬']
- },
- series: [
- {
- name: '鍣ㄥ畼鍒╃敤',
- type: 'pie',
- radius: ['50%', '70%'],
- avoidLabelOverlap: false,
- label: {
- show: false,
- position: 'center'
- },
- emphasis: {
- label: {
- show: true,
- fontSize: '18',
- fontWeight: 'bold'
- }
- },
- labelLine: {
- show: false
- },
- data: [
- { value: 35, name: '鑲濊剰' },
- { value: 30, name: '鑲捐剰' },
- { value: 15, name: '蹇冭剰' },
- { value: 10, name: '鑲鸿剰' },
- { value: 8, name: '瑙掕啘' },
- { value: 2, name: '鍏朵粬' }
- ]
- }
- ]
- };
- this.organDistributionChart.setOption(option);
- },
+ // 鍒濆鍖栨暟鎹�
+ initData() {
+ const infoid = this.infoid;
- // 鍒濆鍖栨垚鍔熺巼瓒嬪娍鍥捐〃
- initSuccessTrendChart() {
- this.successTrendChart = echarts.init(this.$refs.successTrendChart);
- const option = {
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['鑲濊剰绉绘', '鑲捐剰绉绘', '蹇冭剰绉绘', '骞冲潎鎴愬姛鐜�']
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- boundaryGap: false,
- data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�']
- },
- yAxis: {
- type: 'value',
- min: 80,
- max: 100
- },
- series: [
- {
- name: '鑲濊剰绉绘',
- type: 'line',
- smooth: true,
- data: [92, 93, 94, 95, 96, 95, 96]
- },
- {
- name: '鑲捐剰绉绘',
- type: 'line',
- smooth: true,
- data: [94, 95, 95, 96, 95, 96, 97]
- },
- {
- name: '蹇冭剰绉绘',
- type: 'line',
- smooth: true,
- data: [88, 89, 90, 91, 92, 91, 92]
- },
- {
- name: '骞冲潎鎴愬姛鐜�',
- type: 'line',
- smooth: true,
- lineStyle: {
- type: 'dashed'
- },
- data: [91.3, 92.3, 93, 94, 94.3, 94, 95]
- }
- ]
- };
- this.successTrendChart.setOption(option);
- },
+ if (!infoid) {
+ this.$message.error("缂哄皯蹇呰鐨勮矾鐢卞弬鏁� infoid");
+ this.$router.back();
+ return;
+ }
- // 鍒濆鍖栭殢璁跨粺璁″浘琛�
- initFollowupStatsChart() {
- this.followupStatsChart = echarts.init(this.$refs.followupStatsChart);
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- }
- },
- legend: {
- data: ['璁″垝闅忚', '宸插畬鎴�', '閫炬湡鏈畬鎴�']
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis: {
- type: 'value'
- },
- yAxis: {
- type: 'category',
- data: ['1涓湀', '3涓湀', '6涓湀', '1骞�', '2骞�', '5骞�']
- },
- series: [
- {
- name: '璁″垝闅忚',
- type: 'bar',
- stack: 'total',
- label: {
- show: true
- },
- emphasis: {
- focus: 'series'
- },
- data: [120, 132, 101, 134, 90, 60]
- },
- {
- name: '宸插畬鎴�',
- type: 'bar',
- stack: 'total',
- label: {
- show: true
- },
- emphasis: {
- focus: 'series'
- },
- data: [115, 125, 95, 120, 85, 55]
- },
- {
- name: '閫炬湡鏈畬鎴�',
- type: 'bar',
- stack: 'total',
- label: {
- show: true
- },
- emphasis: {
- focus: 'series'
- },
- data: [5, 7, 6, 14, 5, 5]
- }
- ]
- };
- this.followupStatsChart.setOption(option);
- },
+ this.form.infoid = infoid;
+ // this.generateDonorNo();
- // 鍒濆鍖栧苟鍙戠棁鍒嗘瀽鍥捐〃
- initComplicationChart() {
- this.complicationChart = echarts.init(this.$refs.complicationChart);
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- }
- },
- radar: {
- indicator: [
- { name: '鎰熸煋椋庨櫓', max: 100 },
- { name: '鎺掓枼鍙嶅簲', max: 100 },
- { name: '琛�绠″苟鍙戠棁', max: 100 },
- { name: '鑳嗛亾骞跺彂鐥�', max: 100 },
- { name: '浠h阿寮傚父', max: 100 },
- { name: '鍏朵粬骞跺彂鐥�', max: 100 }
- ]
- },
- series: [
- {
- type: 'radar',
- data: [
- {
- value: [85, 90, 78, 82, 75, 70],
- name: '鑲濊剰绉绘',
- areaStyle: {}
- },
- {
- value: [78, 85, 72, 65, 80, 68],
- name: '鑲捐剰绉绘',
- areaStyle: {}
- },
- {
- value: [90, 88, 85, 60, 82, 75],
- name: '蹇冭剰绉绘',
- areaStyle: {}
- }
- ]
- }
- ]
- };
- this.complicationChart.setOption(option);
- },
+ if (infoid) {
+ this.getDetail(infoid);
+ }
- // 鏇存柊鍥捐〃瑙嗗浘
- updateCharts() {
- if (this.chartView === 'bar') {
- this.updateToBarChart();
- } else {
- this.initOrganDistributionChart(); // 鍒囧洖楗煎浘
+ this.getHospitalData();
+ },
+ getOrganNameByNo(organno) {
+ // 妫�鏌ユ槸鍚﹀湪鏄犲皠鐨勫瓙椤逛腑
+ for (const key in this.organExpansionMap) {
+ const { subItems, subNames } = this.organExpansionMap[key];
+ const idx = subItems.indexOf(organno);
+ if (idx !== -1) {
+ return subNames[idx];
+ }
+ }
+ // 鍚﹀垯浠庡瓧鍏镐腑鑾峰彇
+ return this.getOrganLabel(organno);
+ },
+ // 鑾峰彇璇︽儏
+ async getDetail(infoid) {
+ this.loading = true;
+ try {
+ const response = await witnessList({ infoid });
+ if (
+ response.code === 200 &&
+ response.data &&
+ response.data.length > 0
+ ) {
+ const data = response.data[0];
+ if (!data.witnessState || data.witnessState == 1) {
+ data.witnessState = "2";
+ }
+
+ // 濉厖琛ㄥ崟鏁版嵁
+ Object.assign(this.form, data);
+
+ // 鍒濆鍖栭檮浠�
+ if (this.form.deathjudgeannex) {
+ const parsed = JSON.parse(this.form.deathjudgeannex);
+ this.attachments = parsed.map(item => ({
+ ...item,
+ fileType: item.fileType || "" // 榛樿绌哄瓧绗︿覆琛ㄧず鏈垎绫�
+ }));
+ this.form.attachments = this.attachments;
+ } else {
+ this.attachments = [];
+ }
+
+ // 澶勭悊鎹愮尞鍣ㄥ畼瀛楁
+ if (data.organdonation) {
+ const organArray = Array.isArray(data.organdonation)
+ ? data.organdonation
+ : (data.organdonation || "").split(",").filter(item => item);
+ this.selectedOrgans = organArray;
+ this.form.organdonationOther = data.organdonationOther || "";
+ }
+
+ // 澶勭悊鍣ㄥ畼鑾峰彇璁板綍
+ if (data.serviceDonationwitnessorgans) {
+ this.procurementData.serviceDonationwitnessorgans = Array.isArray(
+ data.serviceDonationwitnessorgans
+ )
+ ? data.serviceDonationwitnessorgans
+ : [];
+ }
+
+ this.$message.success("鏁版嵁鍔犺浇鎴愬姛");
+ this.syncOrgansFromSelection();
+ } else {
+ this.$message.warning("鏈壘鍒板搴旂殑鍣ㄥ畼鑾峰彇鏁版嵁");
+ }
+ } catch (error) {
+ console.error("鑾峰彇鍣ㄥ畼鑾峰彇璇︽儏澶辫触:", error);
+ this.$message.error("鑾峰彇璇︽儏澶辫触");
+ } finally {
+ this.loading = false;
}
},
+ syncOrgansFromSelection() {
+ const records = this.procurementData.serviceDonationwitnessorgans || [];
+ const targetNos = [];
+ this.selectedOrgans.forEach(val => {
+ if (this.organExpansionMap[val]) {
+ targetNos.push(...this.organExpansionMap[val].subItems);
+ } else {
+ targetNos.push(val);
+ }
+ });
- // 鏇存柊涓烘煴鐘跺浘
- updateToBarChart() {
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
+ // 鏂板鎴栨仮澶�
+ targetNos.forEach(no => {
+ const existing = records.find(r => r.organno === no);
+ if (existing) {
+ if (existing.delFlag === 1) {
+ existing.delFlag = 0; // 鎭㈠鏄剧ず
}
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- data: ['鑲濊剰', '鑲捐剰', '蹇冭剰', '鑲鸿剰', '瑙掕啘', '鍏朵粬']
- },
- yAxis: {
- type: 'value',
- name: '鏁伴噺'
- },
- series: [
- {
- name: '鍣ㄥ畼鍒╃敤鏁伴噺',
- type: 'bar',
- data: [35, 30, 15, 10, 8, 2],
- itemStyle: {
- color: function(params) {
- const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272'];
- return colorList[params.dataIndex];
- }
+ } else {
+ records.push({
+ id: null,
+ organname: this.getOrganNameByNo(no),
+ organno: no,
+ organStartTime: "",
+ organgettime: "",
+ gainhospitalno: "",
+ gainhospitalname: "",
+ organgetdoct: "",
+ assistant: "",
+ procurementNurse: "",
+ operatingRoomNurse: "",
+ anesthesiologist: "",
+ organstate: "1",
+ notgetreason: "",
+ delFlag: 0
+ });
+ }
+ });
+
+ // 锛堝彲閫夛級濡傛灉鍔犺浇鏃跺悗绔繑鍥炰簡 delFlag=1 鐨勮褰曪紝浣嗗疄闄呭簲璇ユ樉绀猴紝寮哄埗閲嶇疆
+ records.forEach(r => {
+ if (r.delFlag === 1) r.delFlag = 0;
+ });
+
+ this.form.organdonation = this.selectedOrgans.join(",");
+ },
+ // 鑾峰彇鍖婚櫌鏁版嵁
+ async getHospitalData() {
+ try {
+ // TODO: 鏇挎崲涓哄疄闄呯殑鍖婚櫌鍒楄〃鎺ュ彛
+ // 鏆傛椂浣跨敤妯℃嫙鏁版嵁
+ this.hospitalList = [
+ { hospitalNo: "H001", hospitalName: "鍖椾含鍗忓拰鍖婚櫌" },
+ { hospitalNo: "H002", hospitalName: "涓婃捣鍗庡北鍖婚櫌" },
+ { hospitalNo: "H003", hospitalName: "骞垮窞涓北鍖婚櫌" },
+ { hospitalNo: "H004", hospitalName: "姝︽眽鍚屾祹鍖婚櫌" },
+ { hospitalNo: "H005", hospitalName: "鎴愰兘鍗庤タ鍖婚櫌" }
+ ];
+ } catch (error) {
+ console.error("鑾峰彇鍖婚櫌鏁版嵁澶辫触:", error);
+ this.$message.error("鑾峰彇鍖婚櫌鏁版嵁澶辫触");
+ }
+ },
+ // 绉绘鍖婚櫌妯$硦鎼滅储
+ queryHospitalSearch(queryString, cb) {
+ const hospitals = this.dict.type.Geta_hospital || [];
+ const results = queryString
+ ? hospitals.filter(item =>
+ item.label.toLowerCase().includes(queryString.toLowerCase())
+ )
+ : hospitals;
+
+ // el-autocomplete 闇�瑕� value 瀛楁
+ cb(results.map(item => ({ value: item.label })));
+ },
+ // 鍣ㄥ畼閫夋嫨鐘舵�佸彉鍖�
+ async handleOrganSelectionChange(selectedValues) {
+ // 1. 澶勭悊浜掓枼閫昏緫锛堜慨鏀� this.selectedOrgans锛�
+ this.handleExclusiveSelections(selectedValues);
+
+ const finalSelected = this.selectedOrgans;
+ const records = this.procurementData.serviceDonationwitnessorgans || [];
+
+ // 2. 鏋勫缓鐩爣鍣ㄥ畼缂栧彿鍒楄〃锛堝睍寮�缁勫悎鍣ㄥ畼锛�
+ const targetOrganNos = [];
+ finalSelected.forEach(val => {
+ if (this.organExpansionMap[val]) {
+ targetOrganNos.push(...this.organExpansionMap[val].subItems);
+ } else {
+ targetOrganNos.push(val);
+ }
+ });
+
+ // 3. 鏂板鎴栨仮澶嶇洰鏍囧櫒瀹樿褰曪紙鏃犲脊绐楋級
+ targetOrganNos.forEach(no => {
+ const existing = records.find(r => r.organno === no);
+ if (existing) {
+ if (existing.delFlag === 1) {
+ existing.delFlag = 0; // 鎭㈠鏄剧ず
+ }
+ } else {
+ records.push({
+ id: null,
+ organname: this.getOrganNameByNo(no),
+ organno: no,
+ organStartTime: "",
+ organgettime: "",
+ gainhospitalno: "",
+ gainhospitalname: "",
+ organgetdoct: "",
+ assistant: "",
+ procurementNurse: "",
+ operatingRoomNurse: "",
+ anesthesiologist: "",
+ organstate: "1",
+ notgetreason: "",
+ delFlag: 0
+ });
+ }
+ });
+
+ // 4. 鎵惧嚭闇�瑕佸彇娑堢殑璁板綍锛堜笉鍦ㄧ洰鏍囬泦鍚堜腑锛�
+ const toRemove = records.filter(r => !targetOrganNos.includes(r.organno));
+ const toRemoveSaved = toRemove.filter(r => r.id); // 宸蹭繚瀛橈紝闇�纭
+ const toRemoveUnsaved = toRemove.filter(r => !r.id); // 鏈繚瀛橈紝鐩存帴绉婚櫎
+
+ // 4.1 鐩存帴绉婚櫎鏈繚瀛樼殑璁板綍
+ toRemoveUnsaved.forEach(r => {
+ const idx = records.indexOf(r);
+ if (idx !== -1) records.splice(idx, 1);
+ });
+
+ // 4.2 澶勭悊宸蹭繚瀛樼殑璁板綍锛氬脊绐楃‘璁�
+ if (toRemoveSaved.length > 0) {
+ const organNames = toRemoveSaved.map(r => r.organname).join("銆�");
+ try {
+ await this.$confirm(
+ `鎮ㄧ‘瀹氳鍙栨秷浠ヤ笅宸蹭繚瀛樼殑鍣ㄥ畼鑾峰彇璁板綍鍚楋紵\n${organNames}\n鍙栨秷鍚庯紝杩欎簺璁板綍灏嗕粠鍒楄〃涓Щ闄わ紙鏁版嵁浠嶄繚鐣欙紝鍙仮澶嶏級銆俙,
+ "鎻愮ず",
+ {
+ confirmButtonText: "纭畾绉婚櫎",
+ cancelButtonText: "鍙栨秷",
+ type: "warning"
}
- }
- ]
- };
- this.organDistributionChart.setOption(option);
- },
-
- // 鑾峰彇鐘舵�佹枃鏈�
- getStatusText() {
- const status = this.stageData.status;
- return status === 'completed' ? '宸插畬鎴�' :
- status === 'in_progress' ? '杩涜涓�' : '鏈紑濮�';
- },
-
- // 鑾峰彇璀﹀憡绫诲瀷
- getAlertType() {
- const status = this.stageData.status;
- return status === 'completed' ? 'success' :
- status === 'in_progress' ? 'warning' : 'info';
- },
-
- // 鑾峰彇璀﹀憡鎻忚堪
- getAlertDescription() {
- const status = this.stageData.status;
- if (status === 'completed') {
- return '鍣ㄥ畼鍒╃敤闃舵宸插畬鎴愶紝鎵�鏈夊櫒瀹樺潎宸叉垚鍔熺Щ妞嶅苟寮�濮嬮殢璁�';
- } else if (status === 'in_progress') {
- return '鍣ㄥ畼鍒╃敤杩涜涓紝绉绘鎵嬫湳宸插畬鎴愶紝姝e湪杩涜鏈悗闅忚';
+ );
+ // 鐢ㄦ埛纭锛氭爣璁� delFlag=1
+ toRemoveSaved.forEach(r => {
+ r.delFlag = 1;
+ });
+ } catch (error) {
+ // 鐢ㄦ埛鍙栨秷锛氭仮澶嶉�変腑鐘舵��
+ const parentToRestore = new Set();
+ toRemoveSaved.forEach(r => {
+ const parent = this.organReverseMap[r.organno];
+ if (parent) {
+ parentToRestore.add(parent);
+ } else {
+ parentToRestore.add(r.organno);
+ }
+ });
+ parentToRestore.forEach(val => {
+ if (!this.selectedOrgans.includes(val)) {
+ this.selectedOrgans.push(val);
+ }
+ });
+ this.$message.info("宸插彇娑堝垹闄ゆ搷浣�");
+ // 鏇存柊琛ㄥ崟瀛楁锛堜繚鎸佷竴鑷存�э級
+ this.form.organdonation = this.selectedOrgans.join(",");
+ return; // 閫�鍑烘柟娉曪紝閬垮厤缁х画鎵ц
+ }
}
- return '绛夊緟寮�濮嬪櫒瀹樺埄鐢ㄦ祦绋�';
+
+ // 5. 鏇存柊琛ㄥ崟瀛楁
+ this.form.organdonation = this.selectedOrgans.join(",");
},
- // 鑾峰彇绉绘鐘舵�佹爣绛�
- getTransplantStatusTag(status) {
- const map = {
- '绉绘鎴愬姛': 'success',
- '绉绘涓�': 'warning',
- '绉绘澶辫触': 'danger'
- };
- return map[status] || 'info';
+ // 澶勭悊浜掓枼閫夋嫨
+ handleExclusiveSelections(selectedValues) {
+ // 鍙岃偩涓庡乏鍙宠偩浜掓枼
+ if (selectedValues.includes("C64")) {
+ this.selectedOrgans = selectedValues.filter(
+ item => item !== "C64L" && item !== "C64R"
+ );
+ } else if (
+ selectedValues.includes("C64L") ||
+ selectedValues.includes("C64R")
+ ) {
+ this.selectedOrgans = selectedValues.filter(item => item !== "C64");
+ }
+
+ // 鍏ㄨ偤涓庡乏鍙宠偤浜掓枼
+ if (selectedValues.includes("C34")) {
+ this.selectedOrgans = selectedValues.filter(
+ item => item !== "C34L" && item !== "C34R"
+ );
+ } else if (
+ selectedValues.includes("C34L") ||
+ selectedValues.includes("C34R")
+ ) {
+ this.selectedOrgans = selectedValues.filter(item => item !== "C34");
+ }
},
- // 鑾峰彇鍙椾綋鐘舵�佹爣绛�
- getRecipientStatusTag(status) {
- const map = {
- '鎭㈠鑹ソ': 'success',
- '绋冲畾鎭㈠': 'warning',
- '瀵嗗垏瑙傚療': 'danger'
- };
- return map[status] || 'info';
- },
+ // 鍒涘缓鍣ㄥ畼璁板綍
+ createOrganRecord(organValue) {
+ const organName = this.getOrganLabel(organValue);
- // 鏌ョ湅璇︽儏
- handleViewDetails(row) {
- this.$message.info(`鏌ョ湅${row.organName}绉绘璇︽儏`);
- },
-
- // 娣诲姞闅忚
- handleAddFollowup(row) {
- this.$message.info(`涓�${row.recipientName}娣诲姞闅忚璁板綍`);
- },
-
- // 鐢熸垚鎶ュ憡
- handleGenerateReport() {
- this.$message.info('鐢熸垚鍣ㄥ畼鍒╃敤鍒嗘瀽鎶ュ憡');
- },
-
- // 瀹屾垚鍒╃敤
- handleCompleteUtilization() {
- this.$confirm('纭瀹屾垚鍣ㄥ畼鍒╃敤闃舵鍚楋紵', '鎻愮ず', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'success'
- }).then(() => {
- this.$message.success('鍣ㄥ畼鍒╃敤闃舵宸插畬鎴�');
+ this.procurementData.serviceDonationwitnessorgans.push({
+ id: null,
+ organname: organName,
+ organno: organValue,
+ organStartTime: "",
+ organgettime: "",
+ gainhospitalno: "",
+ gainhospitalname: "",
+ organgetdoct: "",
+ assistant: "",
+ procurementNurse: "",
+ operatingRoomNurse: "",
+ anesthesiologist: "",
+ organstate: "1",
+ notgetreason: ""
});
},
- // 缁熻鏁版嵁鍒嗘瀽
- handleStatistics() {
- this.$message.info('鎵撳紑缁熻鍒嗘瀽闈㈡澘');
+ // 鍖婚櫌閫夋嫨鍙樺寲
+ handleHospitalChange(row, hospitalNo) {
+ const hospital = this.hospitalList.find(
+ item => item.hospitalNo === hospitalNo
+ );
+ if (hospital) {
+ row.gainhospitalname = hospital.hospitalName;
+ }
+ },
+ // 缂栬緫鑾峰彇璁板綍
+ handleEditProcurement(row) {
+ const index = this.procurementData.serviceDonationwitnessorgans.findIndex(
+ item => item.organno === row.organno
+ );
+ if (index !== -1) {
+ this.currentRecord = { ...row };
+ this.currentEditIndex = index;
+ this.editDialogVisible = true;
+ }
+ },
+ // 纭缂栬緫
+ handleEditConfirm() {
+ if (this.currentEditIndex !== -1) {
+ this.procurementData.serviceDonationwitnessorgans[
+ this.currentEditIndex
+ ] = {
+ ...this.currentRecord
+ };
+ this.$message.success("鑾峰彇璁板綍鏇存柊鎴愬姛");
+ this.editDialogVisible = false;
+ }
+ },
+ // 鍣ㄥ畼琛屾牱寮�
+ getOrganRowClassName({ row }) {
+ if (
+ !row.organStartTime ||
+ !row.organgettime ||
+ !row.gainhospitalno ||
+ !row.organgetdoct
+ ) {
+ return "warning-row";
+ }
+ return "";
+ },
+ // 淇濆瓨鍩烘湰淇℃伅
+ async handleSave() {
+ this.$refs.form.validate(async valid => {
+ if (valid) {
+ this.saveLoading = true;
+ try {
+ console.log(this.procurementData.serviceDonationwitnessorgans);
+
+ const saveData = {
+ ...this.form,
+ deathjudgeannex: JSON.stringify(this.attachments),
+ organdonation: this.selectedOrgans.join(","),
+ serviceDonationwitnessorganList:
+ this.procurementData.serviceDonationwitnessorgans || [],
+ serviceDonationwitnessorgans:
+ this.procurementData.serviceDonationwitnessorgans || []
+ };
+ console.log(saveData.serviceDonationwitnessorganList);
+ console.log(saveData.serviceDonationwitnessorgans);
+
+ const apiMethod = this.form.id ? witnessedit : witnessadd;
+ const response = await apiMethod(saveData);
+
+ if (response.code === 200) {
+ this.$message.success("淇濆瓨鎴愬姛");
+ if (!this.form.id && response.data && response.data.id) {
+ this.form.id = response.data.id;
+ this.$router.replace({
+ query: { ...this.$route.query, id: this.form.id }
+ });
+ }
+ } else {
+ this.$message.error("淇濆瓨澶辫触锛�" + (response.msg || "鏈煡閿欒"));
+ }
+ } catch (error) {
+ console.error("淇濆瓨澶辫触:", error);
+ this.$message.error("淇濆瓨澶辫触");
+ } finally {
+ this.saveLoading = false;
+ }
+ }
+ });
+ },
+ // 淇濆瓨鑾峰彇璁板綍
+ async handleSaveProcurement() {
+ if (!this.form.id) {
+ this.$message.warning("璇峰厛淇濆瓨鍩烘湰淇℃伅");
+ return;
+ }
+
+ this.saveLoading = true;
+ try {
+ const saveData = {
+ ...this.form,
+ attachments: this.attachments,
+ organdonation: this.selectedOrgans.join(","),
+ serviceDonationwitnessorgans:
+ this.procurementData.serviceDonationwitnessorgans || []
+ };
+
+ const response = await witnessedit(saveData);
+
+ if (response.code === 200) {
+ this.$message.success("鑾峰彇璁板綍淇濆瓨鎴愬姛");
+ } else {
+ this.$message.error(
+ "淇濆瓨鑾峰彇璁板綍澶辫触锛�" + (response.msg || "鏈煡閿欒")
+ );
+ }
+ } catch (error) {
+ console.error("淇濆瓨鑾峰彇璁板綍澶辫触:", error);
+ this.$message.error("淇濆瓨鑾峰彇璁板綍澶辫触");
+ } finally {
+ this.saveLoading = false;
+ }
+ },
+ // 纭瀹屾垚鑾峰彇
+ async handleConfirmProcurement() {
+ if (this.incompleteRecords > 0) {
+ this.$message.warning("璇峰厛瀹屽杽鎵�鏈夎幏鍙栬褰曠殑淇℃伅");
+ return;
+ }
+
+ this.$confirm("纭瀹屾垚鍣ㄥ畼鑾峰彇鍚楋紵瀹屾垚鍚庡皢鏃犳硶淇敼鑾峰彇淇℃伅銆�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning"
+ })
+ .then(async () => {
+ this.confirmLoading = true;
+ this.form.witnessState = "3";
+ this.form.operationendtime =
+ this.form.operationendtime ||
+ new Date()
+ .toISOString()
+ .replace("T", " ")
+ .substring(0, 19);
+
+ try {
+ const saveData = {
+ ...this.form,
+ attachments: this.attachments,
+ organdonation: this.selectedOrgans.join(","),
+ serviceDonationwitnessorgans:
+ this.procurementData.serviceDonationwitnessorgans || []
+ };
+
+ const response = await witnessedit(saveData);
+
+ if (response.code === 200) {
+ this.$message.success("鍣ㄥ畼鑾峰彇宸插畬鎴�");
+ } else {
+ this.$message.error(
+ "纭鑾峰彇澶辫触锛�" + (response.msg || "鏈煡閿欒")
+ );
+ this.form.witnessState = "2";
+ this.form.operationendtime = "";
+ }
+ } catch (error) {
+ console.error("纭鑾峰彇澶辫触:", error);
+ this.$message.error("纭鑾峰彇澶辫触");
+ this.form.witnessState = "2";
+ this.form.operationendtime = "";
+ } finally {
+ this.confirmLoading = false;
+ }
+ })
+ .catch(() => {});
+ },
+ // 纭鑾峰彇鎸夐挳鍒悕
+ handleProcure() {
+ this.handleConfirmProcurement();
},
- // 瀵煎嚭鏁版嵁
- exportData() {
- this.$message.info('瀵煎嚭鍣ㄥ畼鍒╃敤鏁版嵁');
+ // ===== 闄勪欢鐩稿叧鏂规硶 =====
+ // 鎵撳紑涓婁紶瀵硅瘽妗�
+ openUploadDialog(category) {
+ this.currentUploadCategory = category;
+ this.tempFileList = [];
+ this.uploadDialogVisible = true;
+ this.$nextTick(() => {
+ if (this.$refs.uploadRef) {
+ this.$refs.uploadRef.clearFiles();
+ }
+ });
+ },
+
+ // 涓婁紶鍓嶆牎楠�
+ beforeUpload(file) {
+ const allowedTypes = [
+ "application/pdf",
+ "image/jpeg",
+ "image/png",
+ "application/msword",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+ ];
+ const maxSize = 10 * 1024 * 1024;
+ const isTypeOk =
+ allowedTypes.includes(file.type) ||
+ file.name.endsWith(".pdf") ||
+ file.name.endsWith(".jpg") ||
+ file.name.endsWith(".jpeg") ||
+ file.name.endsWith(".png") ||
+ file.name.endsWith(".doc") ||
+ file.name.endsWith(".docx");
+ if (!isTypeOk) {
+ this.$message.error(
+ "鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇蜂笂浼爌df銆乯pg銆乸ng銆乨oc鎴杁ocx鏍煎紡鏂囦欢"
+ );
+ return false;
+ }
+ if (file.size > maxSize) {
+ this.$message.error("鏂囦欢澶у皬涓嶈兘瓒呰繃10MB");
+ return false;
+ }
+ return true;
+ },
+
+ // 鏂囦欢閫夋嫨鍙樺寲
+ handleFileChange(file, fileList) {
+ this.tempFileList = fileList;
+ },
+
+ // 涓存椂绉婚櫎
+ handleTempRemove(file, fileList) {
+ this.tempFileList = fileList;
+ },
+
+ // 涓婁紶鎴愬姛澶勭悊
+ handleUploadSuccess(response, file, fileList) {
+ if (response.code !== 200) {
+ this.$message.error(response.msg || "涓婁紶澶辫触");
+ return;
+ }
+ // 鏈垎绫诲搴旂┖瀛楃涓诧紝涓庡睍绀�/淇濆瓨閫昏緫涓�鑷�
+ const category =
+ this.currentUploadCategory === "鏈垎绫�"
+ ? ""
+ : this.currentUploadCategory;
+ const attachmentObj = {
+ fileName: file.name,
+ path: response.fileUrl || response.url || response.data || file.url,
+ fileUrl: response.fileUrl || response.url || response.data || file.url,
+ fileType: category,
+ fileSize: file.size,
+ uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
+ };
+ if (!Array.isArray(this.attachments)) {
+ this.attachments = [];
+ }
+ this.attachments.push(attachmentObj);
+ this.$message.success("鏂囦欢涓婁紶鎴愬姛");
+ this.uploadLoading = false;
+ this.uploadDialogVisible = false;
+ this.tempFileList = [];
+ },
+
+ // 鎻愪氦涓婁紶
+ submitUpload() {
+ if (this.tempFileList.length === 0) {
+ this.$message.warning("璇峰厛閫夋嫨瑕佷笂浼犵殑鏂囦欢");
+ return;
+ }
+ this.uploadLoading = true;
+ this.$refs.uploadRef.submit();
+ },
+
+ // 鑾峰彇鏌愬垎绫荤殑鏂囦欢鏁伴噺
+ getCategoryCount(category) {
+ return this.attachments.filter(item => {
+ const type = item.fileType || "";
+ if (category === "鏈垎绫�") {
+ return !this.presetCategories.includes(type);
+ }
+ return type === category;
+ }).length;
+ },
+
+ // 鑾峰彇鏌愬垎绫荤殑鏂囦欢鍒楄〃
+ getCategoryFiles(category) {
+ return this.attachments.filter(item => {
+ const type = item.fileType || "";
+ if (category === "鏈垎绫�") {
+ return !this.presetCategories.includes(type);
+ }
+ return type === category;
+ });
+ },
+
+ // 鏇存柊闄勪欢鍒嗙被锛堜笅鎷変慨鏀规椂瑙﹀彂锛�
+ updateAttachmentCategory(row, newVal) {
+ const target = this.attachments.find(item => item === row);
+ if (target) {
+ target.fileType = newVal;
+ const currentTabHasFiles =
+ this.getCategoryFiles(this.activeTab).length > 0;
+ if (!currentTabHasFiles) {
+ const firstCategory = this.categories[0];
+ if (firstCategory) this.activeTab = firstCategory;
+ }
+ }
+ },
+
+ // 鎸夋枃浠跺璞″垹闄わ紙鐢ㄤ簬琛ㄦ牸涓殑鍒犻櫎鎸夐挳锛�
+ handleRemoveAttachmentByFile(file) {
+ this.$confirm("纭畾瑕佸垹闄よ繖涓檮浠跺悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning"
+ })
+ .then(() => {
+ const index = this.attachments.findIndex(item => item === file);
+ if (index > -1) {
+ this.attachments.splice(index, 1);
+ this.$message.success("闄勪欢鍒犻櫎鎴愬姛");
+ }
+ })
+ .catch(() => {});
+ },
+
+ // 鏂囦欢棰勮
+ handlePreview(file) {
+ this.currentPreviewFile = {
+ fileName: file.fileName,
+ fileUrl: file.path || file.fileUrl,
+ fileType: this.getFileType(file.fileName)
+ };
+ this.previewVisible = true;
+ },
+
+ // 鏂囦欢涓嬭浇
+ handleDownload(file) {
+ const fileUrl = file.path || file.fileUrl;
+ const fileName = file.fileName;
+
+ if (fileUrl) {
+ const link = document.createElement("a");
+ link.href = fileUrl;
+ link.download = fileName;
+ link.style.display = "none";
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ this.$message.success("寮�濮嬩笅杞芥枃浠�");
+ } else {
+ this.$message.warning("鏂囦欢璺緞涓嶅瓨鍦紝鏃犳硶涓嬭浇");
+ }
+ },
+
+ /** 鑾峰彇鏂囦欢绫诲瀷 */
+ getFileType(fileName) {
+ if (!fileName) return "other";
+ const extension = fileName
+ .split(".")
+ .pop()
+ .toLowerCase();
+ const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
+ const pdfTypes = ["pdf"];
+ const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
+ if (imageTypes.includes(extension)) return "image";
+ if (pdfTypes.includes(extension)) return "pdf";
+ if (officeTypes.includes(extension)) return "office";
+ return "other";
+ },
+
+ /** 鑾峰彇鏂囦欢鍥炬爣棰滆壊 */
+ getFileIconColor(fileName) {
+ const type = this.getFileType(fileName);
+ const colorMap = {
+ image: "#67C23A",
+ pdf: "#F56C6C",
+ office: "#409EFF",
+ other: "#909399"
+ };
+ 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();
+ },
+
+ /** 鏍煎紡鍖栨枃浠跺ぇ灏� */
+ formatFileSize(bytes) {
+ if (!bytes || bytes === 0) return "0 B";
+ const k = 1024;
+ const sizes = ["B", "KB", "MB", "GB"];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
+ },
+
+ /** 鏃ユ湡鏃堕棿鏍煎紡鍖� */
+ 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>
-.utilization-overview {
- padding: 10px 0;
+.organ-procurement-detail {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
}
-.overview-item {
+.detail-card {
+ margin-bottom: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border: 1px solid #e4e7ed;
+}
+
+.procurement-card {
+ margin-bottom: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border: 1px solid #e4e7ed;
+}
+
+.attachment-card {
+ margin-bottom: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border: 1px solid #e4e7ed;
+ padding: 20px;
+ background: #fafafa;
+}
+
+.attachment-header {
display: flex;
align-items: center;
- margin-bottom: 15px;
- padding: 8px 0;
- border-bottom: 1px solid #f0f0f0;
+ gap: 8px;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid #ebeef5;
}
-.overview-icon {
- font-size: 24px;
- margin-right: 15px;
-}
-
-.overview-content .value {
- font-size: 24px;
- font-weight: bold;
+.attachment-title {
+ font-weight: 600;
color: #303133;
}
-.overview-content .label {
+.attachment-tip {
font-size: 12px;
color: #909399;
+ margin-left: auto;
}
-.success-stats, .time-tracking, .quality-assessment {
- padding: 10px 0;
+.attachment-list {
+ margin-top: 16px;
}
-.success-item, .time-item, .quality-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 15px;
-}
-
-.success-item .label, .time-item .label, .quality-item .label {
- color: #606266;
+.list-title {
+ font-weight: bold;
+ margin-bottom: 12px;
+ color: #303133;
font-size: 14px;
- min-width: 80px;
}
-.time-item .value {
+.file-name {
+ font-size: 13px;
+ margin-left: 8px;
+}
+
+.detail-title {
+ font-size: 18px;
font-weight: 600;
- color: #409EFF;
+ color: #303133;
+ line-height: 1.4;
}
-.chart-container {
- position: relative;
- min-height: 300px;
-}
-
-.action-buttons {
- display: flex;
- justify-content: center;
- gap: 15px;
+/* 缁熻淇℃伅鏍峰紡 */
+.procurement-stats {
margin-top: 20px;
+ padding: 15px;
+ background: linear-gradient(135deg, #a6b2e7 0%, #8a66ad 100%);
+ border-radius: 8px;
+ color: white;
}
-.card-header {
+.stat-item {
display: flex;
- justify-content: space-between;
+ flex-direction: column;
align-items: center;
+ padding: 10px;
+ text-align: center;
+}
+
+.stat-label {
+ font-size: 12px;
+ opacity: 0.9;
+ margin-bottom: 5px;
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.stat-value {
+ font-size: 18px;
+ font-weight: bold;
+ color: white;
+}
+
+/* 绌虹姸鎬佹牱寮� */
+.empty-procurement {
+ text-align: center;
+ padding: 40px 0;
+ color: #909399;
+ background: #fafafa;
+ border-radius: 4px;
+ margin: 20px 0;
+}
+
+/* 瀵硅瘽妗嗗簳閮ㄦ寜閽� */
+.dialog-footer {
+ margin-top: 20px;
+ text-align: center;
+ padding-top: 20px;
+ border-top: 1px solid #e4e7ed;
+}
+
+.dialog-footer .el-button {
+ margin: 0 10px;
+ min-width: 120px;
+}
+
+/* 琛ㄦ牸琛屾牱寮� */
+:deep(.warning-row) {
+ background-color: #fff7e6 !important;
+}
+
+:deep(.warning-row:hover) {
+ background-color: #ffecc2 !important;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+ .organ-procurement-detail {
+ padding: 10px;
+ }
+
+ .procurement-stats .el-col {
+ margin-bottom: 10px;
+ }
}
</style>
--
Gitblit v1.9.3