| | |
| | | <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" |
| | |
| | | /> |
| | | </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> --> |
| | | |
| | | <!-- 人体器官获取组织与负责人签字 --> |
| | | <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="请输入负责人签字" |
| | | /> |
| | | </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" |
| | |
| | | <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" |
| | |
| | | </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%;" |
| | |
| | | </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) |
| | |
| | | </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" |
| | |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | v-if="!isReadOnly" |
| | | size="mini" |
| | | type="danger" |
| | | @click="handleRemoveAttachment(type.value, scope.$index)" |
| | |
| | | </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 |
| | |
| | | </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> |
| | |
| | | </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, |
| | |
| | | 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: "捐献者及直系亲属身份证、户口簿相关证明" }, |
| | | { 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() { |
| | |
| | | } |
| | | }, |
| | | 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 || "未知错误")); |
| | | } |
| | |
| | | } |
| | | }, |
| | | |
| | | // 处理详情数据 |
| | | handleDetailData(response) { |
| | | handleDetailData(response, fullRecord) { |
| | | let detailData = null; |
| | | |
| | | // 根据接口实际返回的数据结构进行调整 |
| | | if (response.data) { |
| | | if (Array.isArray(response.data)) { |
| | | detailData = response.data[0] || {}; |
| | |
| | | } 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("解析其他家属数据失败:", 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 || "", |
| | |
| | | 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); |
| | | // 命中项在解析数组中的位置;-1 表示主亲属不来自 otherFamilyMembers |
| | | let mainIndex = mainMember ? parsedMembers.indexOf(mainMember) : -1; |
| | | if (!mainMember) { |
| | | const hasMain = |
| | | detailData.relativeconfirmationsignname || |
| | | detailData.signfamilyrelations || |
| | | detailData.relativeidcardno; |
| | | if (hasMain) { |
| | | // 老格式:主亲属存在专用字段里,otherFamilyMembers 只存"其他亲属" |
| | | mainMember = { |
| | | name: detailData.relativeconfirmationsignname || "", |
| | | relation: detailData.signfamilyrelations || "", |
| | | idcard: detailData.relativeidcardno || "", |
| | | phone: detailData.phone || detailData.relativephone || "", |
| | | address: "", |
| | | currentResidence: "", |
| | | isMain: true |
| | | }; |
| | | } else if (parsedMembers.length) { |
| | | // 脏数据兜底:主亲属专用字段全空、JSON 里也没有 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 |
| | | }); |
| | | }); |
| | | |
| | | // 字典若已缓存,watch 不会触发,这里主动把勾选值归一化一次 |
| | | 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 || ""; |
| | | |
| | | // 处理附件数据 - 从assessannex字段解析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数据解析失败:", error); |
| | | // 加载档案表信息(人体器官获取组织等字段属于档案表,不在亲属确认表) |
| | | 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("获取档案表信息失败:", 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; |
| | | }, |
| | | |
| | | // 解析亲属关系确认(多选,; 或 , 分隔,统一转为字符串数组) |
| | | 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数据解析失败:", error); |
| | | } |
| | | }, |
| | | |
| | | getConfirmAttachments(type) { |
| | | return this.confirmAttachmentData[type] || []; |
| | | }, |
| | | |
| | | getRegisterAttachments(type) { |
| | | return this.registerAttachmentData[type] || []; |
| | | }, |
| | | |
| | | openUploadDialog(type) { |
| | | this.currentUploadType = type; |
| | | this.tempFileList = []; |
| | |
| | | }); |
| | | }, |
| | | |
| | | // 上传前校验[7](@ref) |
| | | beforeUpload(file) { |
| | | const allowedTypes = [ |
| | | "application/pdf", |
| | |
| | | "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") || |
| | |
| | | file.name.endsWith(".png") || |
| | | file.name.endsWith(".doc") || |
| | | file.name.endsWith(".docx"); |
| | | |
| | | if (!isTypeOk) { |
| | | this.$message.error( |
| | | "文件格式不支持,请上传pdf、jpg、png、doc或docx格式文件" |
| | | ); |
| | | 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: "确定", |
| | |
| | | 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) })); |
| | | |
| | | // 子女数量:接口可能不返回该字段 |
| | | // 回显时用已有子女行数兜底;用户主动清空("")则不兜底,行照常清掉 |
| | | 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(); |
| | | // 兜底只在回显那一次生效 |
| | | 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, |
| | |
| | | this.previewVisible = true; |
| | | }, |
| | | |
| | | // 文件下载 |
| | | handleDownload(file) { |
| | | const fileUrl = file.fileUrl; |
| | | const fileName = file.fileName; |
| | | |
| | | if (fileUrl) { |
| | | const link = document.createElement("a"); |
| | | link.href = fileUrl; |
| | |
| | | } |
| | | }, |
| | | |
| | | // 获取文件类型 |
| | | 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(".") |
| | |
| | | .toLowerCase(); |
| | | }, |
| | | |
| | | // 文件大小格式化 |
| | | formatFileSize(size) { |
| | | if (!size) return "0 B"; |
| | | const k = 1024; |
| | |
| | | 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) |
| | |
| | | .toString() |
| | | .padStart(2, "0")}`; |
| | | }, |
| | | |
| | | accomplish() { |
| | | this.$confirm("是否完成该案例捐献确认步骤?", "提醒", { |
| | | confirmButtonText: "确定", |
| | |
| | | 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(",") |
| | | }; |
| | | // 人体器官获取组织属于档案表字段,不随亲属确认表保存 |
| | | 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); |
| | |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | // 人体器官获取组织单独保存到档案表 |
| | | await this.saveArchiveAcquisitionTissue(); |
| | | this.$message.success("保存成功"); |
| | | this.$router.push("/case/affirm"); |
| | | } else { |
| | |
| | | } finally { |
| | | this.saveLoading = false; |
| | | } |
| | | }, |
| | | // 保存档案表的人体器官获取组织字段 |
| | | 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("保存档案表人体器官获取组织失败:", 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; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | |
| | | |
| | | .detail-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .main-family { |
| | | font-weight: bold; |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | .attachment-card { |
| | |
| | | |
| | | .empty-attachment { |
| | | text-align: center; |
| | | padding: 40px 0; |
| | | padding: 30px 0; |
| | | color: #909399; |
| | | } |
| | | |
| | |
| | | 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> |