From 4c9fdc87987140e8b2c3f0dfc2f6608cdb6be774 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期三, 21 十月 2026 17:39:24 +0800
Subject: [PATCH] 青岛维护

---
 src/views/business/affirm/affirmInfo.vue | 1635 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 1,344 insertions(+), 291 deletions(-)

diff --git a/src/views/business/affirm/affirmInfo.vue b/src/views/business/affirm/affirmInfo.vue
index 613f64e..01a463a 100644
--- a/src/views/business/affirm/affirmInfo.vue
+++ b/src/views/business/affirm/affirmInfo.vue
@@ -1,64 +1,17 @@
 <template>
   <div class="confirmation-detail">
-    <case-basic-info :case-id="caseId" :show-attachment="true" />
+    <case-basic-info :case-id="caseId" :show-attachment="true" :column="3" />
 
-    <el-card class="detail-card">
+    <el-card class="detail-card paper-card">
       <!-- 鍩虹淇℃伅 -->
       <div slot="header" class="clearfix">
         <span class="detail-title">鎹愮尞纭淇℃伅</span>
-        <el-button
-          type="primary"
-          style="float: right;margin-left: 20px;"
-          @click="handleSave"
-          :loading="saveLoading"
-        >
-          淇濆瓨纭淇℃伅
-        </el-button>
-        <el-button
-          type="success"
-          style="float: right;margin-left: 20px;"
-          @click="accomplish"
-          :loading="saveLoading"
-        >
-          纭瀹屾垚
-        </el-button>
       </div>
 
-      <el-form :model="form" ref="form" label-width="120px">
-        <el-row :gutter="20">
+      <el-form :model="form" ref="form" label-width="120px" class="paper-form">
+        <!-- <el-row :gutter="20">
           <el-col :span="8">
-            <el-form-item label="鍗忚皟鍛�1" prop="coordinatedusernameo">
-              <el-input v-model="form.coordinatedusernameo" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="鍗忚皟鍛�2" prop="coordinatedusernamet">
-              <el-input v-model="form.coordinatedusernamet" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="涓氬姟浜哄憳" prop="responsibleusername">
-              <el-input v-model="form.responsibleusername" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-
-        <el-row :gutter="20">
-          <!-- <el-col :span="8">
-            <el-form-item label="纭鐘舵��" prop="relativeconfirmationsign">
-              <el-select
-                v-model="form.relativeconfirmationsign"
-                style="width: 100%"
-
-              >
-                <el-option label="鏈‘璁�" value="0" />
-                <el-option label="瀹跺睘纭" value="1" />
-                <el-option label="涓嶅悓鎰忔崘鐚�" value="2" />
-              </el-select>
-            </el-form-item>
-          </el-col> -->
-          <el-col :span="8">
-            <el-form-item label="绛惧瓧鏃堕棿" prop="signdate">
+            <el-form-item label="纭鏃堕棿" prop="signdate">
               <el-date-picker
                 v-model="form.signdate"
                 type="datetime"
@@ -66,107 +19,282 @@
               />
             </el-form-item>
           </el-col>
-          <!-- <el-col :span="8">
-            <el-form-item label="琛�鍨�" prop="bloodtype">
-              <el-input v-model="form.bloodtype"  />
-            </el-form-item>
-          </el-col> -->
-        </el-row>
-
-        <!-- <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="璇佷欢鍙风爜" prop="idcardno">
-              <el-input v-model="form.idcardno"  />
-            </el-form-item>
-          </el-col>
         </el-row> -->
 
         <!-- 浜插睘淇℃伅 -->
-        <!-- 浜插睘淇℃伅 -->
         <el-divider content-position="left">浜插睘纭淇℃伅</el-divider>
 
-        <el-row :gutter="20">
-          <el-col :span="6">
-            <el-form-item label="浜插睘濮撳悕" prop="relativeconfirmationsignname">
-              <el-input
-                v-model="form.relativeconfirmationsignname"
-                placeholder="璇疯緭鍏ヤ翰灞炲鍚�"
+        <!-- 涓昏浜插睘琛ㄥ崟 -->
+        <div class="form-row">
+          <el-form-item label="浜插睘濮撳悕" class="col-1-3">
+            <el-input
+              v-model="familyMemberList[0].name"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ヤ翰灞炲鍚�"
+            />
+          </el-form-item>
+          <el-form-item label="鍏崇郴" class="col-1-3">
+            <el-select
+              v-model="familyMemberList[0].relation"
+              :disabled="isReadOnly"
+              placeholder="璇烽�夋嫨鍏崇郴"
+            >
+              <el-option
+                v-for="dict in dict.type.sys_FamilyRelation"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
               />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="涓庢崘璧犺�呭叧绯�" prop="signfamilyrelations">
-              <el-select
-                v-model="form.signfamilyrelations"
-                placeholder="璇烽�夋嫨涓庢崘璧犺�呭叧绯�"
-              >
-                <el-option
-                  v-for="dict in dict.type.sys_FamilyRelation || []"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                ></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="浜插睘韬唤璇�" prop="relativeidcardno">
+            </el-select>
+          </el-form-item>
+          <el-form-item label="韬唤璇佸彿" class="col-1-3">
+            <el-input
+              v-model="familyMemberList[0].idcard"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ヨ韩浠借瘉鍙�"
+              maxlength="18"
+            />
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <el-form-item label="浣忓潃" class="col-full">
+            <template v-if="!isReadOnly">
+              <div class="area-select-box">
+                <li_area_select v-model="familyMemberList[0].address" />
+              </div>
               <el-input
-                v-model="form.relativeidcardno"
-                placeholder="璇疯緭鍏ヤ翰灞炶瘉浠跺彿鐮�"
+                v-model="familyMemberList[0].address.detail"
+                placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
+                class="address-detail"
               />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="浜插睘鐢佃瘽" prop="relativephone">
