소스 검색

报港预约船主手签

shasha 19 시간 전
부모
커밋
25ff6082cd

+ 1 - 0
app.json

@@ -83,6 +83,7 @@
         "loadArrive/add",
         "loadArrive/edit",
         "loadArrive/info",
+        "loadArrive/shipSign",
         "loadAppoint/index",
         "loadAppoint/info",
         "loadAppoint/allocation",

+ 2 - 1
otherPages/loadArrive/index.wxml

@@ -54,7 +54,8 @@
                 
                 <van-button type="primary" size="small" data-id="{{item.id}}" data-approve-type="one" catchtap="showPopup" wx:if="{{roleCodeList == 'bizAdmin' && item.status == '1'}}">审核</van-button>
 
-                <van-button type="warning" size="small" data-id="{{item.id}}" data-arrive-number="{{item.arriveNumber}}" catchtap="confirmFun" style="margin-right: 20rpx;" wx:if="{{roleCodeList == 'ship' && item.loadStatus == '9' && item.status == '2'}}">确认</van-button>
+                <!-- <van-button type="warning" size="small" data-id="{{item.id}}" data-arrive-number="{{item.arriveNumber}}" catchtap="confirmFun" style="margin-right: 20rpx;" wx:if="{{roleCodeList == 'ship' && item.loadStatus == '9' && item.status == '2'}}">确认</van-button> -->
+                <van-button type="warning" size="small" data-url="shipSign?id={{item.id}}" catchtap="toLink" style="margin-right: 20rpx;" wx:if="{{roleCodeList == 'ship' && item.loadStatus == '9' && item.status == '2'}}">手签</van-button>
               </view>
             </navigator>
           </block>

+ 288 - 0
otherPages/loadArrive/shipSign.js

