Преглед изворни кода

feat(shipOwnerManage): 优化船员信息保存逻辑

- 为保存按钮添加 loading 状态,提升用户体验
- 实现证书删除功能
- 优化绑定船舶流程,添加异常处理
- 调整船员信息表单结构,提高代码可读性
wzg пре 9 месеци
родитељ
комит
39032b3b42
1 измењених фајлова са 134 додато и 76 уклоњено
  1. 134 76
      src/views/shipOwnerManage/shipOwnerDetail.vue

+ 134 - 76
src/views/shipOwnerManage/shipOwnerDetail.vue

@@ -100,7 +100,13 @@
       </el-button>
       <template v-else>
         <el-button @click="cancelEditingBasicInfo">取消</el-button>
-        <el-button type="primary" @click="saveBasicInfo">保存</el-button>
+        <el-button
+          type="primary"
+          :loading="saveBasicInfoLoading"
+          @click="saveBasicInfo"
+        >
+          保存
+        </el-button>
       </template>
     </div>
   </div>
@@ -227,7 +233,6 @@
               :params="{ type: 1, shipOwnerId: shipOwnerForm.shipOwnerId }"
               @onUploadFileList="handleCertSuccess"
               @onRemoveFileList="handleCertRemove"
-              :limit="1"
               upload-text="点击上传证书"
             />
           </el-form-item>
@@ -244,7 +249,13 @@
       </el-button>
       <template v-else>
         <el-button @click="cancelEditingCertificate">取消</el-button>
-        <el-button type="primary" @click="updateShipOwnerCert">保存</el-button>
+        <el-button
+          type="primary"
+          :loading="saveCertificateLoading"
+          @click="updateShipOwnerCert"
+        >
+          保存
+        </el-button>
       </template>
     </div>
   </div>
@@ -283,7 +294,7 @@
     <div class="container-title df aic jcsb pr20">
       船舶信息
       <el-button
-        v-if="!shipOwnerForm?.shipInfo?.shipId && !isBindShipVisible"
+        v-if="!shipOwnerForm?.shipInfo?.id && !isBindShipVisible"
         type="primary"
         @click="bindShip"
       >
@@ -470,7 +481,9 @@
       v-if="!shipOwnerForm.shipInfo.id && isBindShipVisible"
     >
       <el-button @click="cancelBindShip">取消绑定</el-button>
-      <el-button type="primary" @click="addShip">绑定船舶</el-button>
+      <el-button type="primary" :loading="bindShipLoading" @click="addShip">
+        绑定船舶
+      </el-button>
     </div>
   </div>
 
@@ -478,7 +491,13 @@
     <el-button @click="router.replace('/shipOwnerManage/shipOwnerList')">
       取消
     </el-button>
-    <el-button type="primary" @click="saveShipOwner">保存</el-button>
+    <el-button
+      type="primary"
+      :loading="saveShipOwnerLoading"
+      @click="saveShipOwner"
+    >
+      保存
+    </el-button>
   </div>
 </template>
 <script setup>
@@ -500,6 +519,11 @@ const certificateFormRef = ref(null);
 const isEditing = ref(false);
 const isEditingBasicInfo = ref(false);
 const isEditingCertificate = ref(false);
+// 加载状态
+const saveBasicInfoLoading = ref(false);
+const saveCertificateLoading = ref(false);
+const bindShipLoading = ref(false);
+const saveShipOwnerLoading = ref(false);
 // 原始数据备份,用于取消编辑时恢复
 const originalData = ref(null);
 const originalBasicInfo = ref(null);
@@ -579,66 +603,66 @@ const certificateRules = {
   certFile: [{ validator: validateCertFile, trigger: "change" }],
 };
 // 初始化船员表单数据结构
