zhangback
2026-03-30 0bafa6aa253c9ef6f5cb24e9a24c5282860e4c59
ui/car_wx_app/pages/observeLaw/index.vue
@@ -1,523 +1,359 @@
<template>
    <view class="container">
        <!-- 顶部导航栏 -->
  <view class="container">
    <Nav title="签署遵纪守法承诺书" @back="goBack" />
        <Nav title="签署遵纪守法承诺书" customBack="pages/acknowledgement/index"></Nav>
        <!-- 承诺书内容区域(可滚动) -->
        <scroll-view class="content-scroll" scroll-y="true">
            <view class="agreement-content">
                <text class="title">遵纪守法承诺书</text>
                <text class="paragraph">因本人在香港执行出车任务,为支持配合公司对持前往香港执行出车任务人员的管理,共同维护国家和公司的声誉,本人承诺做到:</text>
                <text class="heading">一、</text>
                <text
                    class="paragraph">严格遵守中华人民共和国《海关法》、《出境入境管理法》、《出境入境边防检查条例》,香港特别行政区有关法律法规及有关外事纪律规定,保守国家及公司的商业机密。</text>
                <text class="heading">二、</text>
                <text class="paragraph">严格遵守珠海市汇畅交通投资有限公司/珠海市海港汽车货运公司《出国(境)工作管理办法》等规章制度。</text>
                <text class="heading">三、</text>
                <text
                    class="paragraph">保证不利用赴港执行公务之便进行有损国家、公司形象及声誉等活动,不从事国家法律法规、香港特别行政区法律、上级主管部门或公司规章制度禁止的一切行为及活动。</text>
                <text class="heading">四、</text>
                <text
                    class="paragraph">保证不在出车任务时间内进行出入境旅游,不走私贩私、不携带违禁品出入境,不组织及不参与赌博、涉足色情场所、偷引渡等活动。如有发现其他人员或线索涉及违法违规活动,即向公司报告。</text>
                <text class="heading">五、</text>
                <text class="paragraph">主动配合口岸各管理部门指挥、检查。服从口岸各管理部门指挥、检查,按规定线路行驶和停放车辆,服从调度和工作安排。</text>
                <text class="heading">六、</text>
                <text
                    class="paragraph">每日驾驶车辆出入境前后自觉检查,如发现人员或交通运输工具潜在安全管理隐患,或有涉及各口岸的违法犯罪人员、车辆进出动态等信息的,及时报告公司及珠海出入境边防检查站。</text>
                <text class="paragraph">本人如有违反,自愿接受法律法规或公司规章制度的处罚。</text>
                <text class="paragraph">特此承诺!</text>
                <text class="sign-line">承诺人签字:[ ]</text>
                <text class="sign-line">日期:[ ]</text>
            </view>
        </scroll-view>
        <!-- 底部固定区域(勾选框+按钮) -->
        <view class="bottom-fixed">
            <!-- 勾选区域 -->
            <!-- <view class="agree-area">
        <view class="checkbox-group">
          <checkbox
            class="checkbox"
            :checked="isAgreed"
            @change="handleAgreeChange"
          ></checkbox>
          <text class="agree-text">我已阅读并理解上述内容,自愿签署</text>
          <text class="required">*</text>
    <scroll-view class="content-scroll" scroll-y>
      <view class="agreement-content">
        <text class="title">{{ agreementContent.title }}</text>
        <text class="intro">{{ agreementContent.intro }}</text>
        <view v-for="(clause, i) in agreementContent.clauses" :key="i" class="clause">
          <text class="clause-number">{{ clause.number }}、</text>
          <text class="clause-text">{{ clause.text }}</text>
        </view>
      </view> -->
            <!-- 底部按钮 -->
            <view class="btn-group">
                <button class="cancel-btn" @click="navigateBack">上一步</button>
                <button class="next-btn" type="primary" @click="showPopup = true">填写内容</button>
            </view>
        <text class="footer">{{ agreementContent.footer }}</text>
        <text class="ending">{{ agreementContent.ending }}</text>
        <view class="signature">
          <text v-for="(line, i) in agreementContent.signature" :key="i" class="sign-line">{{ line }}</text>
        </view>
      </view>
    </scroll-view>
        <!-- <uni-popup ref="popup" background-color="#fff" @change="change">
            <view class="popup-content" :class="{ 'popup-height': type === 'left' || type === 'right' }"><text
                    class="text">popup 内容</text></view>
        </uni-popup> -->
        <view class="popup-mask" v-if="showPopup" @click="showPopup = false"></view>
        <view class="popup-container" v-if="showPopup" style="height: 100%;" :class="{ 'popup-show': showPopup }">
            <view class="popup-title">实名信息确认</view>
            <!-- uView 表单组件 -->
            <!-- <u-form ref="verifyForm" :model="formData" :rules="rules" labelPosition="left" labelWidth="180rpx">
                <u-form-item label="本人姓名" prop="name" required>
                    <u-input v-model="formData.name" placeholder="请输入姓名" maxlength="20"></u-input>
                </u-form-item>
                <u-form-item label="身份证号" prop="idCard" required>
                    <u-input v-model="formData.idCard" placeholder="请输入18位身份证号" maxlength="18"
                        keyboard-type="number"></u-input>
                </u-form-item>
                <u-form-item label="日期" prop="date" required>
                    <uni-datetime-picker type="datetime" v-model="formData.date" style="flex: 1;"
                        @change="onDateTimeChange">
                    </uni-datetime-picker>
                </u-form-item>
            </u-form> -->
            <view class="content" style="padding: 10rpx;">
                <view style="border: 1rpx dashed #555555;">
                    <Signature ref="sig" v-model="v"></Signature>
                </view>
                <u-button class="sign-btn" @click="startSign" type="primary" plain>开始签名</u-button>
                <!-- <text style="overflow-wrap: break-word;">{{ v }}</text> -->
            </view>
            <!-- 手动签名区域 -->
            <!-- <view class="signature-area">
                <view class="signature-title">手动签名</view>
                <view class="signature-box">
                    <text class="signature-hint" v-if="!v">要求:字迹清晰,与身份证一致</text>
                    <view class="signature-preview" v-if="v">
                        <text>签名预览</text>
                    </view>
                </view>
            </view> -->
            <!-- 底部按钮 -->
            <view class="btn-group">
                <u-button class="cancel-btn" @click="showPopup = false" type="info" plain>
                    取消
                </u-button>
                <u-button class="submit-btn" @click="handleSubmit" type="primary">
                    提交
                </u-button>
            </view>
        </view>
    <!-- 底部按钮 -->
    <view class="bottom-bar">
      <view class="btn-group">
        <button class="cancel-btn" @tap="goBack">上一步</button>
        <button class="confirm-btn" type="primary" @tap="openSign">签名确认</button>
      </view>
    </view>
    <!-- 签名组件(全屏覆盖层,不嵌套在弹窗内,避免层级冲突) -->
    <Signature ref="signatureRef" v-model="signatureData" />
    <!-- 签名预览确认弹窗(签完名后展示) -->
    <u-popup :show="showPreview" round="12" mode="center" :closeable="true" @close="showPreview = false">
      <view v-if="showPreview" class="preview-popup">
        <text class="preview-title">签名预览</text>
        <view class="preview-img-wrap">
          <image v-if="signatureData" :src="signatureData" mode="aspectFit" class="preview-img" />
          <text v-else class="no-sign">暂无签名</text>
        </view>
        <view class="preview-btns">
          <button class="re-sign-btn" @tap="reSign">重新签名</button>
          <button class="submit-btn" type="primary" :loading="submitting" @tap="handleSubmit">确认提交</button>
        </view>
      </view>
    </u-popup>
  </view>