+            </template>
+            <span v-else>{{ formatAddress(familyMemberList[0].address) }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <el-form-item label="鐜板眳浣忓湴" class="col-full">
+            <template v-if="!isReadOnly">
+              <div class="area-select-box">
+                <li_area_select
+                  v-model="familyMemberList[0].currentResidence"
+                />
+              </div>
               <el-input
-                v-model="form.relativephone"
-                placeholder="璇疯緭鍏ヤ翰灞炶仈绯荤數璇�"
+                v-model="familyMemberList[0].currentResidence.detail"
+                placeholder="璇疯緭鍏ヨ缁嗗湴鍧�"
+                class="address-detail"
               />
-            </el-form-item>
-          </el-col>
-        </el-row>
+            </template>
+            <span v-else>{{
+              formatAddress(familyMemberList[0].currentResidence)
+            }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <el-form-item label="鎵嬫満" class="col-1-3">
+            <el-input
+              v-model="familyMemberList[0].phone"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ユ墜鏈哄彿"
+              maxlength="11"
+            />
+          </el-form-item>
+        </div>
 
-        <el-row>
-          <el-form-item label-width="100px" label="鎹愮尞鍐冲畾">
-            <el-checkbox-group v-model="organdecision">
+        <!-- 浜插睘鍏崇郴纭 -->
+        <div class="form-row">
+          <el-form-item label="浜插睘鍏崇郴纭" class="col-full">
+            <el-checkbox-group
+              v-model="form.kinship"
+              :disabled="isReadOnly"
+              @change="syncKinshipRelatives"
+            >
               <el-checkbox
-                v-for="item in organselection"
-                :key="item"
-                :label="item"
-                >{{ item }}
+                v-for="dict in kinshipCheckboxOptions"
+                :key="dict.value"
+                :label="String(dict.value)"
+              >
+                {{
+                  isChildLabel(dict.label) ? dict.label + "(浜�)" : dict.label
+                }}
               </el-checkbox>
             </el-checkbox-group>
-            <el-input
-              v-if="organdecision.includes('鍏朵粬')"
-              v-model="organdecisionOther"
-              placeholder="璇疯緭鍏ュ叾浠栨崘鐚喅瀹氱殑鍏蜂綋鍐呭"
-              style="margin-top: 10px; width: 300px;"
-            ></el-input>
           </el-form-item>
-        </el-row>
+        </div>
+        <div class="form-row" v-if="adultChildSelected">
+          <el-form-item label="瀛愬コ鏁伴噺" class="col-1-3">
+            <el-input
+              v-model="form.kinshipChildrennum"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ュ瓙濂虫暟閲�"
+              @input="syncKinshipRelatives"
+            />
+          </el-form-item>
+        </div>
 
-        <el-form-item label="瀹跺睘鎰忚澶囨敞" prop="relativeRemark">
-          <el-input
-            type="textarea"
-            :rows="3"
-            v-model="form.relativeRemark"
-            placeholder="璁板綍瀹跺睘鐨勬剰瑙佸拰娌熼�氭儏鍐�"
-          />
-        </el-form-item>
+        <!-- 浜插睘琛紙鐢变翰灞炲叧绯诲嬀閫夎嚜鍔ㄧ敓鎴愶紝濮撳悕鍙紪杈戯級 -->
+        <el-table
+          :data="otherFamilyMemberList"
+          size="small"
+          border
+          style="margin-top: 15px;"
+        >
+          <el-table-column label="搴忓彿" width="60" align="center">
+            <template slot-scope="scope">
+              {{ scope.$index + 1 }}
+            </template>
+          </el-table-column>
+          <el-table-column label="涓庢崘璧犺�呭叧绯�" width="160" align="center">
+            <template slot-scope="scope">
+              {{ getKinshipLabel(scope.row.relation) }}
+            </template>
+          </el-table-column>
+          <el-table-column label="濮撳悕" min-width="200">
+            <template slot-scope="scope">
+              <el-input
+                style="width: 160px"
+                v-model="scope.row.name"
+                :disabled="isReadOnly"
+                placeholder="璇疯緭鍏ュ鍚�"
+                size="small"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            v-if="!isReadOnly"
+            label="鎿嶄綔"
+            width="80"
+            align="center"
+          >
+            <template slot-scope="scope">
+              <el-button
+                type="text"
+                size="small"
+                style="color: #f56c6c"
+                @click="handleDeleteFamilyRow(scope.$index)"
+                >鍒犻櫎</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <div class="form-row">
+          <el-form-item label-width="100px" label="鎹愮尞鍐冲畾" class="col-full">
+            <div class="decision-statement">
+              鎴�(浠�)宸茬煡鎮夋崘鐚殑鐩稿叧娉曞緥娉曡鍙婅瀹氾紝鍚屾剰骞朵唬琛ㄦ崘鐚�呭仛鍑洪�濅笘鍚庤嚜鎰裤�佹棤鍋挎崘鐚喅瀹氾細
+            </div>
+            <template v-if="!isReadOnly">
+              <el-checkbox-group v-model="organdecision">
+                <el-checkbox
+                  v-for="item in organselection"
+                  :key="item"
+                  :label="item"
+                  >{{ item }}
+                </el-checkbox>
+              </el-checkbox-group>
+              <el-input
+                v-if="organdecision.includes('鍏朵粬')"
+                v-model="organdecisionOther"
+                placeholder="璇疯緭鍏ュ叾浠栨崘鐚喅瀹氱殑鍏蜂綋鍐呭"
+                class="decision-other"
+              ></el-input>
+            </template>
+            <span v-else class="decision-selected">{{
+              displayOrganDecision
+            }}</span>
+            <div class="decision-statement">
+              鍚屾剰涓婅堪鎵�鎹愮敤浜庝复搴婂尰鐤椼�佸尰瀛︽暀瀛﹀拰绉戝鐮旂┒銆�
+            </div>
+          </el-form-item>
+        </div>
+
+        <!-- <div class="form-row">
+          <el-form-item
+            label="瀹跺睘鎰忚澶囨敞"
+            prop="relativeRemark"
+            class="col-full"
+          >
+            <el-input
+              type="textarea"
+              :rows="3"
+              v-model="form.relativeRemark"
+              placeholder="璁板綍瀹跺睘鐨勬剰瑙佸拰娌熼�氭儏鍐�"
+              :disabled="isReadOnly"
+            />
+          </el-form-item>
+        </div> -->
+
+        <!-- 浜轰綋鍣ㄥ畼鑾峰彇缁勭粐涓庤礋璐d汉绛惧瓧 -->
+        <div class="form-row">
+          <el-form-item label="浜轰綋鍣ㄥ畼鑾峰彇缁勭粐" class="col-half">
+            <el-input
+              v-model="form.acquisitiontissuename"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ヤ汉浣撳櫒瀹樿幏鍙栫粍缁�"
+            />
+          </el-form-item>
+          <el-form-item
+            label="璐熻矗浜虹瀛�"
+            prop="responsibleusername"
+            class="col-half"
+          >
+            <el-input
+              v-model="form.responsibleusername"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ヨ礋璐d汉绛惧瓧"
+            />
+          </el-form-item>
+        </div>
+
+        <!-- 鍗忚皟鍛樹笌绛剧讲鏃ユ湡 -->
+        <div class="form-row">
+          <el-form-item
+            label="鍗忚皟鍛�1"
+            prop="coordinatedusernameo"
+            class="col-1-3"
+          >
+            <el-input
+              v-model="form.coordinatedusernameo"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ュ崗璋冨憳1"
+            />
+          </el-form-item>
+          <el-form-item
+            label="鍗忚皟鍛�2"
+            prop="coordinatedusernamet"
+            class="col-1-3"
+          >
+            <el-input
+              v-model="form.coordinatedusernamet"
+              :disabled="isReadOnly"
+              placeholder="璇疯緭鍏ュ崗璋冨憳2"
+            />
+          </el-form-item>
+          <el-form-item label="绛剧讲鏃ユ湡" prop="signdate" class="col-1-3">
+            <el-date-picker
+              clearable
+              v-model="form.signdate"
+              type="date"
+              value-format="yyyy-MM-dd"
+              placeholder="閫夋嫨绛剧讲鏃ユ湡"
+              :disabled="isReadOnly"
+            />
+          </el-form-item>
+        </div>
       </el-form>
     </el-card>
 
-    <!-- 闄勪欢淇℃伅 - 鎸夌被鍨嬪垎绫� -->
+    <!-- 娣诲姞杩欓噷锛氬簳閮ㄥ眳涓寜閽� -->
+
+    <!-- 鎹愮尞纭闃舵闄勪欢锛堝彲缂栬緫锛� -->
     <el-card class="attachment-card">
       <div slot="header" class="clearfix">
-        <span class="detail-title">鐩稿叧闄勪欢涓婁紶</span>
+        <span class="detail-title">鎹愮尞纭闃舵闄勪欢</span>
       </div>
 
-      <!-- 闄勪欢绫诲瀷閫夐」鍗� -->
       <el-tabs v-model="activeAttachmentType" type="card">
         <el-tab-pane
-          v-for="type in attachmentTypes"
+          v-for="type in confirmAttachmentTypes"
           :key="type.value"
           :label="type.label"
           :name="type.value"
@@ -176,6 +304,7 @@
               <span class="upload-title">{{ type.label }}</span>
               <el-tooltip content="鐐瑰嚮涓婁紶璇ョ被鍨嬮檮浠�" placement="top">
                 <el-button
+                  v-if="!isReadOnly"
                   size="mini"
                   type="primary"
                   icon="el-icon-plus"
@@ -186,10 +315,9 @@
               </el-tooltip>
             </div>
 
-            <!-- 褰撳墠绫诲瀷鐨勯檮浠跺垪琛� -->
             <div class="attachment-list">
               <el-table
-                :data="getAttachmentsByType(type.value)"
+                :data="getConfirmAttachments(type.value)"
                 size="small"
                 v-loading="attachmentLoading"
                 style="width: 100%;"
@@ -204,7 +332,7 @@
                   </template>
                 </el-table-column>
 
-                <el-table-column label="鏂囦欢绫诲瀷" width="100" align="center">
+                <el-table-column label="鏂囦欢绫诲瀷" width="90" align="center">
                   <template slot-scope="scope">
                     <el-tag size="small">{{
                       getFileType(scope.row.fileName)
@@ -212,19 +340,19 @@
                   </template>
                 </el-table-column>
 
-                <el-table-column label="鏂囦欢澶у皬" width="100" align="center">
+                <el-table-column label="鏂囦欢澶у皬" width="90" align="center">
                   <template slot-scope="scope">
                     <span>{{ formatFileSize(scope.row.fileSize) }}</span>
                   </template>
                 </el-table-column>
 
-                <el-table-column label="涓婁紶鏃堕棿" width="160" align="center">
+                <el-table-column label="涓婁紶鏃堕棿" width="155" align="center">
                   <template slot-scope="scope">
                     <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
                   </template>
                 </el-table-column>
 
-                <el-table-column label="鎿嶄綔" width="150" align="center">
+                <el-table-column label="鎿嶄綔" width="145" align="center">
                   <template slot-scope="scope">
                     <el-button
                       size="mini"
@@ -234,6 +362,7 @@
                       棰勮
                     </el-button>
                     <el-button
+                      v-if="!isReadOnly"
                       size="mini"
                       type="danger"
                       @click="handleRemoveAttachment(type.value, scope.$index)"
@@ -244,9 +373,8 @@
                 </el-table-column>
               </el-table>
 
-              <!-- 绌虹姸鎬佹彁绀� -->
               <div
-                v-if="getAttachmentsByType(type.value).length === 0"
+                v-if="getConfirmAttachments(type.value).length === 0"
                 class="empty-attachment"
               >
                 <el-empty
@@ -260,25 +388,134 @@
       </el-tabs>
     </el-card>
 
+    <!-- 鎹愮尞鑰呯櫥璁伴樁娈甸檮浠讹紙浠呮煡鐪嬶級 -->
+    <el-card class="attachment-card">
+      <div slot="header" class="clearfix">
+        <span class="detail-title">鎹愮尞鑰呯櫥璁伴樁娈甸檮浠讹紙浠呮煡鐪嬶級</span>
+      </div>
+
+      <el-tabs v-model="activeRegisterType" type="card">
+        <el-tab-pane
+          v-for="type in registerAttachmentTypes"
+          :key="type.value"
+          :label="type.label"
+          :name="type.value"
+        >
+          <div class="attachment-section">
+            <div class="attachment-header">
+              <span class="upload-title">{{ type.label }}</span>
+            </div>
+
+            <div class="attachment-list">
+              <el-table
+                :data="getRegisterAttachments(type.value)"
+                size="small"
+                v-loading="attachmentLoading"
+                style="width: 100%;"
+              >
+                <el-table-column label="鏂囦欢鍚�" min-width="200">
+                  <template slot-scope="scope">
+                    <i
+                      class="el-icon-document"
+                      style="color: #409EFF; margin-right: 8px;"
+                    ></i>
+                    <span class="file-name">{{ scope.row.fileName }}</span>
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="鏂囦欢绫诲瀷" width="90" align="center">
+                  <template slot-scope="scope">
+                    <el-tag size="small">{{
+                      getFileType(scope.row.fileName)
+                    }}</el-tag>
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="鏂囦欢澶у皬" width="90" align="center">
+                  <template slot-scope="scope">
+                    <span>{{ formatFileSize(scope.row.fileSize) }}</span>
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="涓婁紶鏃堕棿" width="155" align="center">
+                  <template slot-scope="scope">
+                    <span>{{
+                      formatDateTime(
+                        scope.row.uploadTime || scope.row.createTime
+                      )
+                    }}</span>
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="鎿嶄綔" width="90" align="center">
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="primary"
+                      @click="handlePreview(scope.row)"
+                    >
+                      棰勮
+                    </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+
+              <div
+                v-if="getRegisterAttachments(type.value).length === 0"
+                class="empty-attachment"
+              >
+                <el-empty
+                  :description="`鏆傛棤${type.label}闄勪欢`"
+                  :image-size="80"
+                ></el-empty>
+              </div>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </el-card>
+    <!-- 搴曢儴鎿嶄綔鎸夐挳 -->
+    <div style="text-align: center; margin: 30px 0;">
+      <el-button
+        v-if="!isReadOnly"
+        type="primary"
+        @click="handleSave"
+        :loading="saveLoading"
+        style="margin-right: 20px; min-width: 140px;"
+      >
+        淇濆瓨纭淇℃伅
+      </el-button>
+      <el-button
+        v-if="!isReadOnly"
+        type="success"
+        @click="accomplish"
+        :loading="saveLoading"
+        style="min-width: 140px;"
+      >
+        纭瀹屾垚
+      </el-button>
+    </div>
+
     <!-- 涓婁紶瀵硅瘽妗� -->
     <el-dialog
       :title="`涓婁紶${getCurrentTypeLabel}闄勪欢`"
       :visible.sync="uploadDialogVisible"
-      width="500px"
+      width="480px"
       :close-on-click-modal="false"
     >
       <el-upload
         ref="uploadRef"
         class="upload-demo"
         drag
-        action="#"
+        :action="uploadAction"
+        :headers="headers"
         multiple
         :file-list="tempFileList"
         :before-upload="beforeUpload"
         :on-change="handleFileChange"
         :on-remove="handleTempRemove"
+        :on-success="handleUploadSuccess"
         :auto-upload="false"
-        :http-request="handleHttpRequest"
       >
         <i class="el-icon-upload"></i>
         <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
@@ -311,23 +548,36 @@
 </template>
 
 <script>
-import { relativesList, relativesEdit, relativesAdd } from "@/api/businessApi";
+import {
+  relativesList,
+  relativesEdit,
+  relativesAdd
+} from "@/api/businessApi";
+import {
+  listRelativesconfirmation,
+  getRelativesconfirmation
+} from "@/api/project/relativesconfirmation";
+import {
+  getDonatebaseinfo,
+  updateDonatebaseinfo
+} from "@/api/project/donatebaseinfo";
 import FilePreviewDialog from "@/components/FilePreviewDialog";
 import CaseBasicInfo from "@/components/CaseBasicInfo";
+import Li_area_select from "@/components/Address";
+import { getToken } from "@/utils/auth";
+
 export default {
   name: "ConfirmationDetail",
   components: {
     FilePreviewDialog,
-    CaseBasicInfo
+    CaseBasicInfo,
+    Li_area_select
   },
-  dicts: ["sys_FamilyRelation"],
+  dicts: ["sys_FamilyRelation", "sys_KinshipConfirm", "sys_Kinship"],
   data() {
     return {
       caseId: null,
-
-      // 鏄惁缂栬緫妯″紡
       isEdit: false,
-      // 琛ㄥ崟鏁版嵁
       form: {
         id: undefined,
         infoid: undefined,
@@ -340,72 +590,175 @@
         coordinatedusernameo: "",
         coordinatedusernamet: "",
         responsibleusername: "",
+        acquisitiontissuename: "",
         relativeconfirmationsign: "0",
         signdate: "",
         relativeconfirmationsignname: "",
         signfamilyrelations: "",
         relativeidcardno: "",
         relativephone: "",
+        phone: "",
+        kinship: [],
+        kinshipChildrennum: null,
         relativeRemark: "",
-        assessannex: "" // JSON瀛楃涓插瓨鍌ㄦ墍鏈夐檮浠�
+        assessannex: "",
+        otherFamilyMembers: ""
+      },
+      // 缁熶竴浜插睘鍒楄〃锛堢涓�鏉′负涓昏浜插睘锛屽叾浣欎负鍏朵粬浜插睘锛�
+      familyMemberList: [
+        {
+          name: "",
+          relation: "",
+          phone: "",
+          idcard: "",
+          address: { sheng: "", shi: "", qu: "", detail: "" },
+          currentResidence: { sheng: "", shi: "", qu: "", detail: "" },
+          isMain: true
+        }
+      ],
+      // 鏍囪鏈 syncKinshipRelatives 灞炰簬"鍥炴樉濉厖"锛堟鏃跺厑璁哥敤宸叉湁瀛愬コ琛屾暟鍏滃簳鏁伴噺锛�
+      kinshipHydrated: false,
+
+      uploadAction: process.env.VUE_APP_BASE_API + "/common/upload",
+      headers: {
+        Authorization: "Bearer " + getToken()
       },
       organdecision: [],
       organdecisionOther: "",
       organselection: [
         "鑲濊剰",
-        "鍙岃偩",
-        "宸﹁偩",
-        "鍙宠偩",
+        "鑲捐剰",
         "蹇冭剰",
         "鑲鸿剰",
         "鑳拌吅",
         "灏忚偁",
-        "鍙岀溂缁勭粐",
-        "閬椾綋",
+        "鐪艰鑶�",
         "鍏朵粬"
       ],
-      // 鍔犺浇鐘舵��
       loading: false,
       saveLoading: false,
       infoid: null,
-      // 闄勪欢鐩稿叧鏁版嵁
-      activeAttachmentType: "1",
+      archiveData: null,
+      activeAttachmentType: "2",
+      activeRegisterType: "1",
       attachmentLoading: false,
       uploadDialogVisible: false,
       uploadLoading: false,
       tempFileList: [],
       currentUploadType: "",
-      // 棰勮鐩稿叧
       previewVisible: false,
       currentPreviewFile: null,
-
-      // 闄勪欢绫诲瀷瀹氫箟
-      attachmentTypes: [
-        { value: "1", label: "浜轰綋鍣ㄥ畼娼滃湪鎹愮尞鑰呯櫥璁拌〃" },
+      // 鎹愮尞纭闃舵闄勪欢锛堝彲缂栬緫锛屽瓨鍌ㄤ簬浜插睘纭琛� assessannex锛�
+      confirmAttachmentTypes: [
         { value: "2", label: "浜轰綋鍣ㄥ畼鎹愮尞浜插睘纭鐧昏琛�" },
         { value: "3", label: "鎹愮尞鑰呭強鐩寸郴浜插睘韬唤璇併�佹埛鍙g翱鐩稿叧璇佹槑" },
         { value: "4", label: "鍏皯韬晠鍚庝汉浣撳櫒瀹橈紙瑙掕啘锛夐仐浣撴崘鐚憡鐭ヤ功" },
-        { value: "5", label: "鑴戞浜″垽瀹氱煡鎯呭悓鎰忎功" },
-        { value: "6", label: "蹇冩浜″垽瀹氱煡鎯呭悓鎰忎功" }
+        { value: "7", label: "鎺堟潈濮旀墭璧勬枡" }
       ],
-
-      // 闄勪欢鏁版嵁缁撴瀯 - 鎸夌被鍨嬪垎寮�瀛樺偍
-      attachmentData: {
-        "1": [], // 绫诲瀷1鐨勯檮浠跺垪琛�
+      confirmAttachmentData: {
         "2": [],
         "3": [],
         "4": [],
+        "7": []
+      },
+      // 鎹愮尞鑰呯櫥璁伴樁娈甸檮浠讹紙浠呮煡鐪嬶紝瀛樺偍浜庝翰灞炵‘璁よ〃 assessannex锛�
+      registerAttachmentTypes: [
+        { value: "1", label: "浜轰綋鍣ㄥ畼娼滃湪鎹愮尞鑰呯櫥璁拌〃闄勪欢" },
+        { value: "5", label: "璇佷欢鐓�" },
+        { value: "6", label: "鐤剧梾璇婃柇娌荤枟" }
+      ],
+      registerAttachmentData: {
+        "1": [],
         "5": [],
         "6": []
       }
     };
   },
   computed: {
-    getCurrentTypeLabel() {
-      const type = this.attachmentTypes.find(
-        t => t.value === this.currentUploadType
+    // 鏌ョ湅妯″紡锛氬彧璇伙紝绂佺敤琛ㄥ崟骞堕殣钘忎繚瀛樻寜閽�
+    isReadOnly() {
+      return this.$route.query.mode === "view";
+    },
+    // 鏄惁閫変腑"鎴愬勾瀛愬コ"
+    adultChildSelected() {
+      const value = this.findAdultChildValue();
+      return value != null && (this.form.kinship || []).includes(value);
+    },
+    // 浜插睘鍏崇郴纭瀛楀吀锛堜紭鍏� sys_KinshipConfirm锛屽叾娆� sys_Kinship锛�
+    kinshipDictOptions() {
+      const a = this.dict.type.sys_KinshipConfirm || [];
+      const b = this.dict.type.sys_Kinship || [];
+      return a.length ? a : b;
+    },
+    // 閲嶆帓浜插睘鍏崇郴閫夐」锛氬瓙濂�/鎴愬勾瀛愬コ鎺掑�掓暟绗簩锛屽彈鎵樹汉鎺掓渶鍚�
+    orderedKinshipOptions() {
+      const list = this.kinshipDictOptions;
+      const children = list.filter(d => this.isChildLabel(d.label));
+      const trustee = list.filter(d => d.label === "鍙楁墭浜�");
+      const others = list.filter(
+        d => !this.isChildLabel(d.label) && d.label !== "鍙楁墭浜�"
       );
+      return [...others, ...children, ...trustee];
+    },
+    // 娓叉煋鍕鹃�夋瀹為檯浣跨敤鐨勯�夐」 = 褰撳墠瀛楀吀 + 鍘嗗彶鑴忔暟鎹腑鏄犲皠涓嶅埌鐨勫��
+    // 鑴忓�煎鏋滀笉鍦ㄩ�夐」閲岋紝el-checkbox-group 鏍规湰娌℃湁瀵瑰簲澶嶉�夋锛岃瑙変笂灏辨槸"鍕句笉涓�"锛�
+    // 琛ユ垚甯�"锛堝巻鍙叉暟鎹級"鏍囪鐨勯」鍚庢棦鑳芥樉绀哄嬀閫夛紝涔熷厑璁哥敤鎴锋墜鍔ㄥ彇娑堛��
+    // 鐙珛鎴愯绠楀睘鎬э紙涓嶅苟鍏� orderedKinshipOptions锛夛紝閬垮厤涓� watch 浜掔浉瑙﹀彂褰㈡垚寰幆銆�
+    kinshipCheckboxOptions() {
+      const options = (this.orderedKinshipOptions || []).map(d => ({
+        value: String(d.value),
+        label: d.label
+      }));
+      const extra = [];
+      (this.form.kinship || []).forEach(v => {
+        const raw = String(v);
+        if (!raw) return;
+        if (options.some(o => o.value === raw)) return;
+        if (extra.some(o => o.value === raw)) return;
+        const label = this.getKinshipLabel(raw);
+        extra.push({
+          value: raw,
+          label: label === raw ? `鍘嗗彶鏁版嵁(${raw})` : `${label}(鍘嗗彶鏁版嵁)`
+        });
+      });
+      return [...options, ...extra];
+    },
+    // 鍏朵粬浜插睘鍒楄〃锛堟帓闄ょ涓�鏉′富瑕佷翰灞烇級
+    otherFamilyMemberList() {
+      return this.familyMemberList.slice(1);
+    },
+    // 鎹愮尞鍐冲畾锛堟煡鐪嬫ā寮忓彧灞曠ず宸插嬀閫夐」锛�
+    displayOrganDecision() {
+      return (this.organdecision || [])
+        .map(item => {
+          if (item === "鍏朵粬" && this.organdecisionOther) {
+            return `鍏朵粬锛�${this.organdecisionOther}锛塦;
+          }
+          return item;
+        })
+        .join("銆�");
+    },
+    getCurrentTypeLabel() {
+      const type =
+        this.confirmAttachmentTypes.find(
+          t => t.value === this.currentUploadType
+        ) ||
+        this.registerAttachmentTypes.find(
+          t => t.value === this.currentUploadType
+        );
       return type ? type.label : "";
+    }
+  },
+  watch: {
+    // 瀛楀吀鏄紓姝ュ姞杞界殑锛屽姞杞藉畬鎴愬悗閲嶆柊鏍″噯宸蹭繚瀛樼殑鍕鹃�夊�煎苟閲嶇畻浜插睘琛�
+    orderedKinshipOptions(val) {
+      if (!val || !val.length) return;
+      const normalized = this.normalizeKinshipValues(this.form.kinship || []);
+      if (normalized.join(",") !== (this.form.kinship || []).join(",")) {
+        this.form.kinship = normalized;
+      }
+      this.kinshipHydrated = true;
+      this.syncKinshipRelatives();
     }
   },
   created() {
@@ -417,14 +770,42 @@
     }
   },
   methods: {
-    // 鑾峰彇璇︽儏
     async getDetail(infoid) {
       this.loading = true;
       try {
-        const response = await relativesList({ infoid });
+        const response = await relativesList({
+          infoid,
+          pageNum: 1,
+          pageSize: 10
+        });
+        // 浜插睘纭瀹屾暣璁板綍锛堝惈 kinship 澶氶�夊瓧娈碉級锛岀敤浜庝繚璇佸嬀閫夊洖鏄�
+        let fullRecord = null;
+        try {
+          const fullRes = await listRelativesconfirmation({
+            infoid,
+            pageNum: 1,
+            pageSize: 10
+          });
+          if (
+            fullRes.code === 200 &&
+            Array.isArray(fullRes.rows) &&
+            fullRes.rows.length
+          ) {
+            // 蹇呴』鏍¢獙 infoid 涓�鑷达紝鍚﹀垯鍙兘鎷垮埌鍏ㄨ〃绗竴鏉¤褰�
+            const matched = fullRes.rows.find(
+              r => String(r.infoid) === String(infoid)
+            );
+            fullRecord = matched || fullRes.rows[0];
+          }
+        } catch (e) {
+          console.warn("鑾峰彇浜插睘纭瀹屾暣璁板綍澶辫触:", e);
+        }
 
         if (response.code === 200) {
-          this.handleDetailData(response);
+          this.handleDetailData(response, fullRecord);
+          await this.loadArchiveInfo();
+          // 鍐嶇敤涓婚敭绮剧‘鎷変竴娆″畬鏁磋褰曪紝纭繚 kinship 涓�瀹氳兘鎷垮埌
+          await this.loadFullKinship();
         } else {
           this.$message.error("鑾峰彇璇︽儏澶辫触锛�" + (response.msg || "鏈煡閿欒"));
         }
@@ -436,11 +817,8 @@
       }
     },
 
-    // 澶勭悊璇︽儏鏁版嵁
-    handleDetailData(response) {
+    handleDetailData(response, fullRecord) {
       let detailData = null;
-
-      // 鏍规嵁鎺ュ彛瀹為檯杩斿洖鐨勬暟鎹粨鏋勮繘琛岃皟鏁�
       if (response.data) {
         if (Array.isArray(response.data)) {
           detailData = response.data[0] || {};
@@ -451,15 +829,66 @@
         } else {
           detailData = response.data;
         }
+      } else if (response.rows && Array.isArray(response.rows)) {
+        detailData = response.rows[0] || {};
       } else {
         detailData = response;
       }
 
-      // 鏄犲皠瀛楁鍒拌〃鍗�
+      // 鍏堣В鏋愪翰灞炲ぇ瀛楁锛氬嬀閫夊�煎彲鑳介渶瑕佷粠瀹冨弽鎺�
+      this.familyMemberList = [];
+      let parsedMembers = [];
+      const rawMembers =
+        detailData.otherFamilyMembers ||
+        (fullRecord && fullRecord.otherFamilyMembers) ||
+        "";
+      if (rawMembers) {
+        try {
+          parsedMembers =
+            typeof rawMembers === "string"
+              ? JSON.parse(rawMembers)
+              : rawMembers || [];
+          if (!Array.isArray(parsedMembers)) parsedMembers = [];
+        } catch (e) {
+          console.warn("瑙f瀽鍏朵粬瀹跺睘鏁版嵁澶辫触:", e);
+          parsedMembers = [];
+        }
+      }
+
+      // 浜插睘鍏崇郴纭鍕鹃�夊�硷細瀹屾暣璁板綍 鈫� 璇︽儏 鈫� 浠庝翰灞炶〃鍙嶆帹锛堜笁閲嶅厹搴曪級
+      let kinshipRaw = null;
+      if (
+        fullRecord &&
+        fullRecord.kinship != null &&
+        fullRecord.kinship !== ""
+      ) {
+        kinshipRaw = fullRecord.kinship;
+      } else if (detailData.kinship != null && detailData.kinship !== "") {
+        kinshipRaw = detailData.kinship;
+      }
+      let kinshipValues = this.parseKinship(kinshipRaw);
+      if (!kinshipValues.length) {
+        // 鍏滃簳锛氫翰灞炶〃鑳藉鐜帮紝璇存槑瀹冨瓨鐨� relation 灏辨槸褰撴椂鍕鹃�夌殑鍊�
+        kinshipValues = Array.from(
+          new Set(
+            parsedMembers
+              .filter(
+                m =>
+                  m &&
+                  m.isMain !== true &&
+                  m.relation != null &&
+                  m.relation !== ""
+              )
+              .map(m => String(m.relation).trim())
+              .filter(v => v !== "")
+          )
+        );
+      }
+
       this.form = {
         ...this.form,
         id: detailData.id || this.$route.query.id,
-        infoid: detailData.infoid || infoid,
+        infoid: detailData.infoid || this.infoid,
         caseNo: detailData.caseNo || "",
         name: detailData.name || "",
         sex: detailData.sex || "",
@@ -469,64 +898,254 @@
         coordinatedusernameo: detailData.coordinatedusernameo || "",
         coordinatedusernamet: detailData.coordinatedusernamet || "",
         responsibleusername: detailData.responsibleusername || "",
+        acquisitiontissuename: "",
         relativeconfirmationsign: detailData.relativeconfirmationsign || "0",
-        signdate: detailData.signdate,
+        signdate: this.normalizeSigndate(detailData.signdate),
         relativeconfirmationsignname:
           detailData.relativeconfirmationsignname || "",
         signfamilyrelations: detailData.signfamilyrelations || "",
         relativeidcardno: detailData.relativeidcardno || "",
         relativephone: detailData.relativephone || "",
+        phone: detailData.phone || detailData.relativephone || "",
+        kinship: kinshipValues,
+        kinshipChildrennum:
+          detailData.kinshipChildrennum != null &&
+          detailData.kinshipChildrennum !== ""
+            ? detailData.kinshipChildrennum
+            : fullRecord && fullRecord.kinshipChildrennum != null
+            ? fullRecord.kinshipChildrennum
+            : null,
         relativeRemark: detailData.relativeRemark || "",
         assessannex: detailData.assessannex || ""
       };
 
-      // 澶勭悊鎹愮尞鍐冲畾鏁版嵁
+      // 涓昏浜插睘锛氫紭鍏堝彇 JSON 涓爣璁� isMain 鐨勯」锛堟柊鏍煎紡锛屽惈浣忓潃/鐜板眳浣忓湴锛�
+      let mainMember = (parsedMembers || []).find(m => m && m.isMain === true);
+      // 鍛戒腑椤瑰湪瑙f瀽鏁扮粍涓殑浣嶇疆锛�-1 琛ㄧず涓讳翰灞炰笉鏉ヨ嚜 otherFamilyMembers
+      let mainIndex = mainMember ? parsedMembers.indexOf(mainMember) : -1;
+      if (!mainMember) {
+        const hasMain =
+          detailData.relativeconfirmationsignname ||
+          detailData.signfamilyrelations ||
+          detailData.relativeidcardno;
+        if (hasMain) {
+          // 鑰佹牸寮忥細涓讳翰灞炲瓨鍦ㄤ笓鐢ㄥ瓧娈甸噷锛宱therFamilyMembers 鍙瓨"鍏朵粬浜插睘"
+          mainMember = {
+            name: detailData.relativeconfirmationsignname || "",
+            relation: detailData.signfamilyrelations || "",
+            idcard: detailData.relativeidcardno || "",
+            phone: detailData.phone || detailData.relativephone || "",
+            address: "",
+            currentResidence: "",
+            isMain: true
+          };
+        } else if (parsedMembers.length) {
+          // 鑴忔暟鎹厹搴曪細涓讳翰灞炰笓鐢ㄥ瓧娈靛叏绌恒�丣SON 閲屼篃娌℃湁 isMain 鏍囪鏃讹紝
+          // 鎶婄涓�鏉″綋浣滀富浜插睘锛屽叾浣欎綔涓哄叾浠栦翰灞烇紝閬垮厤涓讳翰灞炴暣鍧楃┖鐧�
+          mainMember = parsedMembers[0];
+          mainIndex = 0;
+        }
+      }
+      this.familyMemberList.push({
+        name: (mainMember && mainMember.name) || "",
+        relation: (mainMember && mainMember.relation) || "",
+        idcard: (mainMember && mainMember.idcard) || "",
+        phone: (mainMember && mainMember.phone) || "",
+        address: this.normalizeAddress(mainMember && mainMember.address),
+        currentResidence: this.normalizeAddress(
+          mainMember && mainMember.currentResidence
+        ),
+        isMain: true
+      });
+
+      // 鍏朵粬浜插睘锛堝鍚嶆潵鑷� JSON锛屽叧绯绘寜 kinship 鍕鹃�夌敓鎴愶級
+      // 鍘嗗彶鑴忔暟鎹殑琛屾病鏈� isMain / seq / 浣忓潃瀛楁锛岃繖閲岀粺涓�琛ラ綈榛樿鍊�
+      (parsedMembers || []).forEach((member, idx) => {
+        if (!member) return;
+        if (idx === mainIndex) return;
+        if (member.isMain === true) return;
+        this.familyMemberList.push({
+          relation: member.relation != null ? String(member.relation) : "",
+          seq: member.seq != null ? member.seq : 0,
+          name: member.name || "",
+          phone: member.phone || "",
+          idcard: member.idcard || "",
+          address: this.normalizeAddress(member.address),
+          currentResidence: this.normalizeAddress(member.currentResidence),
+          isMain: false
+        });
+      });
+
+      // 瀛楀吀鑻ュ凡缂撳瓨锛寃atch 涓嶄細瑙﹀彂锛岃繖閲屼富鍔ㄦ妸鍕鹃�夊�煎綊涓�鍖栦竴娆�
+      this.form.kinship = this.normalizeKinshipValues(this.form.kinship || []);
+
+      // 鏍规嵁 kinship 鍕鹃�夎嚜鍔ㄧ敓鎴愪翰灞炶〃琛岋紙淇濈暀宸叉湁濮撳悕锛�
+      this.kinshipHydrated = true;
+      this.syncKinshipRelatives();
+
       if (detailData.organdecision) {
         this.organdecision = Array.isArray(detailData.organdecision)
           ? detailData.organdecision
           : detailData.organdecision.split(",");
       }
-      console.log(this.organdecision, "this.organdecision");
+      this.organdecisionOther = detailData.organdecisionOther || "";
 
-      // 澶勭悊闄勪欢鏁版嵁 - 浠巃ssessannex瀛楁瑙f瀽JSON骞舵寜绫诲瀷鍒嗙被
       this.processAssessannexData();
+
+      // 璋冭瘯鐢細纭 kinship / 瀛愬コ鏁伴噺 / 浜插睘澶у瓧娈� 鏄惁閮藉洖鏉ヤ簡
+      console.log("[affirmInfo] 浜插睘鍏崇郴鍥炴樉", {
+        kinship: this.form.kinship,
+        kinshipChildrennum: this.form.kinshipChildrennum,
+        otherFamilyMembers: this.form.otherFamilyMembers
+      });
     },
 
-    // 澶勭悊assessannex瀛楁鏁版嵁骞舵寜绫诲瀷鍒嗙被
-    processAssessannexData() {
-      if (this.form.assessannex) {
-        try {
-          const annexData =
-            typeof this.form.assessannex === "string"
-              ? JSON.parse(this.form.assessannex)
-              : this.form.assessannex;
-
-          // 娓呯┖鐜版湁鏁版嵁
-          Object.keys(this.attachmentData).forEach(key => {
-            this.attachmentData[key] = [];
-          });
-
-          // 鎸夌被鍨嬪垎绫诲瓨鍌�
-          if (Array.isArray(annexData)) {
-            annexData.forEach(attachment => {
-              const type = attachment.type || "1"; // 榛樿鍒扮涓�绉嶇被鍨�
-              if (this.attachmentData[type]) {
-                this.attachmentData[type].push(attachment);
-              }
-            });
-          }
-        } catch (error) {
-          console.warn("assessannex鏁版嵁瑙f瀽澶辫触:", error);
+    // 鍔犺浇妗f琛ㄤ俊鎭紙浜轰綋鍣ㄥ畼鑾峰彇缁勭粐绛夊瓧娈靛睘浜庢。妗堣〃锛屼笉鍦ㄤ翰灞炵‘璁よ〃锛�
+    async loadArchiveInfo() {
+      if (!this.caseId) return;
+      try {
+        const caseRes = await getDonatebaseinfo(this.caseId);
+        if (caseRes.code === 200 && caseRes.data) {
+          this.archiveData = caseRes.data;
+          this.form.acquisitiontissuename =
+            caseRes.data.acquisitiontissuename || "";
         }
+      } catch (e) {
+        console.warn("鑾峰彇妗f琛ㄤ俊鎭け璐�:", e);
       }
     },
 
-    // 鏍规嵁绫诲瀷鑾峰彇闄勪欢鍒楄〃
-    getAttachmentsByType(type) {
-      return this.attachmentData[type] || [];
+    // 鐢ㄤ富閿簿纭媺鍙栧畬鏁磋褰曪紝琛ラ綈鍒楄〃鎺ュ彛鍙兘缂哄け鐨� kinship 瀛楁
+    async loadFullKinship() {
+      const rid = this.form.id || this.$route.query.id;
+      if (!rid) return;
+      try {
+        const res = await getRelativesconfirmation(rid);
+        const data = res && res.data;
+        if (!data) return;
+        let changed = false;
+        if (data.kinship != null && data.kinship !== "") {
+          const values = this.parseKinship(data.kinship);
+          // 鎺ュ彛杩斿洖鐨勭湡瀹炲�间紭鍏堜簬浠� otherFamilyMembers 鍙嶆帹鐨勫厹搴曞��
+          // 锛堝弽鎺ㄥ�煎彧鐢ㄤ簬瀛楁缂哄け鐨勬儏鍐碉紝灞炰簬闄嶇骇鐪熺浉婧愶級
+          if (
+            values.length &&
+            values.join(",") !== (this.form.kinship || []).join(",")
+          ) {
+            this.form.kinship = values;
+            changed = true;
+          }
+        }
+        if (
+          (this.form.kinshipChildrennum == null ||
+            this.form.kinshipChildrennum === "") &&
+          data.kinshipChildrennum != null
+        ) {
+          this.form.kinshipChildrennum = data.kinshipChildrennum;
+          changed = true;
+        }
+        if (changed) {
+          this.kinshipHydrated = true;
+          this.syncKinshipRelatives();
+        }
+      } catch (e) {
+        console.warn("鑾峰彇浜插睘纭瀹屾暣璁板綍澶辫触(getInfo):", e);
+      }
     },
 
-    // 鎵撳紑涓婁紶瀵硅瘽妗�
+    // 鎶婂凡淇濆瓨鐨勫嬀閫夊�兼槧灏勫埌褰撳墠瀛楀吀鐨� value锛堝吋瀹逛袱濂楀瓧鍏哥紪鐮佷笉涓�鑷达級
+    // 娉ㄦ剰锛氭槧灏勪笉鍒扮殑鍘嗗彶鑴忓�硷紙濡� relation="4"/"6"锛夊繀椤诲師鏍蜂繚鐣欙紝涓嶈兘涓㈠純锛�
+    // 瀛楀吀鏄紓姝ュ姞杞界殑锛岃嫢鍦ㄦ澶勮繃婊わ紝瀛楀吀涓�鍒颁綅灏变細鎶婂弽鎺ㄥ嚭鏉ョ殑鍕鹃�夋竻绌恒��
+    normalizeKinshipValues(values) {
+      const options = this.orderedKinshipOptions || [];
+      if (!options.length) return values;
+      const result = [];
+      (values || []).forEach(v => {
+        const mapped = this.toCurrentKinshipValue(v);
+        if (mapped !== "" && !result.includes(mapped)) result.push(mapped);
+      });
+      return result;
+    },
+
+    // 鍗曚釜鍏崇郴鍊� 鈫� 褰撳墠瀛楀吀浣撶郴涓嬬殑鍊�
+    // 鍛戒腑椤哄簭锛氬綋鍓嶅瓧鍏� value 鈫� 褰撳墠瀛楀吀鍚屽悕 label 鈫� 瀛愬コ绫诲綊涓�鍖栵紙瀛愬コ 鈬� 鎴愬勾瀛愬コ锛�
+    // 鍏ㄩ兘鍛戒腑涓嶄簡璇存槑鏄巻鍙茶剰鏁版嵁锛屽師鏍疯繑鍥烇紝淇濊瘉琛ㄦ牸琛屼笉涓€�佸嬀閫変笉琚姽鎺�
+    toCurrentKinshipValue(v) {
+      if (v == null || v === "") return "";
+      const options = this.orderedKinshipOptions || [];
+      if (!options.length) return String(v);
+      const raw = String(v);
+      if (options.some(o => String(o.value) === raw)) return raw;
+
+      const label = this.getKinshipLabel(raw);
+      if (!label || label === raw) return raw; // 涓変釜瀛楀吀閮芥煡涓嶅埌 鈫� 鑴忓�煎師鏍蜂繚鐣�
+
+      const sameLabel = options.find(o => o.label === label);
+      if (sameLabel) return String(sameLabel.value);
+
+      // 瀛愬コ绫诲叧绯诲湪涓嶅悓瀛楀吀閲屽彨娉曚笉鍚岋紙"瀛愬コ"/"鎴愬勾瀛愬コ"锛夛紝瑙嗕负鍚屼竴鍏崇郴
+      if (this.isChildLabel(label)) {
+        const exact = options.find(o => o.label === "鎴愬勾瀛愬コ");
+        if (exact) return String(exact.value);
+        const any = options.find(o => this.isChildLabel(o.label));
+        if (any) return String(any.value);
+      }
+      return raw;
+    },
+
+    // 瑙f瀽浜插睘鍏崇郴纭锛堝閫夛紝; 鎴� , 鍒嗛殧锛岀粺涓�杞负瀛楃涓叉暟缁勶級
+    parseKinship(val) {
+      if (!val) return [];
+      const arr = Array.isArray(val) ? val : String(val).split(/[;,]/);
+      return arr
+        .map(v => (v == null ? "" : String(v).trim()))
+        .filter(v => v !== "");
+    },
+
+    // 绛剧讲鏃ユ湡缁熶竴杞垚 yyyy-MM-dd锛屽吋瀹瑰悗绔繑鍥炵殑澶氱鏃ユ湡鏍煎紡
+    normalizeSigndate(val) {
+      if (!val) return null;
+      const m = String(val).match(/^(\d{4}-\d{2}-\d{2})/);
+      return m ? m[1] : null;
+    },
+
+    processAssessannexData() {
+      Object.keys(this.confirmAttachmentData).forEach(key => {
+        this.confirmAttachmentData[key] = [];
+      });
+      Object.keys(this.registerAttachmentData).forEach(key => {
+        this.registerAttachmentData[key] = [];
+      });
+      if (!this.form.assessannex) return;
+      try {
+        const annexData =
+          typeof this.form.assessannex === "string"
+            ? JSON.parse(this.form.assessannex)
+            : this.form.assessannex;
+        if (Array.isArray(annexData)) {
+          annexData.forEach(attachment => {
+            const type = String(attachment.type || "");
+            // 纭闃舵锛�2/3/4锛変笌鐧昏闃舵锛�1/5/6锛夊潎缁存姢鍦� assessannex
+            if (this.confirmAttachmentData[type]) {
+              this.confirmAttachmentData[type].push(attachment);
+            } else if (this.registerAttachmentData[type]) {
+              this.registerAttachmentData[type].push(attachment);
+            }
+          });
+        }
+      } catch (error) {
+        console.warn("assessannex鏁版嵁瑙f瀽澶辫触:", error);
+      }
+    },
+
+    getConfirmAttachments(type) {
+      return this.confirmAttachmentData[type] || [];
+    },
+
+    getRegisterAttachments(type) {
+      return this.registerAttachmentData[type] || [];
+    },
+
     openUploadDialog(type) {
       this.currentUploadType = type;
       this.tempFileList = [];
@@ -538,7 +1157,6 @@
       });
     },
 
-    // 涓婁紶鍓嶆牎楠孾7](@ref)
     beforeUpload(file) {
       const allowedTypes = [
         "application/pdf",
@@ -547,10 +1165,7 @@
         "application/msword",
         "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
       ];
-
-      const maxSize = 10 * 1024 * 1024; // 10MB
-
-      // 鏍¢獙鏂囦欢绫诲瀷
+      const maxSize = 10 * 1024 * 1024;
       const isTypeOk =
         allowedTypes.includes(file.type) ||
         file.name.endsWith(".pdf") ||
@@ -559,85 +1174,64 @@
         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;
     },
 
-    // 鑷畾涔変笂浼犺姹�
-    handleHttpRequest(options) {
-      return new Promise((resolve, reject) => {
-        this.uploadLoading = true;
+    handleUploadSuccess(response, file) {
+      if (response.code !== 200) {
+        this.$message.error(response.msg || "涓婁紶澶辫触");
+        return;
+      }
+      const newAttachment = {
+        id: Date.now(),
+        fileName: file.name,
+        fileUrl: response.url,
+        fileSize: file.size,
+        fileType: this.getFileExtension(file.name),
+        type: this.currentUploadType,
+        uploadTime: this.getCurrentTime(),
+        uploader: "褰撳墠鐢ㄦ埛"
+      };
+      if (this.confirmAttachmentData[this.currentUploadType]) {
+        this.confirmAttachmentData[this.currentUploadType].push(newAttachment);
+      } else if (this.registerAttachmentData[this.currentUploadType]) {
+        this.registerAttachmentData[this.currentUploadType].push(newAttachment);
+      }
 
-        // 妯℃嫙涓婁紶杩囩▼
-        setTimeout(() => {
-          const newAttachment = {
-            id: Date.now(),
-            fileName: options.file.name,
-            fileUrl: URL.createObjectURL(options.file),
-            fileSize: options.file.size,
-            fileType: this.getFileExtension(options.file.name),
-            type: this.currentUploadType, // 璁板綍闄勪欢绫诲瀷
-            uploadTime: new Date().toISOString(),
-            uploader: "褰撳墠鐢ㄦ埛"
-          };
-
-          // 娣诲姞鍒板搴旂被鍨嬬殑闄勪欢鍒楄〃
-          if (this.attachmentData[this.currentUploadType]) {
-            this.attachmentData[this.currentUploadType].push(newAttachment);
-          }
-
-          this.uploadLoading = false;
-          this.updateAssessannexField(); // 鏇存柊瀛樺偍瀛楁
-          resolve({ code: 200, data: newAttachment });
-        }, 1500);
-      });
+      this.updateAssessannexField();
+      this.$message.success("涓婁紶鎴愬姛");
+      this.uploadLoading = false;
+      this.uploadDialogVisible = false;
+      this.tempFileList = [];
     },
 
-    // 鎻愪氦涓婁紶
-    async submitUpload() {
+    submitUpload() {
       if (this.tempFileList.length === 0) {
         this.$message.warning("璇峰厛閫夋嫨瑕佷笂浼犵殑鏂囦欢");
         return;
       }
-
-      try {
-        for (const file of this.tempFileList) {
-          await this.$refs.uploadRef.submit();
-        }
-
-        this.$message.success("鏂囦欢涓婁紶鎴愬姛");
-        this.uploadDialogVisible = false;
-        this.tempFileList = [];
-      } catch (error) {
-        this.$message.error("鏂囦欢涓婁紶澶辫触");
-        console.error("涓婁紶澶辫触:", error);
-      }
+      this.uploadLoading = true;
+      this.$refs.uploadRef.submit();
     },
 
-    // 鍒犻櫎闄勪欢
     handleRemoveAttachment(type, index) {
       this.$confirm("纭畾瑕佸垹闄よ繖涓檮浠跺悧锛�", "鎻愮ず", {
         confirmButtonText: "纭畾",
@@ -645,28 +1239,292 @@
         type: "warning"
       })
         .then(() => {
-          if (this.attachmentData[type] && this.attachmentData[type][index]) {
-            this.attachmentData[type].splice(index, 1);
+          const container =
+            this.confirmAttachmentData[type] || this.registerAttachmentData[type];
+          if (container && container[index]) {
+            container.splice(index, 1);
             this.$message.success("闄勪欢鍒犻櫎鎴愬姛");
-            this.updateAssessannexField(); // 鏇存柊瀛樺偍瀛楁
+            this.updateAssessannexField();
           }
         })
         .catch(() => {});
     },
 
-    // 鏇存柊assessannex瀛樺偍瀛楁
-    updateAssessannexField() {
-      // 灏嗘墍鏈夌被鍨嬬殑闄勪欢鍚堝苟涓轰竴涓暟缁�
-      const allAttachments = [];
-      Object.values(this.attachmentData).forEach(attachments => {
-        allAttachments.push(...attachments);
+    // 鏍规嵁 kinship 鍕鹃�夎嚜鍔ㄧ敓鎴愪翰灞炶〃琛岋紝鍚屾椂淇濈暀宸叉湁浜插睘鏁版嵁锛堝悎骞讹紝閬垮厤涓㈠け锛�
+    syncKinshipRelatives() {
+      // 鍕鹃�夊�肩粺涓�鏄犲皠鍒板綋鍓嶅瓧鍏镐綋绯伙紝淇濊瘉涓庤〃鏍艰鐨� relation 澶勫湪鍚屼竴鍊煎煙銆�
+      // 蹇呴』鍘婚噸锛氬巻鍙茶剰鏁版嵁閲屽涓笉鍚岀紪鐮侊紙濡� "4"銆�"6"锛夊彲鑳芥槧灏勬垚鍚屼竴涓� value锛�
+      // 涓嶅幓閲嶇殑璇濇瘡涓噸澶嶅�奸兘浼氬啀鐢熸垚涓�閬嶈锛岃〃鐜板氨鏄�"琛屾暟鎴愬�嶅彉澶�"銆�
+      const kinship = Array.from(
+        new Set(
+          (this.form.kinship || [])
+            .map(v => this.toCurrentKinshipValue(v))
+            .filter(v => v !== "")
+        )
+      );
+      const adultChildValue = this.findAdultChildValue();
+
+      // 宸叉湁浜插睘锛堥潪涓昏浜插睘锛夛紝淇濈暀濮撳悕涓庡叧绯伙紱鍏崇郴鍊肩粺涓�鏄犲皠鍒板綋鍓嶅瓧鍏镐綋绯�
+      const existing = this.familyMemberList
+        .slice(1)
+        .filter(m => m && !m.isMain)
+        .map(m => ({ ...m, relation: this.toCurrentKinshipValue(m.relation) }));
+
+      // 瀛愬コ鏁伴噺锛氭帴鍙e彲鑳戒笉杩斿洖璇ュ瓧娈�
+      // 鍥炴樉鏃剁敤宸叉湁瀛愬コ琛屾暟鍏滃簳锛涚敤鎴蜂富鍔ㄦ竻绌猴紙""锛夊垯涓嶅厹搴曪紝琛岀収甯告竻鎺�
+      const existingChildCount = adultChildValue
+        ? existing.filter(e => e.relation === adultChildValue).length
+        : 0;
+      const rawCountStr = this.form.kinshipChildrennum;
+      // null / "" / 鏁板瓧 0 閮借涓�"娌″~鏁伴噺"锛堢湡瑕� 0 涓紝鍙栨秷鍕鹃�夊嵆鍙級
+      const rawMissing =
+        rawCountStr == null || rawCountStr === "" || rawCountStr === 0;
+      let childCount;
+      if (rawMissing) {
+        childCount = this.kinshipHydrated ? existingChildCount : 0;
+        // 鍥炴樉鍏滃簳锛氭妸鎺ㄧ畻鍑虹殑鏁伴噺鍐欏洖琛ㄥ崟锛屽惁鍒欐暟閲忔绌虹櫧銆佷繚瀛樻椂鍙堜涪
+        // 锛堢▼搴忚祴鍊间笉浼氳Е鍙� el-input 鐨� @input锛屼笉浼氬舰鎴愬惊鐜級
+        if (this.kinshipHydrated && existingChildCount > 0) {
+          this.form.kinshipChildrennum = String(existingChildCount);
+        }
+      } else {
+        const n = parseInt(rawCountStr, 10);
+        childCount = isNaN(n) || n < 0 ? 0 : n;
+      }
+
+      // 鍙栦竴琛屽凡鏈夋暟鎹鐢ㄥ鍚嶏細鍏堟寜 鍏崇郴+搴忓彿 绮剧‘鍖归厤锛屽啀閫�鍖栦负鍚屽叧绯婚『搴忓彇
+      const used = new Set();
+      const takeExisting = (relation, seq) => {
+        let idx = existing.findIndex(
+          (e, i) =>
+            !used.has(i) && e.relation === relation && (e.seq || 0) === seq
+        );
+        if (idx === -1) {
+          idx = existing.findIndex(
+            (e, i) => !used.has(i) && e.relation === relation
+          );
+        }
+        if (idx === -1) return null;
+        used.add(idx);
+        return existing[idx];
+      };
+
+      // 鐢熸垚涓�琛岋細鍛戒腑宸叉湁琛屾椂鏁磋澶嶇敤锛堝惈 phone/idcard/浣忓潃绛夛級锛�
+      // 鍘嗗彶鑴忔暟鎹噷杩欎簺瀛楁鍙兘鏈夊�硷紝閲嶅缓鏃朵笉鑳藉彧淇濈暀 relation/name 鎶婂叾浣欐姽鎺�
+      const buildRow = (relation, seq, hit) => ({
+        relation: relation,
+        seq: seq,
+        name: (hit && hit.name) || "",
+        phone: (hit && hit.phone) || "",
+        idcard: (hit && hit.idcard) || "",
+        address: this.normalizeAddress(hit && hit.address),
+        currentResidence: this.normalizeAddress(hit && hit.currentResidence),
+        isMain: false
       });
 
-      // 鏇存柊鍒拌〃鍗曞瓧娈�
+      const merged = [];
+      kinship.forEach(rel => {
+        if (adultChildValue && rel === adultChildValue) {
+          // 鎴愬勾瀛愬コ锛氬瓙濂虫暟閲忓喅瀹氳鏁�
+          for (let i = 0; i < childCount; i++) {
+            const hit = takeExisting(rel, i);
+            merged.push(buildRow(rel, i, hit));
+          }
+        } else {
+          const hit = takeExisting(rel, 0);
+          merged.push(buildRow(rel, 0, hit));
+        }
+      });
+
+      // 鏈鍕鹃�夊懡涓殑宸叉湁浜插睘涓�寰嬩繚鐣欍��
+      // 涓嶈兘鎸夊叧绯诲幓閲嶏細鍘嗗彶鏁版嵁閲�"涓や釜鍏勫紵濮愬"杩欑被鍚屽叧绯诲琛屾槸鍚堟硶鐨勶紝
+      // 鍘婚噸浼氶潤榛樹涪浜恒�備箣鍓嶅嚭鐜�"鍚屽叧绯婚噸澶嶈"鐨勬牴鍥犳槸 takeExisting 娌″懡涓紝
+      // 鐜板湪 used 淇濊瘉姣忎釜宸叉湁琛屾渶澶氳娑堣�椾竴娆★紝涓嶄細閲嶅鐢熸垚銆�
+      existing.forEach((e, idx) => {
+        if (used.has(idx)) return;
+        // 瀛愬コ琛屾暟鐢卞瓙濂虫暟閲忓喅瀹氾紝澶氫綑鐨勫瓙濂宠涓嶄繚鐣�
+        if (adultChildValue && e.relation === adultChildValue) return;
+        merged.push(buildRow(e.relation || "", e.seq != null ? e.seq : 0, e));
+      });
+
+      this.familyMemberList = [this.familyMemberList[0], ...merged];
+      this.updateFamilyMemberField();
+      // 鍏滃簳鍙湪鍥炴樉閭d竴娆$敓鏁�
+      this.kinshipHydrated = false;
+    },
+
+    // 鍒犻櫎浜插睘琛ㄦ煇涓�琛岋紝骞跺悓姝ュ彇娑堜笂鏂瑰搴旂殑鍏崇郴鍕鹃��
+    handleDeleteFamilyRow(index) {
+      const rowIndex = index + 1; // otherFamilyMemberList = familyMemberList.slice(1)
+      const row = this.familyMemberList[rowIndex];
+      if (!row) return;
+      if (row.isMain) return;
+
+      const relation = row.relation
+        ? this.toCurrentKinshipValue(row.relation)
+        : "";
+      const adultChildValue = this.findAdultChildValue();
+      const isChild = !!adultChildValue && relation === adultChildValue;
+
+      // 鍕鹃�夐噷瀛樼殑鍙兘鏄巻鍙茬紪鐮侊紙濡� "4"锛夎�屼笉鏄槧灏勫悗鐨勫�硷紙濡� "2"锛夛紝
+      // 鍙栨秷鍕鹃�夋椂涓ょ閮借姣斿锛屽惁鍒欎細鍑虹幇"琛屽垹浜嗕絾鍕鹃�夎繕鍦�"
+      const removeKinship = target => {
+        const mapped = this.toCurrentKinshipValue(target);
+        this.form.kinship = (this.form.kinship || []).filter(
+          v =>
+            String(v) !== String(target) &&
+            this.toCurrentKinshipValue(v) !== mapped
+        );
+      };
+
+      console.log("[affirmInfo] 鍒犻櫎浜插睘琛�", {
+        index,
+        relation,
+        adultChildValue,
+        isChild,
+        before: this.familyMemberList.slice(1).map(m => m.relation),
+        kinship: this.form.kinship
+      });
+
+      if (isChild) {
+        // 鎴愬勾瀛愬コ锛氱洿鎺ュ垹杩欎竴琛岋紝鏁伴噺鎸夊墿浣欏瓙濂宠鏁伴噸绠楋紝褰掗浂鎵嶅彇娑堝嬀閫�
+        this.familyMemberList.splice(rowIndex, 1);
+        const rest = this.familyMemberList.filter(
+          (m, i) =>
+            i > 0 &&
+            !m.isMain &&
+            this.toCurrentKinshipValue(m.relation) === adultChildValue
+        ).length;
+        if (rest > 0) {
+          this.form.kinshipChildrennum = String(rest);
+        } else {
+          this.form.kinshipChildrennum = "";
+          removeKinship(adultChildValue);
+        }
+      } else if (relation) {
+        // 鍏朵綑鍏崇郴锛氫竴琛屽搴斾竴涓嬀閫夛紝鍙栨秷鍕鹃�夊苟鏁寸粍娓呮帀
+        removeKinship(relation);
+        this.familyMemberList = this.familyMemberList.filter(
+          (m, i) =>
+            i === 0 ||
+            m.isMain ||
+            this.toCurrentKinshipValue(m.relation) !== relation
+        );
+      } else {
+        // 鍏崇郴涓虹┖鐨勫巻鍙查仐鐣欒锛屽彧鍒犺繖涓�琛�
+        this.familyMemberList.splice(rowIndex, 1);
+      }
+
+      // 鐩存帴鍥炲啓澶у瓧娈点�備笉璋冪敤 syncKinshipRelatives锛岄伩鍏嶈琚寜鍕鹃�夐噸鏂扮敓鎴愬洖鏉�
+      this.updateFamilyMemberField();
+
+      if (relation) {
+        this.$message.success(
+          `宸茬Щ闄ゃ��${this.getKinshipLabel(relation)}銆嶅苟鍚屾鍙栨秷鍕鹃�塦
+        );
+      }
+    },
+
+    getKinshipLabel(value) {
+      if (value == null || value === "") return "";
+      const dictLists = [
+        this.dict.type.sys_KinshipConfirm,
+        this.dict.type.sys_Kinship,
+        this.dict.type.sys_FamilyRelation
+      ];
+      for (const list of dictLists) {
+        const dict = (list || []).find(d => String(d.value) === String(value));
+        if (dict) return dict.label;
+      }
+      // 涓変釜瀛楀吀閮芥煡涓嶅埌 鈫� 鑰佺紪鐮�/鑴忔暟鎹紝鎸夊師鍊煎睍绀猴紝骞惰褰曚竴娆′究浜庢帓鏌�
+      if (!this._warnedKinshipValues) this._warnedKinshipValues = new Set();
+      const key = String(value);
+      if (!this._warnedKinshipValues.has(key)) {
+        this._warnedKinshipValues.add(key);
+        console.warn(
+          `[affirmInfo] 浜插睘鍏崇郴缂栫爜銆�${key}銆嶅湪 sys_KinshipConfirm / sys_Kinship / sys_FamilyRelation 涓潎涓嶅瓨鍦紝鎸夊師鍊煎睍绀篳
+        );
+      }
+      return value;
+    },
+
+    isChildLabel(label) {
+      return label === "瀛愬コ" || label === "鎴愬勾瀛愬コ";
+    },
+
+    findAdultChildValue() {
+      const list = this.kinshipDictOptions || [];
+      // 浼樺厛绮剧‘鍖归厤"鎴愬勾瀛愬コ"锛岄伩鍏嶆妸"瀛愬コ"褰撴垚鎴愬勾瀛愬コ澶勭悊
+      const exact = list.find(d => d.label === "鎴愬勾瀛愬コ");
+      if (exact) return String(exact.value);
+      const any = list.find(d => this.isChildLabel(d.label));
+      return any ? String(any.value) : null;
+    },
+
+    formatAddress(addr) {
+      if (!addr) return "";
+      if (typeof addr === "string") return addr;
+      return [addr.sheng, addr.shi, addr.qu, addr.detail]
+        .filter(p => p)
+        .join("");
+    },
+
+    normalizeAddress(addr) {
+      if (!addr) {
+        return { sheng: "", shi: "", qu: "", detail: "" };
+      }
+      if (typeof addr === "string") {
+        return { sheng: "", shi: "", qu: "", detail: addr };
+      }
+      return {
+        sheng: (addr && addr.sheng) || "",
+        shi: (addr && addr.shi) || "",
+        qu: (addr && addr.qu) || "",
+        detail: (addr && addr.detail) || ""
+      };
+    },
+
+    updateFamilyMemberField() {
+      const mainMember = this.familyMemberList[0];
+      if (mainMember) {
+        this.form.relativeconfirmationsignname = mainMember.name || "";
+        this.form.signfamilyrelations = mainMember.relation || "";
+        this.form.relativeidcardno = mainMember.idcard || "";
+        this.form.phone = mainMember.phone || "";
+        this.form.relativephone = mainMember.phone || "";
+      } else {
+        this.form.relativeconfirmationsignname = "";
+        this.form.signfamilyrelations = "";
+        this.form.relativeidcardno = "";
+        this.form.phone = "";
+        this.form.relativephone = "";
+      }
+
+      // 鎵�鏈変翰灞烇紙鍚富瑕佷翰灞烇級缁熶竴瀛樺叆涓�涓� JSON 澶у瓧娈碉紝浣忓潃/鐜板眳浣忓湴涔熷瓨杩欓噷
+      const allMembers = this.familyMemberList.map((member, index) => ({
+        name: member.name || "",
+        relation: member.relation || "",
+        idcard: member.idcard || "",
+        phone: member.phone || "",
+        address: member.address || "",
+        currentResidence: member.currentResidence || "",
+        seq: member.seq != null ? member.seq : 0,
+        isMain: index === 0
+      }));
+      this.form.otherFamilyMembers = JSON.stringify(allMembers);
+    },
+
+    updateAssessannexField() {
+      const allAttachments = [];
+      [
+        ...Object.values(this.confirmAttachmentData),
+        ...Object.values(this.registerAttachmentData)
+      ].forEach(attachments => {
+        allAttachments.push(...attachments);
+      });
       this.form.assessannex = JSON.stringify(allAttachments);
     },
 
-    // 鏂囦欢棰勮
     handlePreview(file) {
       this.currentPreviewFile = {
         fileName: file.fileName,
@@ -676,11 +1534,9 @@
       this.previewVisible = true;
     },
 
-    // 鏂囦欢涓嬭浇
     handleDownload(file) {
       const fileUrl = file.fileUrl;
       const fileName = file.fileName;
-
       if (fileUrl) {
         const link = document.createElement("a");
         link.href = fileUrl;
@@ -695,21 +1551,18 @@
       }
     },
 
-    // 鑾峰彇鏂囦欢绫诲瀷
     getFileType(fileName) {
       if (!fileName) return "other";
       const extension = this.getFileExtension(fileName);
       const imageTypes = ["jpg", "jpeg", "png"];
       const pdfTypes = ["pdf"];
       const officeTypes = ["doc", "docx"];
-
       if (imageTypes.includes(extension)) return "image";
       if (pdfTypes.includes(extension)) return "pdf";
       if (officeTypes.includes(extension)) return "office";
       return "other";
     },
 
-    // 鑾峰彇鏂囦欢鎵╁睍鍚�
     getFileExtension(filename) {
       return filename
         .split(".")
@@ -717,7 +1570,6 @@
         .toLowerCase();
     },
 
-    // 鏂囦欢澶у皬鏍煎紡鍖�
     formatFileSize(size) {
       if (!size) return "0 B";
       const k = 1024;
@@ -726,26 +1578,22 @@
       return parseFloat((size / 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;
       }
     },
 
-    // 鑾峰彇褰撳墠鏃堕棿
     getCurrentTime() {
       const now = new Date();
       return `${now.getFullYear()}-${(now.getMonth() + 1)
@@ -764,6 +1612,7 @@
         .toString()
         .padStart(2, "0")}`;
     },
+
     accomplish() {
       this.$confirm("鏄惁瀹屾垚璇ユ渚嬫崘鐚‘璁ゆ楠わ紵", "鎻愰啋", {
         confirmButtonText: "纭畾",
@@ -774,29 +1623,44 @@
           this.form.state = 3;
           this.handleSave();
         })
-
         .catch(() => {});
     },
 
-    // 淇濆瓨纭淇℃伅
     async handleSave() {
+      if (this.saveLoading) return;
       try {
         await this.$refs.form.validate();
         this.saveLoading = true;
 
-        // 纭繚闄勪欢鏁版嵁鏄渶鏂扮殑
+        this.updateFamilyMemberField();
         this.updateAssessannexField();
 
         const saveData = {
           ...this.form,
           infoid: this.infoid,
           organdecision: this.organdecision.join(","),
-          organdecisionOther: this.organdecisionOther
-          // assessannex瀛楁宸插湪updateAssessannexField涓洿鏂�
+          organdecisionOther: this.organdecisionOther,
+          kinship: (this.form.kinship || []).join(",")
         };
+        // 浜轰綋鍣ㄥ畼鑾峰彇缁勭粐灞炰簬妗f琛ㄥ瓧娈碉紝涓嶉殢浜插睘纭琛ㄤ繚瀛�
+        delete saveData.acquisitiontissuename;
+        // 绛剧讲鏃ユ湡涓虹┖鏃朵笉鎻愪氦锛岄伩鍏嶅悗绔� Date 鍙嶅簭鍒楀寲鎶ラ敊
+        if (!saveData.signdate) {
+          delete saveData.signdate;
+        }
         if (saveData.state == 1 || !saveData.state) {
           saveData.state = 2;
         }
+
+        // 鏂板鏃舵牎楠屾槸鍚﹀凡鏈夌浉鍚屾偅鑰�
+        if (!saveData.id) {
+          const exists = await this.checkPatientExists();
+          if (exists) {
+            this.$message.warning("璇ユ偅鑰呭凡瀛樺湪锛岃鍕块噸澶嶆坊鍔�");
+            return;
+          }
+        }
+
         let response = null;
         if (saveData.id) {
           response = await relativesEdit(saveData);
@@ -805,6 +1669,8 @@
         }
 
         if (response.code === 200) {
+          // 浜轰綋鍣ㄥ畼鑾峰彇缁勭粐鍗曠嫭淇濆瓨鍒版。妗堣〃
+          await this.saveArchiveAcquisitionTissue();
           this.$message.success("淇濆瓨鎴愬姛");
           this.$router.push("/case/affirm");
         } else {
@@ -818,6 +1684,45 @@
       } finally {
         this.saveLoading = false;
       }
+    },
+    // 淇濆瓨妗f琛ㄧ殑浜轰綋鍣ㄥ畼鑾峰彇缁勭粐瀛楁
+    async saveArchiveAcquisitionTissue() {
+      if (!this.caseId) return;
+      try {
+        const payload = {
+          ...(this.archiveData || {}),
+          id: this.caseId,
+          acquisitiontissuename: this.form.acquisitiontissuename
+        };
+        await updateDonatebaseinfo(payload);
+      } catch (e) {
+        console.warn("淇濆瓨妗f琛ㄤ汉浣撳櫒瀹樿幏鍙栫粍缁囧け璐�:", e);
+      }
+    },
+
+    // 鏂板鏃舵牎楠屾槸鍚﹀凡鏈夌浉鍚屾偅鑰咃紙鎸変綇闄㈠彿锛�
+    async checkPatientExists() {
+      let inpatientno = this.form.inpatientno;
+      if (!inpatientno && this.caseId) {
+        try {
+          const caseRes = await getDonatebaseinfo(this.caseId);
+          inpatientno = (caseRes.data && caseRes.data.inpatientno) || "";
+        } catch (e) {
+          inpatientno = "";
+        }
+      }
+      if (!inpatientno) return false;
+      try {
+        const res = await relativesList({
+          inpatientno,
+          pageNum: 1,
+          pageSize: 1
+        });
+        const list = res.data || [];
+        return list.some(item => item && item.id != null && item.id !== "");
+      } catch (e) {
+        return false;
+      }
     }
   }
 };
@@ -830,6 +1735,11 @@
 
 .detail-card {
   margin-bottom: 20px;
+}
+
+.main-family {
+  font-weight: bold;
+  color: #e6a23c;
 }
 
 .attachment-card {
@@ -867,7 +1777,7 @@
 
 .empty-attachment {
   text-align: center;
-  padding: 40px 0;
+  padding: 30px 0;
   color: #909399;
 }
 
@@ -875,4 +1785,147 @@
   font-size: 13px;
   color: #606266;
 }
+
+/* ===== 绾歌川琛ㄦ牸缃戞牸鏍峰紡 ===== */
+.paper-card >>> .el-card__body {
+  padding: 16px;
+}
+
+.paper-form {
+  border-left: 1px solid #d0d3db;
+  background: #fff;
+}
+
+.paper-form >>> .form-row {
+  display: flex;
+  width: 100%;
+  border-top: 1px solid #d0d3db;
+  /* 涓婄Щ1px涓庝笂涓�琛岀殑border-bottom閲嶅彔锛屼袱琛屼箣闂村彧鏄剧ず涓�鏉�1px缁嗙嚎 */
+  margin-top: -1px;
+}
+.paper-form >>> .form-row:first-child {
+  margin-top: 0;
+}
+
+/* 琛屽熬绌虹櫧濉厖锛氫笉婊℃暣琛岀殑鍙充晶鑷姩琛ヤ竴涓┖鐧芥牸瀛愶紝缃戞牸淇濇寔闂悎锛堝彸渚ч�傚綋鐣欑櫧锛� */
+.paper-form >>> .form-row::after {
+  content: "";
+  flex: 1 1 0;
+  min-height: 42px;
+  background: linear-gradient(to left, #d0d3db 1px, transparent 1px),
+    linear-gradient(to top, #d0d3db 1px, transparent 1px);
+  background-color: #fff;
+}
+
+.paper-form >>> .el-form-item {
+  flex: 0 0 33.3333%;
+  display: flex;
+  margin: 0;
+  background: #fff;
+  border-right: 1px solid #d0d3db;
+  border-bottom: 1px solid #d0d3db;
+}
+.paper-form >>> .el-form-item::after,
+.paper-form >>> .el-form-item::before {
+  display: none;
+}
+
+.paper-form >>> .col-1-3 {
+  flex: 0 0 33.3333%;
+}
+.paper-form >>> .col-half {
+  flex: 0 0 50%;
+}
+.paper-form >>> .col-2-3 {
+  flex: 0 0 66.6666%;
+}
+.paper-form >>> .col-full {
+  flex: 0 0 100%;
+}
+
+.paper-form >>> .el-form-item__label {
+  flex: 0 0 150px;
+  width: 150px !important;
+  float: none;
+  padding: 0 8px !important;
+  background: #ecf5ff;
+  border-right: 1px solid #d0d3db;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  text-align: center;
+  font-size: 13px;
+  font-weight: 600;
+  color: #2c3038;
+  line-height: 1.3;
+  white-space: nowrap;
+}
+.paper-form
+  >>> .el-form-item.is-required:not(.is-no-asterisk)
+  > .el-form-item__label:before {
+  color: #f56c6c;
+  margin-right: 2px;
+}
+
+.paper-form >>> .el-form-item__content {
+  flex: 1;
+  margin-left: 0 !important;
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  padding: 6px 10px;
+  background: #fff;
+  min-height: 42px;
+  line-height: 1.4;
+}
+
+/* 鎺т欢瀹藉害閫備腑锛屼笉閾烘弧鏁存牸锛堝唴瀹圭煭鏃惰緭鍏ユ涓嶅啀鎷夊緱寰堥暱锛夛紱绐勫睆鏃惰嚜鍔ㄦ敹缂╅伩鍏嶆孩鍑� */
+.paper-form >>> .el-form-item__content .el-input,
+.paper-form >>> .el-form-item__content .el-select,
+.paper-form >>> .el-form-item__content .el-cascader {
+  width: 100%;
+  max-width: 220px;
+}
+.paper-form >>> .el-form-item__content .el-date-editor {
+  width: 100%;
+  max-width: 240px;
+}
+.paper-form >>> .el-form-item__content .el-range-editor {
+  width: 360px;
+  max-width: 100%;
+}
+
+/* 鍦板潃閫夋嫨鍣紙鐪佸競鍖轰笁绾ц仈鍔� + 璇︾粏鍦板潃锛岃缁嗗湴鍧�鍒嗚鏄剧ず锛� */
+.paper-form >>> .area-select-box {
+  flex: 0 0 auto;
+  width: 480px;
+  max-width: 100%;
+}
+.paper-form >>> .address-detail {
+  flex: 0 0 100%;
+  width: 100% !important;
+  margin: 6px 0 0 0;
+}
+
+/* 鎹愮尞鍐冲畾璇彞鎺掔増 */
+.paper-form >>> .decision-statement {
+  flex: 0 0 100%;
+  width: 100%;
+  line-height: 1.8;
+  font-size: 13px;
+  color: #303133;
+  padding: 2px 0;
+}
+.paper-form >>> .decision-other {
+  width: 320px !important;
+  margin-left: 8px;
+}
+.paper-form >>> .decision-selected {
+  flex: 0 0 100%;
+  width: 100%;
+  line-height: 1.8;
+  font-size: 13px;
+  color: #303133;
+  padding: 2px 0;
+}
 </style>

--
Gitblit v1.9.3