From ed62678cd16042506bad5e5f75665a822f2d5717 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期二, 30 十二月 2025 10:28:18 +0800
Subject: [PATCH] 数据更新推送

---
 src/views/business/course/components/EthicalReviewStage.vue | 1607 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 1,444 insertions(+), 163 deletions(-)

diff --git a/src/views/business/course/components/EthicalReviewStage.vue b/src/views/business/course/components/EthicalReviewStage.vue
index 47e4877..a5b8476 100644
--- a/src/views/business/course/components/EthicalReviewStage.vue
+++ b/src/views/business/course/components/EthicalReviewStage.vue
@@ -1,206 +1,1487 @@
 <template>
-  <base-stage :stage-data="stageData" :case-info="caseInfo">
-    <template #header>
-      <el-alert
-        title="浼︾悊瀹℃煡闃舵"
-        :type="getAlertType()"
-        :description="getAlertDescription()"
-        show-icon
-        :closable="false"
-      />
-    </template>
-
-    <el-row :gutter="20" style="margin-top: 20px;">
-      <el-col :span="12">
-        <el-card>
-          <div slot="header" class="card-header">
-            <span>瀹℃煡濮斿憳浼氫俊鎭�</span>
-          </div>
-          <el-descriptions :column="1" border>
-            <el-descriptions-item label="濮斿憳浼氬悕绉�">
-              {{ reviewCommittee.name }}
-            </el-descriptions-item>
-            <el-descriptions-item label="瀹℃煡浼氳鏃堕棿">
-              {{ formatTime(reviewCommittee.meetingTime) }}
-            </el-descriptions-item>
-            <el-descriptions-item label="鍙備細濮斿憳">
-              {{ reviewCommittee.members.length }} 浜�
-            </el-descriptions-item>
-            <el-descriptions-item label="瀹℃煡缁撹">
-              <el-tag :type="reviewCommittee.conclusion ? 'success' : 'warning'">
-                {{ reviewCommittee.conclusion ? '瀹℃煡閫氳繃' : '瀹℃煡涓�' }}
-              </el-tag>
-            </el-descriptions-item>
-            <el-descriptions-item label="涓诲腑绛惧瓧">
-              {{ reviewCommittee.chairman }}
-            </el-descriptions-item>
-          </el-descriptions>
-        </el-card>
-      </el-col>
-
-      <el-col :span="12">
-        <el-card>
-          <div slot="header" class="card-header">
-            <span>瀹℃煡娴佺▼杩涘害</span>
-          </div>
-          <el-steps direction="vertical" :active="reviewProgress.active" space="80px">
-            <el-step
-              v-for="step in reviewProgress.steps"
-              :key="step.title"
-              :title="step.title"
-              :description="step.description"
-              :status="step.status"
-            />
-          </el-steps>
-        </el-card>
-      </el-col>
-    </el-row>
-
-    <el-card style="margin-top: 20px;">
-      <div slot="header" class="card-header">
-        <span>濮斿憳瀹℃煡鎰忚</span>
+  <div class="ethics-review-detail">
+    <el-card class="detail-card">
+      <!-- 鍩虹淇℃伅 -->
+      <div slot="header" class="clearfix">
+        <span class="detail-title">浼︾悊瀹℃煡鍩烘湰淇℃伅</span>
       </div>
-      <el-table :data="reviewComments" border>
-        <el-table-column label="濮斿憳濮撳悕" prop="memberName" width="120" />
-        <el-table-column label="涓撲笟棰嗗煙" prop="specialty" width="120" />
-        <el-table-column label="瀹℃煡鎰忚" prop="comment" min-width="200" />
-        <el-table-column label="鎶曠エ缁撴灉" width="100">
+
+      <el-form :model="form" ref="form" :rules="rules" label-width="120px">
+
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="浼︾悊缁撹" prop="ethicsConclusion">
+              <el-select v-model="form.ethicsConclusion" style="width: 100%">
+                <el-option label="瀹℃煡涓�" value="reviewing" />
+                <el-option label="鍚屾剰" value="approved" />
+                <el-option
+                  label="淇敼鍚庡悓鎰�"
+                  value="approved_with_modifications"
+                />
+                <el-option label="淇敼鍚庨噸瀹�" value="re-review" />
+                <el-option label="涓嶅悓鎰�" value="disapproved" />
+                <el-option label="缁堟瀹℃煡" value="terminated" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="瀹℃煡鏃堕棿" prop="reviewTime">
+              <el-date-picker
+                v-model="form.reviewTime"
+                type="datetime"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鐧昏浜�" prop="registrant">
+              <el-input v-model="form.registrant" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="浼︾悊鎰忚" prop="ethicsOpinion">
+              <el-input
+                type="textarea"
+                :rows="3"
+                v-model="form.ethicsOpinion"
+                placeholder="璇疯緭鍏ヤ鸡鐞嗗鏌ユ剰瑙�"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="鐧昏鏃堕棿" prop="registrationTime">
+          <el-date-picker
+            v-model="form.registrationTime"
+            type="datetime"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            style="width: 100%"
+          />
+        </el-form-item>
+      </el-form>
+    </el-card>
+    <!-- 闄勪欢涓婁紶 -->
+    <el-card class="attachment-card">
+      <div slot="header" class="clearfix">
+        <span class="detail-title">鐩稿叧闄勪欢</span>
+        <el-button type="primary" size="mini" @click="handleUploadAttachment">
+          涓婁紶闄勪欢
+        </el-button>
+      </div>
+
+      <el-table :data="attachments" style="width: 100%">
+        <el-table-column label="鏂囦欢鍚嶇О" min-width="200">
           <template slot-scope="scope">
-            <el-tag :type="scope.row.vote === '鍚屾剰' ? 'success' : 'danger'">
-              {{ scope.row.vote }}
-            </el-tag>
+            <div class="file-info">
+              <i
+                class="el-icon-document"
+                style="margin-right: 8px; color: #409EFF;"
+              ></i>
+              <span>{{ scope.row.fileName }}</span>
+            </div>
           </template>
         </el-table-column>