</template>
<script>
import Signature from '@/components/sin-signature/index.vue'
import { carUploadTrip } from "@/common/examine";
import { carUploadTrip } from '@/common/examine'
const AGREEMENT_CONTENT = Object.freeze({
  title: '遵纪守法承诺书',
  intro: '因本人在香港执行出车任务,为支持配合公司对持前往香港执行出车任务人员的管理,共同维护国家和公司的声誉,本人承诺做到:',
  clauses: [
    { number: '一', text: '严格遵守中华人民共和国《海关法》、《出境入境管理法》、《出境入境边防检查条例》,香港特别行政区有关法律法规及有关外事纪律规定,保守国家及公司的商业机密。' },
    { number: '二', text: '严格遵守珠海市汇畅交通投资有限公司/珠海市海港汽车货运公司《出国(境)工作管理办法》等规章制度。' },
    { number: '三', text: '保证不利用赴港执行公务之便进行有损国家、公司形象及声誉等活动,不从事国家法律法规、香港特别行政区法律、上级主管部门或公司规章制度禁止的一切行为及活动。' },
    { number: '四', text: '保证不在出车任务时间内进行出入境旅游,不走私贩私、不携带违禁品出入境,不组织及不参与赌博、涉足色情场所、偷引渡等活动。如有发现其他人员或线索涉及违法违规活动,即向公司报告。' },
    { number: '五', text: '主动配合口岸各管理部门指挥、检查。服从口岸各管理部门指挥、检查,按规定线路行驶和停放车辆,服从调度和工作安排。' },
    { number: '六', text: '每日驾驶车辆出入境前后自觉检查,如发现人员或交通运输工具潜在安全管理隐患,或有涉及各口岸的违法犯罪人员、车辆进出动态等信息的,及时报告公司及珠海出入境边防检查站。' }
  ],
  footer: '本人如有违反,自愿接受法律法规或公司规章制度的处罚。',
  ending: '特此承诺!',
  signature: ['承诺人签字:[ ]', '日期:[ ]']
})
export default {
    data() {
        return {
            url: '',
            v: '',
            // 控制弹窗显示
            showPopup: false,
            uploadIshow: false,
            // 表单数据
            formData: {
                name: '',
                idCard: '',
                date: ''
            },
            // 签名状态
            hasSignature: false,
            // 表单验证规则
            rules: {
                name: [
                    { required: true, message: '请输入姓名', trigger: 'blur' }
                ],
                idCard: [
                    { required: true, message: '请输入身份证号', trigger: 'blur' },
                    {
                        pattern: /(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
                        message: '请输入正确的18位身份证号',
                        trigger: 'blur'
                    }
                ],
                date: [
                    { required: true, message: '请选择日期', trigger: 'blur' }
                ]
            },
            // 其他数据保持不变
            signatureUrl: '', // 签名图片地址
            hasSignature: false, // 签名状态
            // 新增:记录原始签名,用于重新签名功能
            originalSignature: ''
        };
    },
    components: {
        Signature,
    },
    methods: {
        async startSign() {
            let s = await this.$refs.sig.getSyncSignature();
            console.log('组件版本', this.$refs.sig.VERSION);
            console.log('签名数据', s);
        },
        // 返回上一页
        navigateBack() {
            uni.navigateTo({
                url: '/pages/acknowledgement/index?uploadIshow=' + this.uploadIshow
            });
        },
        // 处理签名变化(修改后)
        handleSignatureChange(url) {
            console.log(url);
            this.signatureUrl = url;
            this.originalSignature = url; // 保存原始签名
            this.hasSignature = !!url; // 有签名时更新状态
        },
        // 提交表单方法中签名验证部分保持不变
        handleSubmit() {
            if (this.v == '') {
                return uni.showToast({ title: '请完成签名', icon: 'none' });
            }
            const form = uni.getStorageSync("signContractForm");
            form.signImg = this.v
            carUploadTrip(form).then((res) => {
                if (res == 1) {
                    this.uploadIshow =true
                    uni.showToast({ title: '提交成功', icon: 'none' });
                    this.v = ''
                    this.showPopup = false;
                    setTimeout(() => {
                        wx.navigateTo({
                         url: '/pages/examine/index?id=' + form.dispatchOrderId+'&name='+'上传行程'+'&router='+'pages/beReferred/index'
                       });
                        uni.removeStorageSync("signContractForm");
  components: { Signature },
                    }, 1000);
                }else {
                    this.uploadIshow =false
                }
            });
        },
  data() {
    return {
      agreementContent: AGREEMENT_CONTENT,
      showPreview: false,
      signatureData: '',
      submitting: false,
      formData: null
    }
};
  },
  onLoad() {
    this.formData = uni.getStorageSync('signContractForm')
    if (!this.formData) {
      uni.showToast({ title: '未找到签署信息', icon: 'none' })
      setTimeout(() => this.goBack(), 1500)
    }
  },
  methods: {
    goBack() {
      const pages = getCurrentPages()
      for (let i = pages.length - 2; i >= 0; i--) {
        if (pages[i].route && pages[i].route.includes('pages/signContract')) {
          uni.navigateBack({ delta: pages.length - 1 - i })
          return
        }
      }
      uni.navigateBack({ delta: 1 })
    },
    async openSign() {
      try {
        const data = await this.$refs.signatureRef.getSyncSignature()
        if (data) {
          this.signatureData = data
          // 签完名后弹出预览确认
          this.$nextTick(() => { this.showPreview = true })
        }
      } catch {
        uni.showToast({ title: '签名失败', icon: 'none' })
      }
    },
    async reSign() {
      this.showPreview = false
      this.signatureData = ''
      // 等弹窗关闭后再打开签名
      setTimeout(() => { this.openSign() }, 300)
    },
    async handleSubmit() {
      if (!this.signatureData) {
        return uni.showToast({ title: '请完成签名', icon: 'none' })
      }
      this.submitting = true
      uni.showLoading({ title: '提交中...' })
      try {
        const form = { ...this.formData, signImg: this.signatureData }
        const res = await carUploadTrip(form)
        if (res === 1) {
          uni.showToast({ title: '提交成功', icon: 'success' })
          this.showPreview = false
          uni.removeStorageSync('signContractForm')
          // 设置刷新标志,让 operate 页面知道需要刷新数据
          uni.setStorageSync('needRefreshOperate', true)
          // 返回到 examine 页面
          setTimeout(() => {
            const pages = getCurrentPages()
            for (let i = pages.length - 2; i >= 0; i--) {
              if (pages[i].route && pages[i].route.includes('pages/examine')) {
                uni.navigateBack({ delta: pages.length - 1 - i })
                return
              }
            }
            uni.navigateBack({ delta: 1 })
          }, 1000)
        } else {
          uni.showToast({ title: '提交失败', icon: 'none' })
        }
      } catch (err) {
        uni.showToast({ title: err.message || '提交失败', icon: 'none' })
      } finally {
        this.submitting = false
        uni.hideLoading()
      }
    }
  }
}
</script>
<style scoped>
.container {
    width: 100%;
    min-height: 100vh;
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    /* 留出底部固定区域空间 */
    padding-bottom: 200rpx;
    box-sizing: border-box;
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: #ffffff;
}
/* 导航栏样式 */
.nav-bar {
    height: 88rpx;
    display: flex;
    align-items: center;
    padding: 0 30rpx;
    border-bottom: 1rpx solid #e5e5e5;
    position: relative;
    z-index: 10;
}
.back-btn image {
    width: 34rpx;
    height: 34rpx;
}
.nav-title {
    flex: 1;
    text-align: center;
    font-size: 34rpx;
    color: #333333;
    font-weight: 500;
}
/* 滚动内容区 */
.content-scroll {
    flex: 1;
    padding: 30rpx;
    box-sizing: border-box;
    /* 避免内容被底部固定区遮挡 */
    padding-bottom: 220rpx;
  flex: 1;
  padding: 30rpx;
  padding-bottom: 180rpx;
  box-sizing: border-box;
}
/* 承诺书内容 */
.agreement-content {
    line-height: 1.8;
    width: 100%;
    height: calc(100vh - 200rpx);
  line-height: 1.8;
}
.title {
    display: block;
    font-size: 32rpx;
    color: #333333;
    font-weight: 600;
    text-align: center;
    margin: 0 0 40rpx 0;
    padding-bottom: 20rpx;
    border-bottom: 1rpx solid #f0f0f0;
  display: block;
  font-size: 34rpx;
  color: #303133;
  font-weight: 600;
  text-align: center;
  margin-bottom: 30rpx;
  padding-bottom: 20rpx;
  border-bottom: 1rpx solid #f0f0f0;
}
.heading {
    display: inline;
    font-size: 28rpx;
    color: #333333;
    font-weight: 500;
.intro {
  display: block;
  font-size: 28rpx;
  color: #606266;
  margin-bottom: 20rpx;
  text-indent: 2em;
}
.paragraph {
    display: block;
    font-size: 28rpx;
    color: #666666;
    margin-bottom: 20rpx;
    text-indent: 0;
    /* 此处无需首行缩进,与条款编号配合 */
.clause {
  margin-bottom: 15rpx;
}
.clause-number {
  font-size: 28rpx;
  color: #303133;
  font-weight: 500;
}
.clause-text {
  font-size: 28rpx;
  color: #606266;
}
.footer,
.ending {
  display: block;
  font-size: 28rpx;
  color: #606266;
  margin-top: 20rpx;
  text-indent: 2em;
}
.ending {
  font-weight: 500;
  color: #303133;
}
.signature {
  margin-top: 40rpx;
}
.sign-line {
    display: block;
    font-size: 28rpx;
    color: #666666;
    margin-top: 30rpx;
    text-align: right;
    padding-right: 50rpx;
  display: block;
  font-size: 28rpx;
  color: #606266;
  margin-top: 15rpx;
  text-align: right;
  padding-right: 30rpx;
}
/* 底部固定区域 */
.bottom-fixed {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ffffff;
    border-top: 1rpx solid #f5f5f5;
    z-index: 99;
/* 底部栏 */
.bottom-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ffffff;
  border-top: 1rpx solid #f0f0f0;
  z-index: 99;
  padding-bottom: env(safe-area-inset-bottom);
}
/* 勾选区域 */
.agree-area {
    padding: 20rpx 30rpx;
}
.checkbox-group {
    display: flex;
    align-items: center;
}
.checkbox {
    width: 30rpx;
    height: 30rpx;
    margin-right: 15rpx;
}
.agree-text {
    font-size: 28rpx;
    color: #333333;
    flex: 1;
}
.required {
    font-size: 28rpx;
    color: #ff4d4f;
}
/* 底部按钮 */
.btn-group {
    padding: 30rpx;
    display: flex;
    gap: 20rpx;
}
.cancel-btn {
    flex: 1;
    height: 90rpx;
    line-height: 90rpx;
    font-size: 32rpx;
    color: #333333;
    background-color: #ffffff;
    border: 1rpx solid #e5e5e5;
    border-radius: 8rpx;
}
.next-btn {
    flex: 1;
    height: 90rpx;
    line-height: 90rpx;
    font-size: 32rpx;
    color: #ffffff;
    background-color: #1677ff;
    border: none;
    border-radius: 8rpx;
}
.next-btn[disabled] {
    background-color: #c9d8e9;
    opacity: 0.7;
}
/* 实名 */
.container {
    width: 100%;
    min-height: 100vh;
    background-color: #f5f5f5;
    display: flex;
    flex-direction: column;
}
/* 主页面样式 */
.main-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 30rpx;
    padding: 30rpx;
}
.open-btn {
    width: 60%;
    height: 80rpx;
    line-height: 80rpx;
    background-color: #1677ff;
    color: #ffffff;
    border-radius: 40rpx;
    font-size: 30rpx;
}
/* 弹窗样式 */
.popup-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 998;
    transition: opacity 0.3s;
}
.popup-container {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ffffff;
    border-top-left-radius: 20rpx;
    border-top-right-radius: 20rpx;
    z-index: 999;
    padding: 30rpx;
    box-sizing: border-box;
    transform: translateY(100%);
    transition: transform 0.3s ease-out;
    max-height: 90vh;
    overflow-y: auto;
}
.popup-show {
    transform: translateY(0);
}
.popup-title {
    font-size: 34rpx;
    color: #333333;
    font-weight: 600;
    text-align: center;
    margin-bottom: 40rpx;
    padding-bottom: 20rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
/* 签名区域 */
.signature-area {
    display: flex;
    flex-direction: column;
    gap: 20rpx;
    margin-top: 20rpx;
    padding-top: 20rpx;
    border-top: 1rpx solid #f0f0f0;
}
.signature-title {
    font-size: 28rpx;
    color: #333333;
    margin-bottom: 10rpx;
}
.signature-box {
    width: 100%;
    height: 200rpx;
    border: 1rpx dashed #e5e5e5;
    border-radius: 8rpx;
    display: flex;
    justify-content: center;
    align-items: center;
}
.signature-hint {
    font-size: 26rpx;
    color: #999999;
    text-align: center;
}
.signature-preview {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #f9f9f9;
    font-size: 26rpx;
    color: #666666;
}
.sign-btn {
    margin-top: 10rpx;
}
/* 底部按钮 */
.btn-group {
    display: flex;
    gap: 20rpx;
    margin-top: 40rpx;
  display: flex;
  gap: 20rpx;
  padding: 20rpx 30rpx 20rpx;
}
.cancel-btn,
.submit-btn {
    flex: 1;
    height: 90rpx;
    line-height: 90rpx;
    font-size: 32rpx;
.confirm-btn {
  flex: 1;
  height: 88rpx;
  line-height: 88rpx;
  font-size: 30rpx;
  border-radius: 12rpx;
  border: none;
  font-weight: 500;
}
/* 签名区域样式 */
/* 仅修改签名区域相关样式 */
</style>
.cancel-btn {
  color: #606266;
  background-color: #f5f7fa;
}
.cancel-btn::after,
.confirm-btn::after {
  border: none;
}
.confirm-btn {
  color: #fff;
  background-color: #4285f4;
}
/* 签名预览弹窗 */
.preview-popup {
  width: 600rpx;
  padding: 40rpx;
}
.preview-title {
  display: block;
  font-size: 32rpx;
  font-weight: 600;
  color: #303133;
  text-align: center;
  margin-bottom: 30rpx;
}
.preview-img-wrap {
  width: 100%;
  height: 300rpx;
  border: 2rpx dashed #dcdfe6;
  border-radius: 12rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #fafafa;
  overflow: hidden;
}
.preview-img {
  width: 100%;
  height: 100%;
}
.no-sign {
  color: #c0c4cc;
  font-size: 28rpx;
}
.preview-btns {
  display: flex;
  gap: 20rpx;
  margin-top: 30rpx;
}
.re-sign-btn,
.submit-btn {
  flex: 1;
  height: 80rpx;
  line-height: 80rpx;
  font-size: 28rpx;
  border-radius: 10rpx;
  border: none;
}
.re-sign-btn {
  color: #606266;
  background-color: #f5f7fa;
}
.re-sign-btn::after,
.submit-btn::after {
  border: none;
}
.submit-btn {
  color: #fff;
  background-color: #4285f4;
}
</style>