@@ -0,0 +1,288 @@
+// otherPages/loadArrive/shipSign.js
+var canvas = null;
+const app = getApp()
+Page({
+
+  /**
+   * 页面的初始数据
+   */
+  data: {
+    id:'',
+    ctx: null,
+    points: [], // 存储所有笔画
+    currentStroke: [], // 当前笔画
+    isDrawing: false,
+  },
+
+  /**
+   * 生命周期函数--监听页面加载
+   */
+  onLoad(options) {
+    this.setData({
+      id:options.id
+    })
+    this.initCanvas();
+  },
+
+  /**
+   * 初始化画布
+   * 设置画布大小、像素比例和画笔样式
+   */
+  async initCanvas() {
+    // 使用ID获取canvas组件实例
+    const query = wx.createSelectorQuery();
+    query.select('#canvas')
+      .fields({ node: true, size: true })
+      .exec((res) => {
+        canvas = res[0].node;
+        const ctx = canvas.getContext('2d');
+
+        // Canvas 画布的实际绘制宽高
+        const width = res[0].width
+        const height = res[0].height
+        // 设置画布大小,使用新的API获取设备像素比
+        const dpr = wx.getWindowInfo().pixelRatio;
+        canvas.width = width * dpr;
+        canvas.height = height * dpr;
+        ctx.scale(dpr, dpr);
+
+        // 设置画笔样式
+        ctx.strokeStyle = '#000000';
+        ctx.lineWidth = 3;
+        ctx.lineCap = 'round';
+        ctx.lineJoin = 'round';
+
+        //绘制背景
+        ctx.fillStyle = '#fff'
+        ctx.clearRect(0, 0, canvas.width, canvas.height)
+        ctx.fillRect(0, 0, canvas.width, canvas.height)
+
+        this.setData({ ctx });
+      });
+  },
+
+  /**
+   * 处理触摸开始事件
+   * 开始一个新的笔画,记录起始点
+   * @param {Object} e - 触摸事件对象
+   */
+  handleTouchStart(e) {
+    const { x, y } = e.touches[0];
+    this.setData({
+      isDrawing: true,
+      currentStroke: [[x, y]]
+    });
+    this.data.ctx.beginPath();
+    this.data.ctx.moveTo(x, y);
+  },
+
+  /**
+   * 处理触摸移动事件
+   * 继续绘制当前笔画的路径
+   * @param {Object} e - 触摸事件对象
+   */
+  handleTouchMove(e) {
+    if (!this.data.isDrawing) return;
+    const { x, y } = e.touches[0];
+    this.data.currentStroke.push([x, y]);
+    this.data.ctx.lineTo(x, y);
+    this.data.ctx.stroke();
+  },
+
+  /**
+   * 处理触摸结束事件
+   * 完成当前笔画,将其添加到笔画历史中
+   */
+  handleTouchEnd() {
+    if (!this.data.isDrawing) return;
+    this.setData({
+      isDrawing: false,
+      points: [...this.data.points, this.data.currentStroke],
+      currentStroke: []
+    });
+  },
+
+  /**
+   * 清除画布内容
+   * 清空所有笔画记录和画布显示
+   */
+  handleClear() {
+    const { ctx } = this.data;
+    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+    this.setData({ points: [] });
+  },
+
+  /**
+   * 撤销上一步操作
+   * 移除最后一笔,并重绘剩余的笔画
+   */
+  handleUndo() {
+    if (this.data.points.length === 0) return;
+
+    const { ctx } = this.data;
+    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+
+    // 移除最后一笔
+    const newPoints = this.data.points.slice(0, -1);
+    this.setData({ points: newPoints });
+
+    // 重绘所有笔画
+    newPoints.forEach(stroke => {
+      ctx.beginPath();
+      ctx.moveTo(stroke[0][0], stroke[0][1]);
+      stroke.forEach(([x, y]) => {
+        ctx.lineTo(x, y);
+      });
+      ctx.stroke();
+    });
+  },
+
+  /**
+   * 提交签名
+   * 将画布内容转换为图片并处理提交逻辑
+   * @returns {Promise<void>}
+   */
+  async handleSubmit() {
+    let that = this
+    if (this.data.points.length === 0) {
+      wx.showToast({
+        title: '请先签名',
+        icon: 'none'
+      });
+      return;
+    }
+
+    try {
+      // 将画布内容转换为图片
+      const tempFilePath = await new Promise((resolve, reject) => {
+        wx.canvasToTempFilePath({
+          canvas: canvas,
+          success: res => resolve(res.tempFilePath),
+          fail: reject
+        });
+      });
+
+      // 这里可以处理签名图片,比如上传到服务器
+      console.log('签名图片路径:', tempFilePath);
+
+      // 将图片转为 Base64
+      that.imageToBase64(tempFilePath, function (error, base64String) {
+        if (error) {
+            console.error('Base64 转换失败', error);
+            return;
+        }
+        that.setData({
+            signature: base64String
+        })
+        let formData = {
+          id         : that.data.id,
+          arriveSign : base64String
+        }
+        // 上传 Base64 编码的图片,订单签名
+        app.request.POST({
+          url: app.API.bizloadarriveSign,
+          params: formData,
+          page: that,
+          isLoadingTxt: '提交中...',
+          isSubmitting: true,
+          successFun: true
+        }).then(res => {
+          wx.showToast({
+            title: '确认成功',
+            icon: 'success',
+            duration: 2000,
+            complete: function () {
+              setTimeout(() => {
+                wx.navigateBack()
+              }, 1500) //延迟时间  
+            }
+          })
+        })
+        //that.selfConfirm(base64String);
+    });
+      
+      // wx.showToast({
+      //   title: '提交成功',
+      //   icon: 'success'
+      // });
+
+      // // 返回上一页
+      // setTimeout(() => {
+      //   wx.navigateBack();
+      // }, 1500);
+    } catch (error) {
+      console.error('提交签名失败:', error);
+      wx.showToast({
+        title: '提交失败',
+        icon: 'error'
+      });
+    }
+
+    
+  },
+
+  //图片转baose64
+  imageToBase64(tempFilePath, callback) {
+    wx.getFileSystemManager().readFile({
+        filePath: tempFilePath,
+        encoding: 'base64',
+        success: function (res) {
+            // 拼接与 PC 端一致的格式
+            var base64Str = "data:image/png;base64," + res.data;
+            callback(null, base64Str);
+        },
+        fail: function (error) {
+            callback(error);
+        }
+    });
+},
+
+  /**
+   * 生命周期函数--监听页面初次渲染完成
+   */
+  onReady() {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面显示
+   */
+  onShow() {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面隐藏
+   */
+  onHide() {
+
+  },
+
+  /**
+   * 生命周期函数--监听页面卸载
+   */
+  onUnload() {
+
+  },
+
+  /**
+   * 页面相关事件处理函数--监听用户下拉动作
+   */
+  onPullDownRefresh() {
+
+  },
+
+  /**
+   * 页面上拉触底事件的处理函数
+   */
+  onReachBottom() {
+
+  },
+
+  /**
+   * 用户点击右上角分享
+   */
+  onShareAppMessage() {
+
+  }
+})

+ 6 - 0
otherPages/loadArrive/shipSign.json

@@ -0,0 +1,6 @@
+{
+  "navigationBarTitleText": "船主手签",
+  "usingComponents": {
+    "van-button": "@vant/weapp/button/index"
+  }
+}

+ 65 - 0
otherPages/loadArrive/shipSign.less

@@ -0,0 +1,65 @@
+/* otherPages/loadArrive/shipSign.wxss */
+/* 页面容器 签字区域只自改这里的高度 */
+.signature-page {
+  width: 100vw;
+  height: calc(50vh - 44rpx);
+  // background-color: #f6f6f6;
+  display: flex;
+  flex-direction: column;
+  padding: 16rpx;
+  box-sizing: border-box;
+}
+
+/* 顶部操作栏 */
+.action-bar {
+  display: flex;
+  justify-content: flex-end;
+  gap: 16rpx;
+  margin-bottom: 20rpx;
+  padding: 0 10rpx;
+}
+
+/* 自定义按钮样式 */
+.action-bar .t-button {
+  min-width: auto;
+  padding: 0 16rpx;
+  font-size: 18rpx !important;
+  height: 35rpx !important;
+  line-height: 35rpx !important;
+}
+
+/* 按钮图标样式 */
+.action-bar .t-icon,
+.action-bar .t-button__icon,
+.action-bar .t-button .t-icon {
+  font-size: 20rpx !important;
+}
+
+/* 签名区域-大尺寸 */
+.signature-area-large {
+  flex: 1;
+  background-color: #ffffff;
+  border-radius: 16rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.2);
+  overflow: hidden;
+  position: relative;
+  margin: 0 auto;
+  width: 94vw;
+  height: 100vh;
+}
+
+/* 签名画布-大尺寸 */
+.signature-canvas-large {
+  width: 100%;
+  height: 100%;
+  background-color: #ffffff;
+}
+
+/* 提示文本 */
+.signature-tips {
+  text-align: center;
+  color: #999999;
+  font-size: 12px;
+  margin-top: 16rpx;
+}
+

+ 28 - 0
otherPages/loadArrive/shipSign.wxml

@@ -0,0 +1,28 @@
+<!-- otherPages/loadArrive/shipSign.wxml-->
+<!-- 电子签名页面 -->
+<view class="signature-page">
+  <!-- 顶部操作栏 -->
+  <!-- <view class="action-bar">
+    <van-button type="primary" bind:tap="handleClear">重写</van-button>
+    <van-button type="danger" bind:tap="handleUndo">撤销</van-button>
+    <van-button type="info" bind:tap="handleSubmit">提交</van-button>
+  </view> -->
+
+  <!-- 签名区域 -->
+  <view class="signature-area-large">
+    <canvas type="2d" id="canvas" class="signature-canvas-large" disable-scroll="{{true}}" bindtouchstart="handleTouchStart" bindtouchmove="handleTouchMove" bindtouchend="handleTouchEnd"></canvas>
+  </view>
+
+  <!-- 提示文本 -->
+  <view class="signature-tips">请在上方区域书写您的签名</view>
+
+  <view style="display: grid;grid-template-columns: 1fr 1fr;grid-gap: 30rpx;padding: 30rpx 0;">
+    <view><van-button type="primary" block bind:tap="handleClear">重写</van-button></view>
+    <view><van-button type="danger" block bind:tap="handleUndo">撤销</van-button></view>
+  </view>
+
+  <view class="fixedBtn submitBtn">
+    <van-button round block type="info" bind:tap="handleSubmit">提交</van-button>
+  </view>
+
+</view>

+ 57 - 0
otherPages/loadArrive/shipSign.wxss

@@ -0,0 +1,57 @@
+/* pages/updateSign/index.wxss */
+/* 页面容器 签字区域只自改这里的高度 */
+.signature-page {
+  width: 100vw;
+  height: calc(50vh - 44rpx);
+  display: flex;
+  flex-direction: column;
+  padding: 16rpx;
+  box-sizing: border-box;
+}
+/* 顶部操作栏 */
+.action-bar {
+  display: flex;
+  justify-content: flex-end;
+  gap: 16rpx;
+  margin-bottom: 20rpx;
+  padding: 0 10rpx;
+}
+/* 自定义按钮样式 */
+.action-bar .t-button {
+  min-width: auto;
+  padding: 0 16rpx;
+  font-size: 18rpx !important;
+  height: 35rpx !important;
+  line-height: 35rpx !important;
+}
+/* 按钮图标样式 */
+.action-bar .t-icon,
+.action-bar .t-button__icon,
+.action-bar .t-button .t-icon {
+  font-size: 20rpx !important;
+}
+/* 签名区域-大尺寸 */
+.signature-area-large {
+  flex: 1;
+  background-color: #ffffff;
+  border-radius: 16rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.2);
+  overflow: hidden;
+  position: relative;
+  margin: 0 auto;
+  width: 94vw;
+  height: 100vh;
+}
+/* 签名画布-大尺寸 */
+.signature-canvas-large {
+  width: 100%;
+  height: 100%;
+  background-color: #ffffff;
+}
+/* 提示文本 */
+.signature-tips {
+  text-align: center;
+  color: #999999;
+  font-size: 12px;
+  margin-top: 16rpx;
+}

+ 1 - 0
utils/api.js

@@ -157,6 +157,7 @@ const api = {
   'bizloadarriveDelete':'/biz/bizloadarrive/delete',//删除
   'bizloadarriveAudit':'/biz/bizloadarrive/auditArrive',//审核(管理员)
   'bizloadarriveConfirm':'/biz/bizloadarrive/arriveConfirm',//确认(船主)
+  'bizloadarriveSign':'/biz/bizloadarrive/arriveSign',//手签(船主)
 
 
   // 砂石预约 调度审批