-        <el-table-column label="瀹℃煡鏃堕棿" width="160">
+
+        <el-table-column label="鏂囦欢绫诲瀷" width="100" align="center">
           <template slot-scope="scope">
-            {{ formatTime(scope.row.reviewTime) }}
+            <el-tag size="small">{{ getFileType(scope.row.fileName) }}</el-tag>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="鏂囦欢澶у皬" width="100" align="center">
+          <template slot-scope="scope">
+            <span>{{ formatFileSize(scope.row.fileSize) }}</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="涓婁紶鏃堕棿" width="160" align="center">
+          <template slot-scope="scope">
+            <span>{{ parseTime(scope.row.uploadTime) }}</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="涓婁紶浜�" width="100" align="center">
+          <template slot-scope="scope">
+            <span>{{ scope.row.uploader }}</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="鎿嶄綔" width="120" align="center">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-view"
+              @click="handlePreviewAttachment(scope.row)"
+              >棰勮</el-button
+            >
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-download"
+              @click="handleDownloadAttachment(scope.row)"
+              >涓嬭浇</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
     </el-card>
-
-    <el-card style="margin-top: 20px;">
-      <div slot="header" class="card-header">
-        <span>瀹℃煡鍐宠鏂囦欢</span>
-        <el-button type="primary" size="small" @click="handleViewResolution">
-          鏌ョ湅鍐宠鏂囦欢
-        </el-button>
-      </div>
-      <div class="resolution-content">
-        <p><strong>浼︾悊瀹℃煡鍐宠锛�</strong></p>
-        <p>{{ resolutionContent }}</p>
-        <el-divider />
-        <div class="signature-area">
-          <p>浼︾悊濮斿憳浼氫富甯細{{ reviewCommittee.chairman }}</p>
-          <p>鏃ユ湡锛歿{ formatTime(reviewCommittee.meetingTime) }}</p>
+    <!-- 涓撳瀹℃煡鎯呭喌 -->
+    <el-card class="expert-card">
+      <div slot="header" class="clearfix">
+        <span class="detail-title"
+          >涓撳瀹℃煡鎯呭喌 (18浣嶄笓瀹� + 1浣嶄富濮斾笓瀹�)</span
+        >
+        <div style="float: right;">
+          <el-button
+            size="mini"
+            type="primary"
+            @click="handleSendToNormalExperts"
+            :disabled="!canSendToNormalExperts"
+          >
+            鍙戦�佷笓瀹�
+          </el-button>
+          <el-button
+            size="mini"
+            type="success"
+            @click="handleSendToChiefExpert"
+            :disabled="!canSendToChiefExpert"
+          >
+            鍙戦�佷富濮斾笓瀹�
+          </el-button>
+          <el-button
+            size="mini"
+            type="warning"
+            @click="handleBatchSend"
+            :disabled="!canBatchSend"
+          >
+            鎵归噺鍙戦��
+          </el-button>
         </div>
       </div>
-    </el-card>
-  </base-stage>
-</template>
+ <!-- 涓撳缁熻淇℃伅 -->
+      <div
+        class="expert-stats"
+        style="margin-top: 20px; padding: 15px; background: #f5f7fa; border-radius: 4px;"
+      >
+        <el-row :gutter="20">
+          <el-col :span="6">
+            <div class="stat-item">
+              <span class="stat-label">涓撳宸插悓鎰�:</span>
+              <span class="stat-value">{{ approvedNormalExperts }}/18</span>
+            </div>
+          </el-col>
+          <el-col :span="6">
+            <div class="stat-item">
+              <span class="stat-label">涓诲涓撳鐘舵��:</span>
+              <span class="stat-value">{{ chiefExpertStatus }}</span>
+            </div>
+          </el-col>
+          <el-col :span="6">
+            <div class="stat-item">
+              <span class="stat-label">鎬诲畬鎴愯繘搴�:</span>
+              <span class="stat-value">{{ completionRate }}%</span>
+            </div>
+          </el-col>
+          <el-col :span="6">
+            <div class="stat-item">
+              <span class="stat-label">瀹℃煡缁撴灉:</span>
+              <span class="stat-value">
+                <el-tag :type="overallConclusionFilter">
+                  {{ overallConclusionText }}
+                </el-tag>
+              </span>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+      <!-- 涓撳瀹℃煡琛ㄦ牸 -->
+      <el-table
+        :data="expertReviews"
+        v-loading="expertLoading"
+        style="width: 100%"
+        heiht="300"
+        :row-class-name="getExpertRowClassName"
+      >
+        <el-table-column label="搴忓彿" width="60" align="center" type="index" />
 
