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

refactor(cert): 重构证书分享页面

- 重新设计了证书分享页面的布局和样式
- 增加了船舶基础信息、船舶证书、船员证书等详细信息展示
- 添加了证书预览功能
- 优化了数据加载和错误处理逻辑
- 调整了分享功能的实现方式
wzg пре 8 месеци
родитељ
комит
3cf5a43c61

+ 9 - 0
miniprogram/pages/cert/cert.js

@@ -197,6 +197,7 @@ Page({
 
   onLoad(options) {
     this.getCerts();
+
     // this.getContacts();
     // this.getIntroduce();
   },
@@ -207,4 +208,12 @@ Page({
       });
     }
   },
+
+  async onShareAppMessage() {
+    let { data } = await getApi("/ship/cert/share/token");
+    return {
+      title: this.data.shipName,
+      path: `/pages/cert/sharePage/sharePage?token=${data.result.result}`,
+    };
+  },
 });

+ 189 - 56
miniprogram/pages/cert/sharePage/sharePage.js

@@ -1,80 +1,213 @@
-// pages/cert/sharePage/sharePage.js
-import { postApi } from "../../../apis/api";
-const app = getApp();
+// pages/cert/cert.js
+import { postApi, getApi } from "../../../apis/api";
 Page({
-  /**
-   * 页面的初始数据
-   */
   data: {
-    sharedCertList: [], // 用于存储分享的证书列表
+    shipName: "",
+    mmsi: "",
+    shipCerts: [],
+    crewCerts: [],
+    certs: [],
+    contacts: [],
+    introduce: {},
+    accessToken: wx.getStorageSync("accessToken") || "",
   },
-
-  /**
-   * 生命周期函数--监听页面加载
-   */
-  onLoad(options) {
-    const token = options.token;
-    if (token) {
-      this.getSharedCertInfo(token);
-    } else {
+  async getCerts(token) {
+    if (!token) {
       wx.showToast({
         title: "无效的分享链接",
         icon: "none",
       });
+      return;
     }
-  },
-
-  async getSharedCertInfo(token) {
-    wx.showLoading({
-      title: "加载中...",
+    let { data } = await postApi("/ship/cert/share/list", {
+      token,
     });
-    let { data } = await postApi("/ship/cert/share/list", { token });
+    console.log(data);
+    if (data.status === 0) {
+      // 处理船舶基本信息
+      const shipInfo = data.result;
+
+      // 处理船舶证书信息
+      const formattedShipCerts = shipInfo.shipCerts.map((cert) => {
+        // 获取第一个有效期(如果有多个,默认使用第一个)
+        const expireDate =
+          cert.certValidities && cert.certValidities.length > 0
+            ? cert.certValidities[0].endValidTime
+                .split(" ")[0]
+                .replace(/\//g, "-")
+            : "";
+
+        // 处理所有的certFileViewUrls,确保它们都被正确格式化
+        const formattedViewUrls =
+          cert.certFileViewUrls && cert.certFileViewUrls.length > 0
+            ? cert.certFileViewUrls.map((url) =>
+                url.trim().replace(/` /g, "").replace(/ `/g, "")
+              )
+            : ["暂无"];
+
+        return {
+          name: cert.certTypeName,
+          photoUrls: formattedViewUrls,
+          photoUrl: formattedViewUrls[0], // 保留单张图片的兼容性
+          expireDate: expireDate,
+        };
+      });
+
+      // 处理船员证书信息
+      const formattedCrewCerts = shipInfo.shipCrewCerts.map((crew) => {
+        // 处理船员的证书
+        const crewCertificates = crew.certs.map((cert) => {
+          // 处理所有的viewUrls,确保它们都被正确格式化
+          const formattedViewUrls =
+            cert.viewUrls && cert.viewUrls.length > 0
+              ? cert.viewUrls.map((url) =>
+                  url.trim().replace(/` /g, "").replace(/ `/g, "")
+                )
+              : ["暂无"];
+
+          return {
+            name: cert.docTypeName,
+            photoUrls: formattedViewUrls,
+            photoUrl: formattedViewUrls[0], // 保留单张图片的兼容性
+            expireDate: cert.expiryAt
+              ? cert.expiryAt.split(" ")[0].replace(/\//g, "-")
+              : "",
+          };
+        });
+
+        // 找到医疗报告和服务簿的URL
+        const medicalReportCert = crew.certs.find((cert) => cert.docType === 2);
+        const serviceBookCert = crew.certs.find((cert) => cert.docType === 3);
+
+        // 处理医疗报告的所有URL
+        const medicalReportUrls =
+          medicalReportCert &&
+          medicalReportCert.viewUrls &&
+          medicalReportCert.viewUrls.length > 0
+            ? medicalReportCert.viewUrls.map((url) =>
+                url.trim().replace(/` /g, "").replace(/ `/g, "")
+              )
+            : ["暂无"];
+
+        // 处理服务簿的所有URL
+        const serviceBookUrls =
+          serviceBookCert &&
+          serviceBookCert.viewUrls &&
+          serviceBookCert.viewUrls.length > 0
+            ? serviceBookCert.viewUrls.map((url) =>
+                url.trim().replace(/` /g, "").replace(/ `/g, "")
+              )
+            : ["暂无"];
 
-    wx.hideLoading();
+        return {
+          name: crew.fullName,
+          medicalReportUrls: medicalReportUrls,
+          medicalReport: medicalReportUrls[0], // 保留单张图片的兼容性
+          serviceBookUrls: serviceBookUrls,
+          serviceBook: serviceBookUrls[0], // 保留单张图片的兼容性
+          certificates: crewCertificates,
+        };
+      });
+
+      this.setData({
+        shipName: shipInfo.shipName,
+        mmsi: shipInfo.mmsi,
+        shipCerts: formattedShipCerts,
+        crewCerts: formattedCrewCerts,
+        certs: data.result,
+      });
+    } else {
+      this.setData({
+        shipCerts: [],
+        crewCerts: [],
+        certs: [],
+      });
+      wx.showToast({
+        title: data.msg,
+        icon: "none",
+      });
+    }
+  },
+  async getContacts() {
+    let { data } = await getApi("/ship/cert/operation/contacts");
     if (data.status === 0) {
       this.setData({
-        sharedCertList: data.result,
+        contacts: data.result,
       });
     } else {
+      this.setData({
+        contacts: [],
+      });
       wx.showToast({
-        title: data.msg || "获取证书信息失败",
+        title: data.msg,
         icon: "none",
       });
     }
   },
+  async getIntroduce() {
+    let { data } = await getApi("/ship/cert/operation/introduce");
+    if (data.status === 0) {
+      this.setData({
+        introduce: data.result,
+      });
+    } else {
+      this.setData({
+        introduce: {},
+      });
+      wx.showToast({
+        title: data.msg,
+        icon: "none",
+      });
+    }
+  },
+  makePhoneCall(e) {
+    wx.makePhoneCall({
+      phoneNumber: e.currentTarget.dataset.phone,
+    });
+  },
 
-  /**
-   * 生命周期函数--监听页面初次渲染完成
-   */
-  onReady() {},
-
-  /**
-   * 生命周期函数--监听页面显示
-   */
-  onShow() {},
-
-  /**
-   * 生命周期函数--监听页面隐藏
-   */
-  onHide() {},
-
-  /**
-   * 生命周期函数--监听页面卸载
-   */
-  onUnload() {},
+  previewImage(e) {
+    const url = e.currentTarget.dataset.url;
+    const urls = e.currentTarget.dataset.urls;
 
-  /**
-   * 页面相关事件处理函数--监听用户下拉动作
-   */
-  onPullDownRefresh() {},
+    // 如果是暂无,则不预览
+    if (url === "暂无") {
+      return;
+    }
 
-  /**
-   * 页面上拉触底事件的处理函数
-   */
-  onReachBottom() {},
+    // 如果提供了多个URL,则使用它们
+    if (
+      urls &&
+      Array.isArray(JSON.parse(urls)) &&
+      JSON.parse(urls).length > 0
+    ) {
+      const urlsArray = JSON.parse(urls);
+      wx.previewImage({
+        current: url, // 当前显示的图片
+        urls: urlsArray,
+      });
+    } else {
+      // 兼容旧版本,只有单张图片
+      wx.previewImage({
+        urls: [url],
+      });
+    }
+  },
+  copy(e) {
+    wx.setClipboardData({
+      data: e.currentTarget.dataset.phone,
+      success(res) {
+        wx.showToast({
+          title: "复制成功",
+        });
+      },
+    });
+  },
 
-  /**
-   * 用户点击右上角分享
-   */
-  onShareAppMessage() {},
+  onLoad(options) {
+    this.getCerts(options.token);
+    // this.getContacts();
+    // this.getIntroduce();
+  },
+  onShow() {},
 });

+ 101 - 12
miniprogram/pages/cert/sharePage/sharePage.wxml

@@ -1,13 +1,102 @@
-<!-- pages/cert/sharePage/sharePage.wxml -->
 <view class="container">
-    <block wx:if="{{sharedCertList.length > 0}}">
-        <view wx:for="{{sharedCertList}}" wx:key="index" class="cert-item">
-            <text class="cert-name">证书名称: {{item.name || '未知证书'}}</text>
-            <text class="cert-expiry">有效期至: {{item.expiryDate || 'N/A'}}</text>
-            <!-- 根据实际返回的字段调整 item.name 和 item.expiryDate -->
-        </view>
-    </block>
-    <block wx:else>
-        <text>暂无分享的证书信息</text>
-    </block>
-</view>
+  <!-- 顶部标题 -->
+  <!-- 内容区域 -->
+  <view class="content">
+    <!-- 船舶基础信息 -->
+    <view class="card">
+      <view class="card-header">船舶基础信息</view>
+      <view class="card-content" wx:if="{{shipName}}">
+        <view class="info-item">
+          <view class="info-label">船舶名称</view>
+          <view class="info-value">{{shipName}}</view>
+        </view>
+        <view class="info-item">
+          <view class="info-label">MMSI</view>
+          <view class="info-value">{{mmsi}}</view>
+        </view>
+      </view>
+      <view class="tac fs28 c7" wx:else>暂无数据</view>
+    </view>
+    <!-- 船舶证书 -->
+    <view class="card">
+      <view class="card-header">船舶证书</view>
+      <view class="card-content" wx:if="{{shipCerts.length}}">
+        <view class="cert-list">
+          <view class="cert-item" wx:for="{{shipCerts}}" wx:key="index">
+            <view class="cert-title">{{item.name}}</view>
+            <block wx:if="{{item.photoUrl === '暂无'}}">
+              <view class="cert-photo pt30 pb30 no-image">暂无</view>
+            </block>
+            <block wx:else>
+              <image class="cert-photo pt30 pb30" mode="aspectFit" src="{{item.photoUrl}}" bindtap="previewImage" data-url="{{item.photoUrl}}" data-urls="{{JSON.stringify(item.photoUrls)}}"></image>
+            </block>
+            <view class="cert-expire">
+              <text class="expire-label">有效期至:</text>
+              <text class="expire-date">{{item.expireDate}}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="tac fs28 c7" wx:else>暂无数据</view>
+    </view>
+    <!-- 船员证书 -->
+    <view class="card">
+      <view class="card-header">船员证书</view>
+      <view class="card-content" wx:if="{{crewCerts.length}}">
+        <view class="crew-list">
+          <view class="crew-item" wx:for="{{crewCerts}}" wx:key="index">
+            <view class="crew-name">{{item.name}}</view>
+            <!-- 体检报告 -->
+            <view class="cert-section">
+              <view class="section-title">体检报告</view>
+              <block wx:if="{{item.medicalReport === '暂无'}}">
+                <view class="cert-photo pt30 pb30 no-image">暂无</view>
+              </block>
+              <block wx:else>
+                <image class="cert-photo pt30 pb30" mode="aspectFit" src="{{item.medicalReport}}" bindtap="previewImage" data-url="{{item.medicalReport}}" data-urls="{{JSON.stringify(item.medicalReportUrls)}}"></image>
+              </block>
+            </view>
+            <!-- 服务簿 -->
+            <view class="cert-section">
+              <view class="section-title">服务簿</view>
+              <block wx:if="{{item.serviceBook === '暂无'}}">
+                <view class="cert-photo pt30 pb30 no-image">暂无</view>
+              </block>
+              <block wx:else>
+                <image class="cert-photo pt30 pb30" mode="aspectFit" src="{{item.serviceBook}}" bindtap="previewImage" data-url="{{item.serviceBook}}" data-urls="{{JSON.stringify(item.serviceBookUrls)}}"></image>
+              </block>
+            </view>
+            <!-- 证书列表 -->
+            <view class="cert-section">
+              <view class="section-title">证书列表</view>
+              <view class="cert-list">
+                <view class="cert-item" wx:for="{{item.certificates}}" wx:for-item="cert" wx:key="index">
+                  <view class="cert-title">{{cert.name}}</view>
+                  <block wx:if="{{cert.photoUrl === '暂无'}}">
+                    <view class="cert-photo pt30 pb30 no-image">暂无</view>
+                  </block>
+                  <block wx:else>
+                    <image class="cert-photo pt30 pb30" mode="aspectFit" src="{{cert.photoUrl}}" bindtap="previewImage" data-url="{{cert.photoUrl}}" data-urls="{{JSON.stringify(cert.photoUrls)}}"></image>
+                  </block>
+                  <view class="cert-expire">
+                    <text class="expire-label">有效期至:</text>
+                    <text class="expire-date">{{cert.expireDate}}</text>
+                  </view>
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="tac fs28 c7" wx:else>暂无数据</view>
+    </view>
+    <!-- 分享按钮 -->
+    <view class="share-section">
+      <!-- <button wx:if="{{accessToken}}" class="share-btn" open-type="share" bindtap="share">
+        一键分享证书信息
+      </button> -->
+      <view class="share-footer">船东证书服务由汇很多船东科技服务平台提供</view>
+    </view>
+  </view>
+</view>
+<view class="h200"></view>

+ 144 - 17
miniprogram/pages/cert/sharePage/sharePage.wxss

@@ -1,39 +1,166 @@
-/* pages/cert/sharePage/sharePage.wxss */
 .container {
   padding: 20rpx;
-  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
-    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
+  background-color: #f5f5f5;
   min-height: 100vh;
-  background-color: #f4f4f4;
 }
 
-.cert-item {
+.header {
+  font-size: 36rpx;
+  font-weight: bold;
+  text-align: center;
+  padding: 20rpx 0;
+  color: #333;
+}
+
+.content {
+  padding: 20rpx;
+}
+
+.card {
   background-color: #fff;
-  border-radius: 10rpx;
-  padding: 30rpx 20rpx;
+  border-radius: 12rpx;
+  padding: 20rpx;
   margin-bottom: 20rpx;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
+}
+
+.card-header {
+  font-size: 32rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 20rpx;
+  padding-bottom: 10rpx;
+  border-bottom: 2rpx solid #eee;
+}
+
+.card-content {
+  padding: 10rpx 0;
+}
+
+.info-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10rpx 0;
+  border-bottom: 1rpx solid #eee;
+}
+
+.info-item:last-child {
+  border-bottom: none;
+}
+
+.info-label {
+  color: #666;
+  font-size: 28rpx;
+}
+
+.info-value {
+  color: #333;
+  font-size: 28rpx;
+  font-weight: 500;
+}
+
+.cert-list {
   display: flex;
   flex-direction: column;
+  gap: 20rpx;
 }
 
-.cert-name {
-  font-size: 32rpx;
+.cert-item {
+  background-color: #f9f9f9;
+  border-radius: 8rpx;
+  padding: 15rpx;
+}
+
+.cert-title {
+  font-size: 28rpx;
   color: #333;
-  font-weight: bold;
   margin-bottom: 10rpx;
 }
 
-.cert-expiry {
+.cert-photo {
+  width: 100%;
+  height: 300rpx;
+  border-radius: 8rpx;
+  margin: 10rpx 0;
+  background-color: #eee;
+}
+
+.no-image {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #999;
   font-size: 28rpx;
+}
+
+.cert-expire {
+  display: flex;
+  align-items: center;
+  margin-top: 10rpx;
+}
+
+.expire-label {
+  font-size: 24rpx;
   color: #666;
 }
 
-/* 如果列表为空 */
-.container > .empty-text {
-  display: block;
+.expire-date {
+  font-size: 24rpx;
+  color: #ff4d4f;
+  margin-left: 10rpx;
+}
+
+.crew-list {
+  display: flex;
+  flex-direction: column;
+  gap: 30rpx;
+}
+
+.crew-item {
+  background-color: #f9f9f9;
+  border-radius: 8rpx;
+  padding: 20rpx;
+}
+
+.crew-name {
+  font-size: 30rpx;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 15rpx;
+}
+
+.cert-section {
+  margin-top: 20rpx;
+}
+
+.section-title {
+  font-size: 28rpx;
+  color: #666;
+  margin-bottom: 10rpx;
+}
+
+.share-section {
+  margin-top: 40rpx;
+  padding: 20rpx;
   text-align: center;
+}
+
+.share-btn {
+  background-color: #1e88e5;
+  color: #fff;
+  font-size: 32rpx;
+  padding: 20rpx 40rpx;
+  border-radius: 40rpx;
+  border: none;
+  margin-bottom: 20rpx;
+}
+
+.share-btn::after {
+  border: none;
+}
+
+.share-footer {
+  font-size: 24rpx;
   color: #999;
-  font-size: 30rpx;
-  padding-top: 200rpx;
 }

+ 14 - 0
miniprogram/pages/securityCheck/securityCheck.js

@@ -7,6 +7,8 @@ Page({
   data: {
     currentNotice: {}, // 当前显示的通知详情
     noticeList: [],
+    shareNoticeId: "",
+    shareNoticeTitle: "",
   },
 
   /**
@@ -101,4 +103,16 @@ Page({
       });
     }
   },
+  share(e) {
+    this.setData({
+      shareNoticeId: e.currentTarget.dataset.id,
+      shareNoticeTitle: e.currentTarget.dataset.title,
+    });
+  },
+  onShareAppMessage() {
+    return {
+      title: this.data.shareNoticeTitle,
+      path: `/pages/securityCheck/sharePage/sharePage?noticeId=${this.data.shareNoticeId}`,
+    };
+  },
 });

+ 3 - 1
miniprogram/pages/securityCheck/securityCheck.wxml

@@ -17,7 +17,9 @@
           拨打电话
         </button>
       </view>
-      <button class="share-btn" open-type="share" data-title="{{item.noticeTitle}}">分享通知</button>
+      <button class="share-btn" open-type="share" data-title="{{item.noticeTitle}}" data-id="{{item.id}}" bindtap="share">
+        分享通知
+      </button>
     </view>
   </view>
   <view class="tac fs28 c7 p40" wx:else>暂无数据</view>

+ 1 - 0
miniprogram/pages/securityCheck/sharePage/sharePage.js

@@ -27,6 +27,7 @@ Page({
    * 生命周期函数--监听页面加载
    */
   onLoad(options) {
+    console.log(options);
     const noticeId = options.noticeId;
     if (noticeId) {
       this.getSharedNoticeInfo(noticeId);

+ 7 - 0
project.private.config.json

@@ -2,6 +2,13 @@
   "condition": {
     "miniprogram": {
       "list": [
+        {
+          "name": "pages/cert/sharePage/sharePage",
+          "pathName": "pages/cert/sharePage/sharePage",
+          "query": "token=122",
+          "launchMode": "default",
+          "scene": null
+        },
         {
           "name": "pages/school/sharePage/sharePage",
           "pathName": "pages/school/sharePage/sharePage",