-// const shipOwnerForm = ref({
-//   shipOwnerId: 0, // 船员ID,匹配时返回,未匹配到为0,非0时下方内容无效
-//   userName: "", // 船员姓名(必填)
-//   userPhone: "", // 船员手机(必填)
-//   idcardNo: "", // 船员身份证号(非必填)
-//   idcardFrontFileKey: "key", // 船员身份证正面文件key(非必填)
-//   idcardFrontViewUrl: "", // 船员身份证正面文件预览地址(非必填)
-//   idcardFrontDownloadUrl: "", // 船员身份证正面文件下载地址(非必填)
-//   idcardBackFileKey: "", // 船员身份证反面文件key(非必填)
-//   idcardBackViewUrl: "", // 船员身份证反面文件预览地址(非必填)
-//   idcardBackDownloadUrl: "", // 船员身份证反面文件下载地址(非必填)
-//   certificate: {
-//     gender: "", // 性别(1-男;2-女)
-//     certNo: "", // 证书编号(必填)
-//     certType: "", // 证书类型(非必填)
-//     postRole: "", // 职务资格(必填)
-//     issuerAt: "", // 发证日期(必填)
-//     expiryAt: "", // 截止日期(必填)
-//     issuerAuthority: "", // 签发机构(必填)
-//     applicableRestrictions: "", // 适用限制(非必填)
-//   },
-//   documents: [], // 文件信息数组
-// shipInfo:{}
-// });
 const shipOwnerForm = ref({
-  shipOwnerId: 0,
-  userName: "测试船员18",
-  userPhone: "13989999918",
-  idcardNo: "",
-  idcardFrontFileKey: "key",
-  idcardFrontViewUrl: "",
-  idcardFrontDownloadUrl: "",
-  idcardBackFileKey: "",
-  idcardBackViewUrl: "",
-  idcardBackDownloadUrl: "",
+  shipOwnerId: 0, // 船员ID,匹配时返回,未匹配到为0,非0时下方内容无效
+  userName: "", // 船员姓名(必填)
+  userPhone: "", // 船员手机(必填)
+  idcardNo: "", // 船员身份证号(非必填)
+  idcardFrontFileKey: "key", // 船员身份证正面文件key(非必填)
+  idcardFrontViewUrl: "", // 船员身份证正面文件预览地址(非必填)
+  idcardFrontDownloadUrl: "", // 船员身份证正面文件下载地址(非必填)
+  idcardBackFileKey: "", // 船员身份证反面文件key(非必填)
+  idcardBackViewUrl: "", // 船员身份证反面文件预览地址(非必填)
+  idcardBackDownloadUrl: "", // 船员身份证反面文件下载地址(非必填)
   certificate: {
-    gender: 1,
-    certNo: "9",
-    certType: "",
-    postRole: "大副",
-    issuerAt: "2025-04-15T16:00:00.000Z",
-    expiryAt: "2025-04-29T16:00:00.000Z",
-    issuerAuthority: "99",
-    applicableRestrictions: "999",
+    gender: "", // 性别(1-男;2-女)
+    certNo: "", // 证书编号(必填)
+    certType: "", // 证书类型(非必填)
+    postRole: "", // 职务资格(必填)
+    issuerAt: "", // 发证日期(必填)
+    expiryAt: "", // 截止日期(必填)
+    issuerAuthority: "", // 签发机构(必填)
+    applicableRestrictions: "", // 适用限制(非必填)
   },
-  documents: [
-    {
-      docType: 1,
-      fileKey:
-        "new/ship_onwer_doc_temp/汇很多船务公司/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png",
-      viewUrl:
-        "https://hhd-shipping-formal-1255802371.cos.ap-shanghai.myqcloud.com/new/ship_onwer_doc_temp/%E6%B1%87%E5%BE%88%E5%A4%9A%E8%88%B9%E5%8A%A1%E5%85%AC%E5%8F%B8/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png?sign=q-sign-algorithm%3Dsha1%26q-ak%3DAKID4xb091cy4tRikV0EBrGOGsCF1WkhMlum%26q-sign-time%3D1744727290%3B93158697600%26q-key-time%3D1744727290%3B93158697600%26q-header-list%3Dhost%26q-url-param-list%3D%26q-signature%3D86b5d9af068ca7a19038b9c67a795cfde834a1d8",
-      downloadUrl:
-        "https://hhd-shipping-formal-1255802371.cos.ap-shanghai.myqcloud.com/new/ship_onwer_doc_temp/%E6%B1%87%E5%BE%88%E5%A4%9A%E8%88%B9%E5%8A%A1%E5%85%AC%E5%8F%B8/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png?sign=q-sign-algorithm%3Dsha1%26q-ak%3DAKID4xb091cy4tRikV0EBrGOGsCF1WkhMlum%26q-sign-time%3D1744727290%3B93156019200%26q-key-time%3D1744727290%3B93156019200%26q-header-list%3Dhost%26q-url-param-list%3Dresponse-cache-control%3Bresponse-content-disposition%3Bresponse-content-language%3Bresponse-content-type%3Bresponse-expires%26q-signature%3D3ebfed3521abe099246ad7cf1370606769ad89cc&response-cache-control=no-cache&response-content-disposition=filename%3D%2255.png%22&response-content-language=zh-CN&response-expires=Wed%2C%2016%20Apr%202025%2014%3A28%3A10%20GMT&response-content-type=application%2Foctet-stream",
-    },
-  ],
-  loginAccountId: "19",
-  shippingId: "15",
+  documents: [], // 文件信息数组
   shipInfo: {},
 });