+        <el-table-column
+          label="涓撳濮撳悕"
+          width="120"
+          align="center"
+          fixed="left"
+        >
+          <template slot-scope="scope">
+            <span>{{ scope.row.expertName }}</span>
+            <el-tag
+              v-if="scope.row.isChief"
+              size="mini"
+              type="danger"
+              style="margin-left: 5px;"
+              >涓诲</el-tag
+            >
+          </template>
+        </el-table-column>
+
+        <el-table-column label="涓撳绫诲瀷" width="100" align="center">
+          <template slot-scope="scope">
+            <span :class="scope.row.isChief ? 'chief-expert' : 'normal-expert'">
+              {{ scope.row.isChief ? "涓诲涓撳" : "涓撳" }}
+            </span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="瀹℃煡鐘舵��" width="100" align="center">
+          <template slot-scope="scope">
+            <el-tag :type="statusFilter(scope.row.reviewStatus)" size="small">
+              {{ statusTextFilter(scope.row.reviewStatus) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="涓撳缁撹" width="120" align="center">
+          <template slot-scope="scope">
+            <el-tag
+              v-if="scope.row.expertConclusion"
+              :type="conclusionFilter(scope.row.expertConclusion)"
+              size="small"
+            >
+              {{ conclusionTextFilter(scope.row.expertConclusion) }}
+            </el-tag>
+            <span v-else class="no-data">-</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="瀹℃煡鎰忚" min-width="200" show-overflow-tooltip>
+          <template slot-scope="scope">
+            <span :class="{ 'expert-opinion': scope.row.expertOpinion }">
+              {{ scope.row.expertOpinion || "鏆傛棤鎰忚" }}
+            </span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="瀹℃煡鏃堕棿" width="160" align="center">
+          <template slot-scope="scope">
+            <span>{{
+              scope.row.reviewTime ? parseTime(scope.row.reviewTime) : "鏈鏌�"
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍙戦�佹椂闂�" width="160" align="center">
+          <template slot-scope="scope">
+            <span>{{
+              scope.row.reviewTime ? parseTime(scope.row.reviewTime) : "鏈彂閫�"
+            }}</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="鎿嶄綔" width="180" align="center" fixed="right">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-s-promotion"
+              @click="handleSendToExpert(scope.row)"
+              :disabled="scope.row.reviewStatus === 'submitted'"
+              :class="{ 'sent-button': scope.row.reviewStatus === 'submitted' }"
+            >
+              {{ scope.row.reviewStatus === "submitted" ? "宸插彂閫�" : "鍙戦��" }}
+            </el-button>
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-edit"
+              @click="handleEditExpertReview(scope.row)"
+              :disabled="scope.row.reviewStatus !== 'submitted'"
+            >
+              缂栬緫
+            </el-button>
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-view"
+              @click="handleViewExpertReview(scope.row)"
+            >
+              璇︽儏
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+
+
+    </el-card>
+
+    <!-- 鍙戦�佷笓瀹跺璇濇 -->
+    <el-dialog
+      title="鍙戦�佷笓瀹跺鏌�"
+      :visible.sync="sendDialogVisible"
+      width="500px"
+    >
+      <el-form :model="sendForm" ref="sendForm" label-width="100px">
+        <el-form-item label="涓撳绫诲瀷" prop="expertType">
+          <el-radio-group v-model="sendForm.expertType">
+            <el-radio label="normal">涓撳</el-radio>
+            <el-radio label="chief">涓诲涓撳</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          label="閫夋嫨涓撳"
+          prop="expertIds"
+          v-if="sendForm.expertType === 'normal'"
+        >
+          <el-select
+            v-model="sendForm.expertIds"
+            multiple
+            placeholder="璇烽�夋嫨涓撳"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="expert in availableExperts"
+              :key="expert.id"
+              :label="expert.name"
+              :value="expert.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鍙戦�佸唴瀹�" prop="content">
+          <el-input
+            type="textarea"
+            :rows="4"
+            v-model="sendForm.content"
+            placeholder="璇疯緭鍏ュ彂閫佺粰涓撳鐨勫鏌ュ唴瀹硅鏄�"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer">
+        <el-button @click="sendDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSendConfirm"
+          >纭鍙戦��</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
 <script>
-import BaseStage from './BaseStage.vue';
+import {
+  getEthicsReviewDetail,
+  updateEthicsReview,
+  sendExpertReview,
+  endEthicsReview,
+  uploadAttachment,
+  deleteAttachment,
+  getAttachments
+} from "./api/ethicsReview";
 
 export default {
-  name: 'EthicalReviewStage',
-  components: { BaseStage },
-  props: {
-    stageData: {
-      type: Object,
-      default: () => ({})
-    },
-    caseInfo: {
-      type: Object,
-      default: () => ({})
-    }
-  },
+  name: "EthicsReviewDetail",
   data() {
     return {
-      reviewCommittee: {
-        name: '鍖婚櫌浼︾悊瀹℃煡濮斿憳浼�',
-        meetingTime: '2023-12-03 15:20:00',
-        members: ['寮犳暀鎺�', '鏉庝富浠�', '鐜嬪尰鐢�', '璧靛鍛�', '閽变笓瀹�'],
-        conclusion: true,
-        chairman: '寮犳暀鎺�'
+      // 琛ㄥ崟鏁版嵁
+      form: {
+        id: undefined,
+        hospitalNo: "",
+        donorName: "",
+        gender: "",
+        age: "",
+        diagnosis: "",
+        ethicsConclusion: "reviewing",
+        ethicsOpinion: "",
+        reviewTime: "",
+        registrant: "",
+        registrationTime: new Date()
+          .toISOString()
+          .replace("T", " ")
+          .substring(0, 19)
       },
-      reviewProgress: {
-        active: 4,
-        steps: [
-          {
-            title: '鏉愭枡鍒濆',
-            description: '鐢宠鏉愭枡瀹屾暣鎬у鏌�',
-            status: 'finish'
-          },
-          {
-            title: '濮斿憳璇勫',
-            description: '鍚勫鍛樼嫭绔嬪鏌�',
-            status: 'finish'
-          },
-          {
-            title: '浼氳璁ㄨ',
-            description: '濮斿憳浼氶泦浣撹璁�',
-            status: 'finish'
-          },
-          {
-            title: '褰㈡垚鍐宠',
-            description: '鎶曠エ褰㈡垚鏈�缁堝喅璁�',
-            status: 'finish'
-          }
+      // 琛ㄥ崟楠岃瘉瑙勫垯
+      rules: {
+        donorName: [
+          { required: true, message: "鎹愮尞鑰呭鍚嶄笉鑳戒负绌�", trigger: "blur" }
+        ],
+        ethicsConclusion: [
+          { required: true, message: "浼︾悊缁撹涓嶈兘涓虹┖", trigger: "change" }
+        ],
+        reviewTime: [
+          { required: true, message: "瀹℃煡鏃堕棿涓嶈兘涓虹┖", trigger: "change" }
         ]
       },
-      reviewComments: [
+      // 淇濆瓨鍔犺浇鐘舵��
+      saveLoading: false,
+
+      // 闄勪欢鏁版嵁
+      attachments: [],
+     expertReviews: [
+        // 涓撳锛�18浣嶏級- 鍒濆鐘舵�佷负鐢宠涓�
         {
-          memberName: '寮犳暀鎺�',
-          specialty: '鍖诲浼︾悊',
-          comment: '鎹愮尞绋嬪簭绗﹀悎浼︾悊瑙勮寖锛屽悓鎰忛�氳繃',
-          vote: '鍚屾剰',
-          reviewTime: '2023-12-03 14:30:00'
+          id: 1,
+          expertName: "闄舵槉",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
         },
         {
-          memberName: '鏉庝富浠�',
-          specialty: '涓村簥鍖诲',
-          comment: '鍖荤枟绋嬪簭瑙勮寖锛屾棤浼︾悊闂',
-          vote: '鍚屾剰',
-          reviewTime: '2023-12-03 14:45:00'
+          id: 2,
+          expertName: "鍒樻枌",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
         },
         {
-          memberName: '鐜嬪尰鐢�',
-          specialty: '娉曞緥鍖诲',
-          comment: '娉曞緥鏂囦欢榻愬叏锛岀▼搴忓悎娉�',
-          vote: '鍚屾剰',
-          reviewTime: '2023-12-03 15:00:00'
+          id: 3,
+          expertName: "浜庢捣鍒� ",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 4,
+          expertName: "鐜嬬孩姊�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 5,
+          expertName: "鐜嬫槬鍏�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 6,
+          expertName: "鐜嬮潤",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 7,
+          expertName: "杈规枃瓒�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 8,
+          expertName: "闂織鍕�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 9,
+          expertName: "璁稿嚖",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 10,
+          expertName: "璁镐紶灞�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 11,
+          expertName: "寮犵孩宀�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 12,
+          expertName: "鏉ㄨ嫃姘�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 13,
+          expertName: "瀹嬬帀寮�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 14,
+          expertName: "鍛ㄤ紶鍒�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 15,
+          expertName: "鑽嗗嚒娉�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 16,
+          expertName: "鐭枃鎹�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 17,
+          expertName: "钁i渿",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        {
+          id: 18,
+          expertName: "钄¢噾璐�",
+          isChief: false,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
+        },
+        // 涓诲涓撳锛�1浣嶏級
+        {
+          id: 19,
+          expertName: "瀛斿績娑�",
+          isChief: true,
+          reviewStatus: "applying",
+          expertConclusion: "",
+          expertOpinion: "",
+          reviewTime: ""
         }
       ],
-      resolutionContent: '缁忎鸡鐞嗗鏌ュ鍛樹細瀹℃煡锛岃鍣ㄥ畼鎹愮尞妗堜緥绗﹀悎鍖诲浼︾悊瑕佹眰锛屾崘鐚▼搴忚鑼冿紝瀹跺睘鎰忔効鐪熷疄鏈夋晥锛屽悓鎰忚繘琛屽櫒瀹樻崘鐚��'
+      expertLoading: false,
+      attachmentLoading: false,
+      // 鍙戦�佸璇濇
+      sendDialogVisible: false,
+      sendForm: {
+        expertType: "normal",
+        expertIds: [],
+        content: ""
+      },
+      // 涓婁紶鐩稿叧
+      uploadDialogVisible: false,
+      uploadLoading: false,
+      tempFileList: [],
+      // 鍙敤涓撳鍒楄〃
+      availableExperts: [
+        { id: 1, name: "寮犳暀鎺�", type: "normal" },
+        { id: 2, name: "鏉庢暀鎺�", type: "normal" },
+        { id: 3, name: "鐜嬫暀鎺�", type: "normal" },
+        { id: 4, name: "璧典富濮�", type: "chief" }
+      ]
     };
   },
+  computed: {
+    // 璁$畻灞炴�э細涓撳鍚屾剰鏁伴噺
+    approvedNormalExperts() {
+      return this.expertReviews.filter(
+        expert => !expert.isChief && expert.expertConclusion === "approved"
+      ).length;
+    },
+    // 璁$畻灞炴�э細涓诲涓撳鐘舵��
+    chiefExpertStatus() {
+      const chiefExpert = this.expertReviews.find(expert => expert.isChief);
+      return chiefExpert
+        ? this.statusTextFilter(chiefExpert.reviewStatus)
+        : "鏈垎閰�";
+    },
+    // 璁$畻灞炴�э細瀹屾垚杩涘害
+    completionRate() {
+      const totalExperts = this.expertReviews.length;
+      const completedExperts = this.expertReviews.filter(
+        expert => expert.reviewStatus === "submitted"
+      ).length;
+      return totalExperts > 0
+        ? Math.round((completedExperts / totalExperts) * 100)
+        : 0;
+    },
+    // 璁$畻灞炴�э細鎬讳綋缁撹
+    overallConclusionText() {
+      if (this.approvedNormalExperts >= 12) {
+        return "閫氳繃";
+      } else if (this.approvedNormalExperts >= 9) {
+        return "淇敼鍚庨�氳繃";
+      } else {
+        return "涓嶉�氳繃";
+      }
+    },
+    overallConclusionFilter() {
+      if (this.approvedNormalExperts >= 12) {
+        return "success";
+      } else if (this.approvedNormalExperts >= 9) {
+        return "warning";
+      } else {
+        return "danger";
+      }
+    },
+    // 鏄惁鍙互鍙戦�佺粰涓撳
+    canSendToNormalExperts() {
+      return (
+        this.expertReviews.filter(
+          expert => !expert.isChief && expert.reviewStatus === "applying"
+        ).length > 0
+      );
+    },
+    // 鏄惁鍙互鍙戦�佺粰涓诲涓撳锛堥渶瑕佽嚦灏�12涓笓瀹跺悓鎰忥級
+    canSendToChiefExpert() {
+      return (
+        this.approvedNormalExperts >= 12 &&
+        this.expertReviews.filter(
+          expert => expert.isChief && expert.reviewStatus === "applying"
+        ).length > 0
+      );
+    },
+    // 鏄惁鍙互鎵归噺鍙戦��
+    canBatchSend() {
+      return (
+        this.expertReviews.filter(expert => expert.reviewStatus === "applying")
+          .length > 0
+      );
+    },
+    // 鏄惁鍙互鍙戦�佷笓瀹跺鏌�
+    canSendToExperts() {
+      return this.form.id && this.form.ethicsConclusion === "reviewing";
+    },
+    // 褰撳墠鐢ㄦ埛淇℃伅
+    currentUser() {
+      return JSON.parse(sessionStorage.getItem("user") || "{}");
+    }
+  },
+  created() {
+    const id = this.$route.query.id;
+    if (id) {
+      this.getDetail(id);
+      this.getAttachments(id);
+      // 涓嶅啀闇�瑕佷粠鎺ュ彛鑾峰彇涓撳鍒楄〃锛屼娇鐢ㄥ浐瀹氱殑expertReviews鏁版嵁
+    } else if (this.$route.path.includes("/add")) {
+      this.generateHospitalNo();
+      this.form.registrant = this.currentUser.username || "褰撳墠鐢ㄦ埛";
+    }
+  },
   methods: {
-    getAlertType() {
-      const status = this.stageData.status;
-      return status === 'completed' ? 'success' :
-             status === 'in_progress' ? 'warning' : 'info';
+    // 鐢熸垚浣忛櫌鍙�
+    generateHospitalNo() {
+      const timestamp = Date.now().toString();
+      this.form.hospitalNo = "D" + timestamp.slice(-6);
     },
-    getAlertDescription() {
-      const status = this.stageData.status;
-      return status === 'completed' ? '浼︾悊瀹℃煡宸查�氳繃锛屽彲浠ヨ繘琛屽櫒瀹樺垎閰�' :
-             status === 'in_progress' ? '浼︾悊瀹℃煡娴佺▼姝e湪杩涜涓�' : '绛夊緟寮�濮嬩鸡鐞嗗鏌ユ祦绋�';
+    getExpertRowClassName({ row }) {
+      return row.isChief ? "chief-expert-row" : "normal-expert-row";
     },
-    handleViewResolution() {
-      this.$message.info('鏌ョ湅浼︾悊瀹℃煡鍐宠鏂囦欢鍔熻兘');
+    // 鑾峰彇璇︽儏
+    getDetail(id) {
+      getEthicsReviewDetail(id)
+        .then(response => {
+          if (response.code === 200) {
+            this.form = response.data;
+          }
+        })
+        .catch(error => {
+          console.error("鑾峰彇浼︾悊瀹℃煡璇︽儏澶辫触:", error);
+          this.$message.error("鑾峰彇璇︽儏澶辫触");
+        });
+    },
+
+    // 鑾峰彇涓撳瀹℃煡鍒楄〃
+    getExpertReviews(ethicsReviewId) {
+      this.expertLoading = true;
+      // 妯℃嫙鏁版嵁 - 瀹為檯椤圭洰涓粠鎺ュ彛鑾峰彇
+      setTimeout(() => {
+        this.expertReviews = [
+          // 涓撳锛�18浣嶏級
+          {
+            id: 1,
+            expertName: "寮犳暀鎺�",
+            isChief: false,
+            reviewStatus: "submitted",
+            expertConclusion: "approved",
+            expertOpinion: "绗﹀悎浼︾悊瑕佹眰",
+            reviewTime: "2025-12-01 10:30:00"
+          },
+          {
+            id: 2,
+            expertName: "鏉庢暀鎺�",
+            isChief: false,
+            reviewStatus: "submitted",
+            expertConclusion: "approved",
+            expertOpinion: "鏂规璁捐鍚堢悊",
+            reviewTime: "2025-12-01 11:20:00"
+          },
+          {
+            id: 3,
+            expertName: "鐜嬫暀鎺�",
+            isChief: false,
+            reviewStatus: "applying",
+            expertConclusion: "",
+            expertOpinion: "",
+            reviewTime: ""
+          },
+          // 涓诲涓撳锛�1浣嶏級
+          {
+            id: 19,
+            expertName: "璧典富濮�",
+            isChief: true,
+            reviewStatus: "applying",
+            expertConclusion: "",
+            expertOpinion: "",
+            reviewTime: ""
+          }
+        ];
+        this.expertLoading = false;
+      }, 500);
+    },
+
+    // 鑾峰彇闄勪欢鍒楄〃
+    getAttachments(ethicsReviewId) {
+      this.attachmentLoading = true;
+      getAttachments(ethicsReviewId)
+        .then(response => {
+          if (response.code === 200) {
+            this.attachments = response.data;
+          }
+          this.attachmentLoading = false;
+        })
+        .catch(error => {
+          console.error("鑾峰彇闄勪欢鍒楄〃澶辫触:", error);
+          this.attachmentLoading = false;
+        });
+    },
+
+    // 鐘舵�佽繃婊ゅ櫒
+    statusFilter(status) {
+      const statusMap = {
+        applying: "info",
+        submitted: "success"
+      };
+      return statusMap[status] || "info";
+    },
+
+    statusTextFilter(status) {
+      const statusMap = {
+        applying: "鐢宠涓�",
+        submitted: "宸叉彁浜�"
+      };
+      return statusMap[status] || "鏈煡";
+    },
+
+    // 缁撹杩囨护鍣�
+    conclusionFilter(conclusion) {
+      const conclusionMap = {
+        approved: "success",
+        approved_with_modifications: "warning",
+        disapproved: "danger"
+      };
+      return conclusionMap[conclusion] || "info";
+    },
+
+    conclusionTextFilter(conclusion) {
+      const conclusionMap = {
+        approved: "鍚屾剰",
+        approved_with_modifications: "淇敼鍚庡悓鎰�",
+        disapproved: "涓嶅悓鎰�"
+      };
+      return conclusionMap[conclusion] || "鏈煡";
+    },
+
+    // 淇濆瓨淇℃伅
+    handleSave() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.saveLoading = true;
+          const apiMethod = this.form.id ? updateEthicsReview : addEthicsReview;
+
+          apiMethod(this.form)
+            .then(response => {
+              if (response.code === 200) {
+                this.$message.success("淇濆瓨鎴愬姛");
+                if (!this.form.id) {
+                  this.form.id = response.data.id;
+                  this.$router.replace({
+                    query: { ...this.$route.query, id: this.form.id }
+                  });
+                }
+              }
+            })
+            .catch(error => {
+              console.error("淇濆瓨澶辫触:", error);
+              this.$message.error("淇濆瓨澶辫触");
+            })
+            .finally(() => {
+              this.saveLoading = false;
+            });
+        }
+      });
+    },
+
+    // 鍙戦�佷笓瀹跺鏌�
+    handleSendToExperts() {
+      this.sendDialogVisible = true;
+    },
+
+    // 鍙戦�佺粰涓撳
+    handleSendToNormalExperts() {
+      const normalExperts = this.expertReviews.filter(
+        expert => !expert.isChief && expert.reviewStatus === "applying"
+      );
+      this.sendForm.expertIds = normalExperts.map(expert => expert.id);
+      this.sendForm.expertType = "normal";
+      this.sendDialogVisible = true;
+    },
+
+    // 鍙戦�佺粰涓诲涓撳
+    handleSendToChiefExpert() {
+      const chiefExpert = this.expertReviews.find(
+        expert => expert.isChief && expert.reviewStatus === "applying"
+      );
+      if (chiefExpert) {
+        this.sendForm.expertIds = [chiefExpert.id];
+        this.sendForm.expertType = "chief";
+        this.sendDialogVisible = true;
+      }
+    },
+
+    // 鎵归噺鍙戦��
+    handleBatchSend() {
+      const applyingExperts = this.expertReviews.filter(
+        expert => expert.reviewStatus === "applying"
+      );
+      this.sendForm.expertIds = applyingExperts.map(expert => expert.id);
+      this.sendForm.expertType = "batch";
+      this.sendDialogVisible = true;
+    },
+
+    // 鍙戦�佺粰鍗曚釜涓撳
+    handleSendToExpert(expert) {
+      this.sendForm.expertIds = [expert.id];
+      this.sendForm.expertType = expert.isChief ? "chief" : "normal";
+      this.sendDialogVisible = true;
+    },
+
+    // 纭鍙戦��
+    handleSendConfirm() {
+      if (this.sendForm.expertIds.length === 0) {
+        this.$message.warning("璇烽�夋嫨瑕佸彂閫佺殑涓撳");
+        return;
+      }
+
+      sendExpertReview({
+        ethicsReviewId: this.form.id,
+        expertIds: this.sendForm.expertIds,
+        content: this.sendForm.content
+      })
+        .then(response => {
+          if (response.code === 200) {
+            this.$message.success("鍙戦�佹垚鍔�");
+            this.sendDialogVisible = false;
+            this.getExpertReviews(this.form.id);
+            this.sendForm = {
+              expertType: "normal",
+              expertIds: [],
+              content: ""
+            };
+          }
+        })
+        .catch(error => {
+          console.error("鍙戦�佸け璐�:", error);
+          this.$message.error("鍙戦�佸け璐�");
+        });
+    },
+
+    // 缁撴潫瀹℃煡
+    handleEndReview() {
+      this.$confirm(
+        "纭畾瑕佺粨鏉熸湰娆′鸡鐞嗗鏌ュ悧锛熺粨鏉熷悗灏嗘棤娉曚慨鏀逛笓瀹跺鏌ョ粨鏋溿��",
+        "鎻愮ず",
+        {
+          confirmButtonText: "纭畾",
+          cancelButtonText: "鍙栨秷",
+          type: "warning"
+        }
+      )
+        .then(() => {
+          endEthicsReview(this.form.id)
+            .then(response => {
+              if (response.code === 200) {
+                this.$message.success("瀹℃煡宸茬粨鏉�");
+                this.form.ethicsConclusion = "terminated";
+              }
+            })
+            .catch(error => {
+              console.error("缁撴潫瀹℃煡澶辫触:", error);
+              this.$message.error("缁撴潫瀹℃煡澶辫触");
+            });
+        })
+        .catch(() => {});
+    },
+
+    // 缂栬緫涓撳瀹℃煡
+    handleEditExpertReview(expert) {
+      this.$prompt("璇疯緭鍏ュ鏌ユ剰瑙�", "缂栬緫涓撳瀹℃煡", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        inputValue: expert.expertOpinion || "",
+        inputValidator: value => {
+          if (!value || value.trim() === "") {
+            return "瀹℃煡鎰忚涓嶈兘涓虹┖";
+          }
+          return true;
+        }
+      })
+        .then(({ value }) => {
+          // 妯℃嫙鏇存柊涓撳瀹℃煡
+          const index = this.expertReviews.findIndex(e => e.id === expert.id);
+          if (index !== -1) {
+            this.expertReviews[index].expertOpinion = value;
+            this.$message.success("瀹℃煡鎰忚宸叉洿鏂�");
+          }
+        })
+        .catch(() => {});
+    },
+
+    // 鏌ョ湅涓撳瀹℃煡璇︽儏
+    handleViewExpertReview(expert) {
+      this.$alert(
+        `
+        <div>
+          <p><strong>涓撳濮撳悕锛�</strong>${expert.expertName}</p>
+          <p><strong>涓撳绫诲瀷锛�</strong>${
+            expert.isChief ? "涓诲涓撳" : "涓撳"
+          }</p>
+          <p><strong>瀹℃煡鐘舵�侊細</strong>${this.statusTextFilter(
+            expert.reviewStatus
+          )}</p>
+          <p><strong>涓撳缁撹锛�</strong>${
+            expert.expertConclusion
+              ? this.conclusionTextFilter(expert.expertConclusion)
+              : "鏈彁浜�"
+          }</p>
+          <p><strong>瀹℃煡鎰忚锛�</strong>${expert.expertOpinion || "鏃�"}</p>
+          <p><strong>瀹℃煡鏃堕棿锛�</strong>${expert.reviewTime || "鏈鏌�"}</p>
+        </div>
+      `,
+        "涓撳瀹℃煡璇︽儏",
+        {
+          dangerouslyUseHTMLString: true,
+          customClass: "expert-review-detail-dialog"
+        }
+      );
+    },
+
+    // 涓婁紶闄勪欢
+    handleUploadAttachment() {
+      this.uploadDialogVisible = true;
+    },
+
+    // 涓婁紶鍓嶆牎楠�
+    beforeUpload(file) {
+      const allowedTypes = [
+        "application/pdf",
+        "image/jpeg",
+        "image/png",
+        "application/msword",
+        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+        "application/vnd.ms-excel",
+        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+      ];
+
+      const maxSize = 10 * 1024 * 1024;
+
+      const isTypeOk =
+        allowedTypes.includes(file.type) ||
+        file.name.endsWith(".pdf") ||
+        file.name.endsWith(".jpg") ||
+        file.name.endsWith(".jpeg") ||
+        file.name.endsWith(".png") ||
+        file.name.endsWith(".doc") ||
+        file.name.endsWith(".docx") ||
+        file.name.endsWith(".xls") ||
+        file.name.endsWith(".xlsx");
+
+      if (!isTypeOk) {
+        this.$message.error("鏂囦欢鏍煎紡涓嶆敮鎸�");
+        return false;
+      }
+
+      if (file.size > maxSize) {
+        this.$message.error("鏂囦欢澶у皬涓嶈兘瓒呰繃10MB");
+        return false;
+      }
+
+      return true;
+    },
+
+    // 鏂囦欢閫夋嫨鍙樺寲
+    handleFileChange(file, fileList) {
+      this.tempFileList = fileList;
+    },
+
+    // 鎻愪氦涓婁紶
+    submitUpload() {
+      if (this.tempFileList.length === 0) {
+        this.$message.warning("璇峰厛閫夋嫨瑕佷笂浼犵殑鏂囦欢");
+        return;
+      }
+
+      this.uploadLoading = true;
+
+      const uploadPromises = this.tempFileList.map(file => {
+        const formData = new FormData();
+        formData.append("file", file.raw);
+        formData.append("ethicsReviewId", this.form.id);
+
+        return uploadAttachment(formData);
+      });
+
+      Promise.all(uploadPromises)
+        .then(responses => {
+          this.$message.success("鏂囦欢涓婁紶鎴愬姛");
+          this.uploadDialogVisible = false;
+          this.tempFileList = [];
+          this.getAttachments(this.form.id);
+        })
+        .catch(error => {
+          console.error("涓婁紶澶辫触:", error);
+          this.$message.error("鏂囦欢涓婁紶澶辫触");
+        })
+        .finally(() => {
+          this.uploadLoading = false;
+        });
+    },
+
+    // 棰勮闄勪欢
+    handlePreviewAttachment(attachment) {
+      if (attachment.fileName.endsWith(".pdf")) {
+        window.open(attachment.fileUrl, "_blank");
+      } else if (attachment.fileName.match(/\.(jpg|jpeg|png)$/i)) {
+        this.$alert(
+          `<img src="${attachment.fileUrl}" style="max-width: 100%;" alt="${attachment.fileName}">`,
+          "鍥剧墖棰勮",
+          {
+            dangerouslyUseHTMLString: true,
+            customClass: "image-preview-dialog"
+          }
+        );
+      } else {
+        this.$message.info("璇ユ枃浠剁被鍨嬫殏涓嶆敮鎸佸湪绾块瑙堬紝璇蜂笅杞藉悗鏌ョ湅");
+      }
+    },
+
+    // 涓嬭浇闄勪欢
+    handleDownloadAttachment(attachment) {
+      const link = document.createElement("a");
+      link.href = attachment.fileUrl;
+      link.download = attachment.fileName;
+      link.click();
+      this.$message.success(`寮�濮嬩笅杞�: ${attachment.fileName}`);
+    },
+
+    // 鍒犻櫎闄勪欢
+    handleRemoveAttachment(attachment) {
+      this.$confirm("纭畾瑕佸垹闄よ繖涓檮浠跺悧锛�", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning"
+      })
+        .then(() => {
+          deleteAttachment(attachment.id)
+            .then(response => {
+              if (response.code === 200) {
+                this.$message.success("闄勪欢鍒犻櫎鎴愬姛");
+                this.getAttachments(this.form.id);
+              }
+            })
+            .catch(error => {
+              console.error("鍒犻櫎闄勪欢澶辫触:", error);
+              this.$message.error("鍒犻櫎闄勪欢澶辫触");
+            });
+        })
+        .catch(() => {});
+    },
+
+    // 鑾峰彇鏂囦欢绫诲瀷
+    getFileType(fileName) {
+      const ext = fileName
+        .split(".")
+        .pop()
+        .toLowerCase();
+      const typeMap = {
+        pdf: "PDF",
+        doc: "DOC",
+        docx: "DOCX",
+        xls: "XLS",
+        xlsx: "XLSX",
+        jpg: "JPG",
+        jpeg: "JPEG",
+        png: "PNG"
+      };
+      return typeMap[ext] || ext.toUpperCase();
+    },
+
+    // 鏂囦欢澶у皬鏍煎紡鍖�
+    formatFileSize(size) {
+      if (size === 0) return "0 B";
+      const k = 1024;
+      const sizes = ["B", "KB", "MB", "GB"];
+      const i = Math.floor(Math.log(size) / Math.log(k));
+      return parseFloat((size / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
+    },
+
+    // 鏃堕棿鏍煎紡鍖�
+    parseTime(time) {
+      if (!time) return "";
+      const date = new Date(time);
+      return `${date.getFullYear()}-${(date.getMonth() + 1)
+        .toString()
+        .padStart(2, "0")}-${date
+        .getDate()
+        .toString()
+        .padStart(2, "0")} ${date
+        .getHours()
+        .toString()
+        .padStart(2, "0")}:${date
+        .getMinutes()
+        .toString()
+        .padStart(2, "0")}`;
     }
   }
 };
 </script>
-
 <style scoped>
-.resolution-content {
+.ethics-review-detail {
   padding: 20px;
-  line-height: 1.8;
+  background-color: #f5f7fa;
 }
 
-.signature-area {
-  text-align: right;
-  margin-top: 30px;
+.detail-card {
+  margin-bottom: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.expert-card {
+  margin-bottom: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.attachment-card {
+  margin-bottom: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.detail-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.expert-stats {
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+  color: rgb(43, 181, 245);
+  border-radius: 8px;
+  margin-bottom: 20px;
+}
+
+.stat-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 10px;
+}
+
+.stat-label {
+  font-size: 12px;
+  opacity: 0.9;
+  margin-bottom: 5px;
+}
+
+.stat-value {
+  font-size: 18px;
+  font-weight: bold;
+}
+
+.upload-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+  padding: 10px;
+  background-color: #f8f9fa;
+  border-radius: 4px;
+}
+
+.upload-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.file-info {
+  display: flex;
+  align-items: center;
+}
+
+.empty-attachment {
+  text-align: center;
+  padding: 40px 0;
+  color: #909399;
+}
+
+/* 琛ㄥ崟鏍峰紡浼樺寲 */
+:deep(.el-form-item__label) {
+  font-weight: 500;
+}
+
+:deep(.el-input__inner) {
+  border-radius: 4px;
+}
+
+:deep(.el-textarea__inner) {
+  border-radius: 4px;
+  resize: vertical;
+}
+
+/* 琛ㄦ牸鏍峰紡浼樺寲 */
+:deep(.el-table) {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+:deep(.el-table th) {
+  background-color: #f5f7fa;
+  color: #606266;
+  font-weight: 500;
+}
+
+:deep(.el-table .cell) {
+  padding: 8px 12px;
+}
+
+/* 鎸夐挳鏍峰紡浼樺寲 */
+:deep(.el-button--primary) {
+  background: linear-gradient(135deg, #409eff 0%, #3375e0 100%);
+  border: none;
+  border-radius: 4px;
+}
+
+:deep(.el-button--success) {
+  background: linear-gradient(135deg, #67c23a 0%, #529b2f 100%);
+  border: none;
+  border-radius: 4px;
+}
+
+:deep(.el-button--warning) {
+  background: linear-gradient(135deg, #e6a23c 0%, #d18c2a 100%);
+  border: none;
+  border-radius: 4px;
+}
+
+:deep(.el-button--danger) {
+  background: linear-gradient(135deg, #f56c6c 0%, #e05b5b 100%);
+  border: none;
+  border-radius: 4px;
+}
+
+/* 鏍囩鏍峰紡 */
+:deep(.el-tag) {
+  border-radius: 12px;
+  border: none;
+  font-weight: 500;
+}
+
+/* 瀵硅瘽妗嗘牱寮忎紭鍖� */
+:deep(.el-dialog) {
+  border-radius: 8px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
+}
+
+:deep(.el-dialog__header) {
+  background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
+  border-bottom: 1px solid #e4e7ed;
+  padding: 15px 20px;
+}
+
+:deep(.el-dialog__title) {
+  font-weight: 600;
+  color: #303133;
+}
+
+/* 涓婁紶缁勪欢鏍峰紡 */
+:deep(.el-upload-dragger) {
+  border: 2px dashed #dcdfe6;
+  border-radius: 6px;
+  background-color: #fafafa;
+  transition: all 0.3s ease;
+}
+
+:deep(.el-upload-dragger:hover) {
+  border-color: #409eff;
+  background-color: #f0f7ff;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .ethics-review-detail {
+    padding: 10px;
+  }
+
+  .expert-stats .el-col {
+    margin-bottom: 10px;
+  }
+
+  .upload-header {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 10px;
+  }
+}
+
+/* 鍔ㄧ敾鏁堟灉 */
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.3s ease;
+}
+
+.fade-enter,
+.fade-leave-to {
+  opacity: 0;
+}
+
+/* 鍔犺浇鐘舵�� */
+.loading-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 200px;
+}
+/* 涓撳绫诲瀷鏍峰紡 */
+.normal-expert {
+  color: #409eff;
+  font-weight: 500;
+}
+
+.chief-expert {
+  color: #f56c6c;
+  font-weight: 600;
+}
+
+/* 涓撳琛屾牱寮� */
+:deep(.normal-expert-row) {
+  background-color: #fafafa;
+}
+
+:deep(.chief-expert-row) {
+  background-color: #fff7e6;
+}
+
+:deep(.normal-expert-row:hover) {
+  background-color: #f0f7ff;
+}
+
+:deep(.chief-expert-row:hover) {
+  background-color: #ffecc2;
+}
+
+/* 鏃犳暟鎹牱寮� */
+.no-data {
+  color: #909399;
+  font-style: italic;
+}
+
+/* 涓撳鎰忚鏍峰紡 */
+.expert-opinion {
+  color: #303133;
+  line-height: 1.5;
+}
+
+/* 宸插彂閫佹寜閽牱寮� */
+.sent-button {
+  color: #67c23a !important;
+}
+
+/* 琛ㄦ牸琛屾偓鍋滄晥鏋� */
+:deep(.el-table__row:hover) {
+  transform: translateY(-1px);
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+}
+/* 鑷畾涔夋粴鍔ㄦ潯 */
+:deep(::-webkit-scrollbar) {
+  width: 6px;
+  height: 6px;
+}
+
+:deep(::-webkit-scrollbar-track) {
+  background: #f1f1f1;
+  border-radius: 3px;
+}
+
+:deep(::-webkit-scrollbar-thumb) {
+  background: #c1c1c1;
+  border-radius: 3px;
+}
+
+:deep(::-webkit-scrollbar-thumb:hover) {
+  background: #a8a8a8;
+}
+
+/* 涓撳瀹℃煡琛ㄦ牸鐗规畩鏍峰紡 */
+.expert-table-special :deep(.el-table__row) {
+  transition: all 0.3s ease;
+}
+
+.expert-table-special :deep(.el-table__row:hover) {
+  background-color: #f0f7ff;
+  transform: translateY(-1px);
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* 涓诲涓撳琛岄珮浜� */
+:deep(.chief-expert-row) {
+  background-color: #fff7e6 !important;
+}
+
+:deep(.chief-expert-row:hover) {
+  background-color: #ffecc2 !important;
 }
 </style>

--
Gitblit v1.9.3