+// const shipOwnerForm = ref({
+//   shipOwnerId: 0,
+//   userName: "测试船员18",
+//   userPhone: "13989999918",
+//   idcardNo: "",
+//   idcardFrontFileKey: "key",
+//   idcardFrontViewUrl: "",
+//   idcardFrontDownloadUrl: "",
+//   idcardBackFileKey: "",
+//   idcardBackViewUrl: "",
+//   idcardBackDownloadUrl: "",
+//   certificate: {
+//     gender: 1,
+//     certNo: "9",
+//     certType: "",
+//     postRole: "大副",
+//     issuerAt: "2025-04-15T16:00:00.000Z",
+//     expiryAt: "2025-04-29T16:00:00.000Z",
+//     issuerAuthority: "99",
+//     applicableRestrictions: "999",
+//   },
+//   documents: [
+//     {
+//       docType: 1,
+//       fileKey:
+//         "new/ship_onwer_doc_temp/汇很多船务公司/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png",
+//       viewUrl:
+//         "https://hhd-shipping-formal-1255802371.cos.ap-shanghai.myqcloud.com/new/ship_onwer_doc_temp/%E6%B1%87%E5%BE%88%E5%A4%9A%E8%88%B9%E5%8A%A1%E5%85%AC%E5%8F%B8/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png?sign=q-sign-algorithm%3Dsha1%26q-ak%3DAKID4xb091cy4tRikV0EBrGOGsCF1WkhMlum%26q-sign-time%3D1744727290%3B93158697600%26q-key-time%3D1744727290%3B93158697600%26q-header-list%3Dhost%26q-url-param-list%3D%26q-signature%3D86b5d9af068ca7a19038b9c67a795cfde834a1d8",
+//       downloadUrl:
+//         "https://hhd-shipping-formal-1255802371.cos.ap-shanghai.myqcloud.com/new/ship_onwer_doc_temp/%E6%B1%87%E5%BE%88%E5%A4%9A%E8%88%B9%E5%8A%A1%E5%85%AC%E5%8F%B8/976a8dc8-94d9-4d0a-ba82-5ddfafddcbc81744727290090.png?sign=q-sign-algorithm%3Dsha1%26q-ak%3DAKID4xb091cy4tRikV0EBrGOGsCF1WkhMlum%26q-sign-time%3D1744727290%3B93156019200%26q-key-time%3D1744727290%3B93156019200%26q-header-list%3Dhost%26q-url-param-list%3Dresponse-cache-control%3Bresponse-content-disposition%3Bresponse-content-language%3Bresponse-content-type%3Bresponse-expires%26q-signature%3D3ebfed3521abe099246ad7cf1370606769ad89cc&response-cache-control=no-cache&response-content-disposition=filename%3D%2255.png%22&response-content-language=zh-CN&response-expires=Wed%2C%2016%20Apr%202025%2014%3A28%3A10%20GMT&response-content-type=application%2Foctet-stream",
+//     },
+//   ],
+//   loginAccountId: "19",
+//   shippingId: "15",
+//   shipInfo: {},
+// });
 // 计算属性 - 文件列表
 const idCardFrontFileList = computed(() => {
   if (
@@ -724,6 +748,9 @@ async function getShipOwnerDetail() {
       documents: data.result.documents || [],
       shipInfo: data.result.shipInfo || {},
     };
+    if (shipOwnerForm.value.shipInfo.id) {
+      shipInfoDisabled.value = true;
+    }
   } else {
     ElMessage.error(data.msg || "获取船员详情失败");
   }
@@ -786,7 +813,16 @@ const handleCertSuccess = ({ response: data }) => {
 };
 
 // 证书删除处理
-const handleCertRemove = ({ fileIndex }) => {
+const handleCertRemove = async ({ file, fileIndex }) => {
+  if (file.id) {
+    let { data } = await api.deleteShipCert({
+      shipCertId: file.id,
+    });
+    if (data.status !== 0) {
+      ElMessage.error(data.msg || "删除失败");
+      return;
+    }
+  }
   const certDocs = shipOwnerForm.value.documents.filter(
     (doc) => doc.docType === 1
   );
@@ -900,6 +936,8 @@ const saveBasicInfo = () => {
   shipOwnerFormRef.value.validate(async (valid) => {
     if (!valid) return;
     if (!(await confirm("确定保存基本信息吗?"))) return;
+
+    saveBasicInfoLoading.value = true;
     // 构建保存数据
     const saveData = {
       shipOwnerId: shipOwnerForm.value.shipOwnerId,
@@ -934,6 +972,9 @@ const saveBasicInfo = () => {
       .catch((err) => {
         console.error(err);
         ElMessage.error("保存失败");
+      })
+      .finally(() => {
+        saveBasicInfoLoading.value = false;
       });
   });
 };
@@ -970,6 +1011,7 @@ const updateShipOwnerCert = () => {
     }
     if (!(await confirm("确定保存证书信息吗?"))) return;
 
+    saveCertificateLoading.value = true;
     // 构建保存数据
     const saveData = {
       shipOwnerId: shipOwnerForm.value.shipOwnerId,
@@ -995,6 +1037,9 @@ const updateShipOwnerCert = () => {
       .catch((err) => {
         console.error(err);
         ElMessage.error("保存失败");
+      })
+      .finally(() => {
+        saveCertificateLoading.value = false;
       });
   });
 };
@@ -1016,6 +1061,7 @@ const saveShipOwner = () => {
 
       if (!(await confirm("确定保存船员信息吗?"))) return;
 
+      saveShipOwnerLoading.value = true;
       // 如果有ID,则更新,否则新增
       const apiMethod = route.query.shipOwnerId
         ? api.updateShipOwner
@@ -1057,6 +1103,9 @@ const saveShipOwner = () => {
         .catch((err) => {
           console.error(err);
           ElMessage.error("保存失败");
+        })
+        .finally(() => {
+          saveShipOwnerLoading.value = false;
         });
       // 表单验证通过,继续保存操作
     });
@@ -1142,21 +1191,30 @@ async function addShip() {
   }
   if (!(await confirm("确认绑定船舶?"))) return;
 
-  let { data } = await api.addShip({
-    ...shipOwnerForm.value.shipInfo,
-    shipOwnerId: route.query.shipOwnerId,
-  });
-
-  if (data.status == 0) {
-    ElMessage({
-      type: "success",
-      message: "绑定成功",
-    });
-  } else {
-    ElMessage({
-      type: "error",
-      message: data.msg,
+  bindShipLoading.value = true;
+  try {
+    let { data } = await api.addShip({
+      ...shipOwnerForm.value.shipInfo,
+      shipOwnerId: route.query.shipOwnerId,
     });
+
+    if (data.status == 0) {
+      ElMessage({
+        type: "success",
+        message: "绑定成功",
+      });
+      getShipOwnerDetail();
+    } else {
+      ElMessage({
+        type: "error",
+        message: data.msg,
+      });
+    }
+  } catch (err) {
+    console.error(err);
+    ElMessage.error("绑定失败");
+  } finally {
+    bindShipLoading.value = false;
   }
 }