From fa821ce7a7755dd0e13897cefc57071d4596431b Mon Sep 17 00:00:00 2001
From: jhzh <1628036192@qq.com>
Date: Wed, 14 Jan 2026 17:51:42 +0800
Subject: [PATCH] 1

---
 src/page/newUser/about.vue |  788 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 688 insertions(+), 100 deletions(-)

diff --git a/src/page/newUser/about.vue b/src/page/newUser/about.vue
index 31737ab..97f65d5 100644
--- a/src/page/newUser/about.vue
+++ b/src/page/newUser/about.vue
@@ -11,68 +11,98 @@
     <div class="hezi" v-show="type == '1'">
       <img src="@/assets/img/yyzz.png" />
       <h6>{{ $t("jy321") }}</h6>
-      <p>{{ $t("jy320") }}:V1.1.2</p>
+      <p>{{ $t("jy320") }}: V1.1.2</p>
     </div>
     <div v-show="type != '1'" class="hezi" style="line-height: 0.5rem;">
-      <div v-if="type == 2" v-html="userInfo.companyInfo"></div>
+      <div v-if="type == 2">
+        <div v-if="generating" class="loading-container">
+          <div class="loading-spinner"></div>
+          <p class="loading-text">{{ $t('jy526') }}</p>
+        </div>
+        <div v-else-if="!hasAgreementPdf" style="text-align: center; padding: 20px;">
+          <!-- <button @click="handleGeneratePdf" class="btn-generate" :disabled="generating">
+            生成用户合同
+          </button> -->
+        </div>
+        <div v-else class="agreement-container">
+          <ImageViewer :imageUrls="imageUrls" v-if="imageUrls && imageUrls.length > 0" />
+          <div class="signature-section" v-if="showSignature && !isSigned">
+            <h4>{{ $t('jy527') }}</h4>
+            <vue-signature-pad
+              ref="mySignaturePad"
+              class="signature-canvas"
+              :options="signatureOptions"
+            ></vue-signature-pad>
+            <div class="signature-btns">
+              <button @click="clearSignature" class="btn-clear" :disabled="submittingSignature">{{ $t('jy528') }}</button>
+              <button @click="confirmSignature" class="btn-confirm" :disabled="submittingSignature">{{ $t('jy529') }}</button>
+            </div>
+          </div>
+          <div v-else-if="!isSigned" class="signature-action">
+            <button @click="showSignature = true" class="btn-signature">{{ $t('jy529') }}</button>
+          </div>
+          <div v-if="isSigned" class="signature-tip">
+            <p>{{ $t('jy530') }}</p>
+          </div>
+        </div>
+      </div>
       <div v-else-if="type == 3" v-html="userInfo.certImg1"></div>
       <div v-else-if="type == 4" v-html="userInfo.certImg2"></div>
       <div v-else-if="type == 5" v-html="userInfo.tradeAgreeText"></div>
       <div v-else-if="type == 6">{{ $t("jy319") }}</div>
+      <div v-else-if="type == 7">
+        <div v-if="generatingContract" class="loading-container">
+          <div class="loading-spinner"></div>
+          <p class="loading-text">{{ $t('jy526') }}</p>
+        </div>
+        <div v-else-if="!hasContractPdf" style="text-align: center; padding: 20px;">
+          <!-- <button @click="handleGenerateContractPdf" class="btn-generate" :disabled="generatingContract">
+            生成用户合同
+          </button> -->
+        </div>
+        <div v-else class="agreement-container">
+          <ImageViewer :imageUrls="contractImageUrls" v-if="contractImageUrls && contractImageUrls.length > 0" />
+          <div class="signature-section" v-if="showContractSignature && !isContractSigned">
+            <h4>{{ $t('jy527') }}</h4>
+            <vue-signature-pad
+              ref="contractSignaturePad"
+              class="signature-canvas"
+              :options="signatureOptions"
+            ></vue-signature-pad>
+            <div class="signature-btns">
+              <button @click="clearContractSignature" class="btn-clear" :disabled="submittingContractSignature">{{ $t('jy528') }}</button>
+              <button @click="confirmContractSignature" class="btn-confirm" :disabled="submittingContractSignature">{{ $t('jy529') }}</button>
+            </div>
+          </div>
+          <div v-else-if="!isContractSigned" class="signature-action">
+            <button @click="showContractSignature = true" class="btn-signature">{{ $t('jy529') }}</button>
+          </div>
+          <div v-if="isContractSigned" class="signature-tip">
+            <p>{{ $t('jy530') }}</p>
+          </div>
+        </div>
+      </div>
       <div v-else></div>
 	  <!-- <img src="@/assets/img/yyzz.png" style="width: 100%;" /> -->
-	  
-    </div>
-	<div>
-	    <!-- 原始图片,点击可放大 -->
-	    <img 
-	      src="@/assets/img/yyzz.png" 
-	      style="width: 100%; cursor: pointer;" 
-	      @click="showModal = true"
-	    />
 
-<!-- <div class="signature-area">
-      <h4>请完成电子签名</h4>
-      <vue-signature-pad
-        ref="mySignaturePad"
-        class="signature-canvas"
-        :options="signatureOptions"
-      ></vue-signature-pad>
-      <div class="signature-btns">
-        <button @click="clearSignature" class="btn-clear">清空签名</button>
-        <button @click="confirmSignature" class="btn-confirm" :disabled="!isAgree || !hasSignature">确认签名</button>
-      </div>
     </div>
-
-    <div class="signature-preview" v-if="signatureImg">
-      <h4>签名预览</h4>
-      <img :src="signatureImg" alt="电子签名" />
-    </div> -->
-      
-	
-	    <!-- 模态框,用于显示放大的图片 -->
-	    <div 
-	      v-if="showModal" 
-	      class="modal" 
-	      @click.self="showModal = false"
-	    >
-	      <div class="modal-content">
-	        <img 
-	          :src="require('@/assets/img/yyzz.png')" 
-	          class="enlarged-image"
-	        />
-	      </div>
-	    </div>
-	  </div>
   </div>
 </template>
 <script>
 import * as api from "@/axios/api";
 import VueSignaturePad from 'vue-signature-pad'
+import PdfViewerModern from '@/components/PdfViewerModern.vue'
+import ImageViewer from '@/components/ImageViewer.vue'
+import axios from '@/axios/index'
+import APIUrl from '@/axios/api.url'
+import { Toast } from 'mint-ui'
+
 export default {
   name: "about",
   components: {
-    VueSignaturePad
+    VueSignaturePad,
+    PdfViewerModern,
+    ImageViewer
   },
   created() {
     var that = this;
@@ -84,7 +114,7 @@
           this.title = this.$t("jy318");
           break;
         case "2":
-          this.title = this.$t("jy317");
+          this.title = this.$t("jy546");
           break;
         case "3":
           this.title = this.$t("jy316");
@@ -98,6 +128,9 @@
         case "6":
           this.title = this.$t("jy315");
           break;
+        case "7":
+          this.title = this.$t("jy547");
+          break;
         default:
           break;
       }
@@ -109,75 +142,513 @@
       title: this.$t("jy314"),
       type: 0,
       userInfo: {},
-	  showModal: false,
-	  signatureImg: '',
-	  isAgree: false,
-	  hasSignature: false,
-	  signatureOptions: {
-		penColor: '#000000',
-		penWidth: 2,
-	  },
-    signatureInstance: null
+      signatureImg: '',
+      hasSignature: false,
+      signatureOptions: {
+        penColor: '#000000',
+        penWidth: 2,
+      },
+      signatureInstance: null,
+      hasAgreementPdf: false,
+      generating: false,
+      pdfUrl: '',
+      imageUrls: [],
+      showSignature: false,
+      currentUser: null,
+      hasContractPdf: false,
+      generatingContract: false,
+      contractPdfUrl: '',
+      contractImageUrls: [],
+      showContractSignature: false,
+      contractSignatureInstance: null,
+      submittingSignature: false,
+      submittingContractSignature: false
     };
   },
-  mounted() {
-    this.getUserInfo();
-    // vue-signature-pad@2.x 的实例在 this.$refs.xxx.signaturePad 里
-    this.signatureInstance = this.$refs.mySignaturePad.signaturePad
-    // 监听签名变化,更新 hasSignature 状态
-    this.$refs.mySignaturePad.$on('signatureChanged', (isEmpty) => {
-      this.hasSignature = !isEmpty
-    })
+  computed: {
+    isSigned() {
+      // 判断是否已签名:检查isSignedContract字段是否不为空
+      return this.currentUser && this.currentUser.isSignedContract && this.currentUser.isSignedContract.trim() !== '';
+    },
+    isContractSigned() {
+      // 判断保密协议是否已签名:检查isSignedAgreement字段是否等于'Y'
+      return this.currentUser && this.currentUser.isSignedAgreement === 'Y';
+    },
+    pdfIframeSrc() {
+      if (!this.pdfUrl) return '';
+      const token = typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('USERTOKEN') || '' : '';
+      return this.pdfUrl + '?token=' + token;
+    }
+  },
+  async mounted() {
+    if(this.type != 3) {
+    await this.getUserInfo();
+    }else{
+      let data = await api.getInfoSite();
+      if (data.status === 0) {
+        this.userInfo = data.data;
+      }
+    }
+    if (this.type == 2) {
+      this.checkAgreementPdf();
+    } else if (this.type == 7) {
+      this.checkContractPdf();
+    }
+  },
+  watch: {
+    showSignature(newVal) {
+      if (newVal) {
+        // 当显示签名区域时,初始化签名组件
+        this.$nextTick(() => {
+          this.initSignaturePad();
+        });
+      }
+    },
+    showContractSignature(newVal) {
+      if (newVal) {
+        // 当显示合同签名区域时,初始化签名组件
+        this.$nextTick(() => {
+          this.initContractSignaturePad();
+        });
+      }
+    }
   },
   methods: {
+    isAuthenticated() {
+      // 判断是否已实名认证:isActive === 1 (审核中) 或 isActive === 2 (已通过)
+      const userInfo = this.currentUser || this.$store.state.userInfo;
+      return userInfo && (userInfo.isActive === 1 || userInfo.isActive === 2);
+    },
     async getUserInfo() {
       // 获取用户信息
       let data = await api.getInfoSite();
       if (data.status === 0) {
         this.userInfo = data.data;
-      } else {
+      }
+      // 获取当前登录用户信息
+      let userData = await api.getUserInfo();
+      if (userData.status === 0) {
+        this.currentUser = userData.data;
+        this.$store.state.userInfo = userData.data;
       }
     },
-    // 清空签名(调用真实实例的方法)
-    clearSignature() {
-      if (this.signatureInstance) {
-        this.signatureInstance.clear()
-        this.signatureImg = ''
-        this.hasSignature = false
-      } else {
-        alert('签名组件未初始化!')
-      }
-    },
-    // 确认签名(调用真实实例的方法)
-    confirmSignature() {
-      if (!this.isAgree) {
-        alert('请先阅读并同意用户协议!')
-        return
-      }
-      if (this.signatureInstance) {
-        // 检查是否有签名
-        if (!this.signatureInstance.isEmpty()) {
-          // 导出 Base64 图片
-          this.signatureImg = this.signatureInstance.toDataURL('image/png')
-          this.hasSignature = true
-          this.submitAgreement()
-        } else {
-          alert('请先完成电子签名!')
+    initSignaturePad() {
+      this.$nextTick(() => {
+        if (this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
         }
-      } else {
-        alert('签名组件未初始化!')
+      });
+    },
+    clearSignature() {
+      this.$nextTick(() => {
+        if (!this.signatureInstance && this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
+        }
+        if (this.signatureInstance) {
+          this.signatureInstance.clear();
+          this.signatureImg = '';
+          this.hasSignature = false;
+        }
+      });
+    },
+    confirmSignature() {
+      // 防止重复点击
+      if (this.submittingSignature) {
+        return;
+      }
+      this.$nextTick(() => {
+        if (!this.signatureInstance && this.$refs.mySignaturePad) {
+          this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
+        }
+        if (this.signatureInstance) {
+          if (!this.signatureInstance.isEmpty()) {
+            this.signatureImg = this.signatureInstance.toDataURL('image/png');
+            this.hasSignature = true;
+            this.submitAgreement();
+          } else {
+          this.$message.error(this.$t('jy554'));
+          }
+        } else {
+          this.$message.error(this.$t('jy555'));
+
+        }
+      });
+    },
+    async submitAgreement() {
+      // 防止重复提交
+      if (this.submittingSignature) {
+        return;
+      }
+      this.submittingSignature = true;
+      try {
+        const blob = await this.dataURLtoBlob(this.signatureImg);
+        const formData = new FormData();
+        formData.append('signature', blob, 'signature.png');
+
+        const config = {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        };
+
+        if (window.localStorage.getItem("USERTOKEN")) {
+          config.headers["USERTOKEN"] = window.localStorage.getItem("USERTOKEN");
+        }
+
+        const result = await axios.post(APIUrl.baseURL + '/user/saveAgreementSignature.do', formData, config);
+
+        if (result.data.status === 0) {
+          this.$message.success(this.$t('jy556'));
+          this.showSignature = false;
+          // 重新获取用户信息,更新签名状态
+          let userData = await api.getUserInfo();
+          if (userData.status === 0) {
+            this.currentUser = userData.data;
+            this.$store.state.userInfo = userData.data;
+          }
+          // 延迟跳转,让用户看到成功提示
+          setTimeout(() => {
+            this.$router.push('/User');
+          }, 1500);
+        } else {
+          this.$message.error(result.data.msg || this.$t('jy557'));
+          this.submittingSignature = false;
+        }
+      } catch (error) {
+        console.error('提交签名失败:', error);
+        this.$message.error(this.$t('jy557'));
+        this.submittingSignature = false;
       }
     },
-    // 提交协议
-    submitAgreement() {
-      const submitData = {
-        userId: '当前用户ID',
-        isAgree: this.isAgree,
-        signature: this.signatureImg,
-        agreeTime: new Date().getTime()
+    dataURLtoBlob(dataurl) {
+      const arr = dataurl.split(',');
+      const mime = arr[0].match(/:(.*?);/)[1];
+      const bstr = atob(arr[1]);
+      let n = bstr.length;
+      const u8arr = new Uint8Array(n);
+      while (n--) {
+        u8arr[n] = bstr.charCodeAt(n);
       }
-      console.log('提交数据:', submitData)
-      alert('签名成功,协议已提交!')
+      return new Blob([u8arr], { type: mime });
+    },
+    async checkAgreementPdf() {
+      try {
+        // type == 2 是线上合同
+        if (this.type == 2) {
+          const APIUrl = require('@/axios/api.url').default;
+          
+          // 如果已签名(isSignedContract === 'Y'),调用viewAgreementPdf接口获取已签名的图片
+          if (this.currentUser && this.currentUser.isSignedContract === 'Y') {
+            this.generating = true;
+            let result = await api.viewAgreementPdf();
+            console.log('viewAgreementPdf返回结果:', result);
+            if (result.status === 0) {
+              this.hasAgreementPdf = true;
+              // result.data 现在是图片数组
+              if (Array.isArray(result.data) && result.data.length > 0) {
+                this.imageUrls = result.data.map(url => {
+                  if (!url.startsWith('http')) {
+                    return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                  }
+                  return url;
+                });
+                console.log('处理后的图片URLs:', this.imageUrls);
+              } else {
+                console.warn('未返回图片数据或数据为空');
+                this.hasAgreementPdf = false;
+              }
+            } else {
+              console.error('接口返回错误:', result.msg);
+              this.hasAgreementPdf = false;
+            }
+            this.generating = false;
+            return;
+          }
+          
+          // 如果未签名(isSignedContract为空),调用generateAgreementPdf接口生成并渲染图片
+          this.generating = true;
+          let result = await api.generateAgreementPdf();
+          if (result.status === 0) {
+            this.hasAgreementPdf = true;
+            // result.data 现在是图片数组
+            if (Array.isArray(result.data) && result.data.length > 0) {
+              this.imageUrls = result.data.map(url => {
+                if (!url.startsWith('http')) {
+                  return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                }
+                return url;
+              });
+            } else {
+              this.hasAgreementPdf = false;
+            }
+          } else {
+            this.hasAgreementPdf = false;
+          }
+          this.generating = false;
+          return;
+        }
+
+        // 其他type的处理逻辑
+        // 如果已签名,直接使用已签名的PDF
+        if (this.isSigned && this.currentUser && this.currentUser.isSignedContract) {
+          this.hasAgreementPdf = true;
+          let url = this.currentUser.isSignedContract;
+          if (!url.startsWith('http')) {
+            url = APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+          }
+          this.pdfUrl = url;
+          return;
+        }
+
+        // 未签名,生成新的PDF
+        this.generating = true;
+        let result = await api.generateAgreementPdf();
+        if (result.status === 0) {
+          this.hasAgreementPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.imageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+          } else {
+            this.hasAgreementPdf = false;
+          }
+        } else {
+          this.hasAgreementPdf = false;
+        }
+      } catch (e) {
+        this.hasAgreementPdf = false;
+      } finally {
+        this.generating = false;
+      }
+    },
+    async handleGeneratePdf() {
+      this.generating = true;
+      try {
+        let result = await api.generateAgreementPdf();
+        if (result.status === 0) {
+          this.hasAgreementPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.imageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+            this.$message.success(this.$t('jy558'));
+          } else {
+            this.$message.error(this.$t('jy559'));
+          }
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generating = false;
+      }
+    },
+    initContractSignaturePad() {
+      this.$nextTick(() => {
+        if (this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+      });
+    },
+    clearContractSignature() {
+      this.$nextTick(() => {
+        if (!this.contractSignatureInstance && this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+        if (this.contractSignatureInstance) {
+          this.contractSignatureInstance.clear();
+        }
+      });
+    },
+    confirmContractSignature() {
+      // 防止重复点击
+      if (this.submittingContractSignature) {
+        return;
+      }
+      this.$nextTick(() => {
+        if (!this.contractSignatureInstance && this.$refs.contractSignaturePad) {
+          this.contractSignatureInstance = this.$refs.contractSignaturePad.signaturePad;
+        }
+        if (this.contractSignatureInstance) {
+          if (!this.contractSignatureInstance.isEmpty()) {
+            const signatureImg = this.contractSignatureInstance.toDataURL('image/png');
+            this.submitContractAgreement(signatureImg);
+          } else {
+            this.$message.error(this.$t('jy554'));
+          }
+        } else {
+          this.$message.error(this.$t('jy555'));
+        }
+      });
+    },
+    async submitContractAgreement(signatureImg) {
+      // 防止重复提交
+      if (this.submittingContractSignature) {
+        return;
+      }
+      this.submittingContractSignature = true;
+      try {
+        const blob = await this.dataURLtoBlob(signatureImg);
+        const formData = new FormData();
+        formData.append('signature', blob, 'signature.png');
+
+        const config = {
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        };
+
+        if (window.localStorage.getItem("USERTOKEN")) {
+          config.headers["USERTOKEN"] = window.localStorage.getItem("USERTOKEN");
+        }
+
+        const result = await axios.post(APIUrl.baseURL + '/user/saveAgreementContractSignature.do', formData, config);
+
+        if (result.data.status === 0) {
+          this.$message.success(this.$t('jy556'));
+          this.showContractSignature = false;
+          // 重新获取用户信息,更新签名状态
+          let userData = await api.getUserInfo();
+          if (userData.status === 0) {
+            this.currentUser = userData.data;
+            this.$store.state.userInfo = userData.data;
+          }
+          // 延迟跳转,让用户看到成功提示
+          setTimeout(() => {
+            this.$router.push('/User');
+          }, 1500);
+        } else {
+          this.$message.error(result.data.msg || this.$t('jy557'));
+          this.submittingContractSignature = false;
+        }
+      } catch (error) {
+        console.error('提交合同签名失败:', error);
+        this.$message.error(this.$t('jy557'));
+        this.submittingContractSignature = false;
+      }
+    },
+    async checkContractPdf() {
+      try {
+        // type == 7 是保密协议
+        if (this.type == 7) {
+          const APIUrl = require('@/axios/api.url').default;
+          
+          // 判断是否已签名:isSignedAgreement === 'Y'
+          const isSigned = this.currentUser && this.currentUser.isSignedAgreement === 'Y';
+          
+          if (isSigned) {
+            // 如果已签名,调用viewAgreementContractPdf接口获取已签名的图片(从数据库查询)
+            this.generatingContract = true;
+            let result = await api.viewAgreementContractPdf();
+            console.log('viewAgreementContractPdf返回结果:', result);
+            if (result.status === 0) {
+              this.hasContractPdf = true;
+              // result.data 现在是图片数组
+              if (Array.isArray(result.data) && result.data.length > 0) {
+                this.contractImageUrls = result.data.map(url => {
+                  if (!url.startsWith('http')) {
+                    return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                  }
+                  return url;
+                });
+                console.log('处理后的图片URLs:', this.contractImageUrls);
+              } else {
+                console.warn('未返回图片数据或数据为空');
+                this.hasContractPdf = false;
+              }
+            } else {
+              console.error('接口返回错误:', result.msg);
+              this.hasContractPdf = false;
+            }
+            this.generatingContract = false;
+            return;
+          }
+          
+          // 如果未签名(isSignedAgreement为空),调用generateAgreementContractPdf接口生成并渲染图片
+          this.generatingContract = true;
+          let result = await api.generateAgreementContractPdf();
+          if (result.status === 0) {
+            this.hasContractPdf = true;
+            // result.data 现在是图片数组
+            if (Array.isArray(result.data) && result.data.length > 0) {
+              this.contractImageUrls = result.data.map(url => {
+                if (!url.startsWith('http')) {
+                  return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+                }
+                return url;
+              });
+            } else {
+              this.hasContractPdf = false;
+            }
+          } else {
+            this.hasContractPdf = false;
+          }
+          this.generatingContract = false;
+          return;
+        }
+      } catch (e) {
+        console.error('checkContractPdf错误:', e);
+        this.hasContractPdf = false;
+      } finally {
+        this.generatingContract = false;
+      }
+    },
+    async handleGenerateContractPdf() {
+      this.generatingContract = true;
+      try {
+        let result = await api.generateAgreementContractPdf();
+        if (result.status === 0) {
+          this.hasContractPdf = true;
+          // result.data 现在是图片数组
+          if (Array.isArray(result.data) && result.data.length > 0) {
+            this.contractImageUrls = result.data.map(url => {
+              if (!url.startsWith('http')) {
+                return APIUrl.baseURL + (url.startsWith('/') ? url : '/' + url);
+              }
+              return url;
+            });
+            this.$message.success(this.$t('jy558'));
+          } else {
+            this.$message.error(this.$t('jy559'));
+          }
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generatingContract = false;
+      }
+    },
+    async handleGenerateContractPdfOld() {
+      this.generatingContract = true;
+      try {
+        let result = await api.generateAgreementContractPdf();
+        if (result.status === 0) {
+          this.hasContractPdf = true;
+          let url = result.data || '/user/viewAgreementContractPdf.do';
+          if (!url.startsWith('http')) {
+            url = APIUrl.baseURL + url;
+          }
+          this.contractPdfUrl = url;
+          this.$message.success(this.$t('jy558'));
+        } else {
+          this.$message.error(result.msg || this.$t('jy560'));
+        }
+      } catch (e) {
+        this.$message.error(this.$t('jy560') + ': ' + e.message);
+      } finally {
+        this.generatingContract = false;
+      }
     }
   }
 };
@@ -270,6 +741,9 @@
 .bijnm {
   background: #fff;
   min-height: 100vh;
+  width: 100%;
+  max-width: 100%;
+  box-sizing: border-box;
 }
 
 .headf {
@@ -311,14 +785,128 @@
 }
 
 .hezi {
-  width: 9.2115rem;
+  width: 100%;
+  max-width: 100%;
+  padding: 0 20px;
   border-bottom: 0.0267rem solid #e0e0e0;
   margin: 0 auto;
   margin-top: 1.1748rem;
   padding-bottom: 0.534rem;
+  box-sizing: border-box;
 }
 
 .hezi img {
   width: 5rem;
 }
+
+.btn-generate, .btn-view {
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 16px;
+  cursor: pointer;
+}
+
+.btn-generate:disabled {
+  background: #ccc;
+  cursor: not-allowed;
+}
+
+.agreement-container {
+  padding: 0;
+  width: 100%;
+  max-width: 100%;
+  box-sizing: border-box;
+  height: calc(100vh - 1.1748rem - 100px);
+  max-height: calc(100vh - 1.1748rem - 100px);
+  margin-top: -20px;
+}
+
+
+.signature-section {
+  margin-top: 20px;
+  padding: 20px;
+  background: #f9f9f9;
+  border-radius: 5px;
+}
+
+.signature-section h4 {
+  margin-bottom: 15px;
+  font-size: 18px;
+  font-weight: bold;
+}
+
+.signature-canvas {
+  width: 100%;
+  height: 300px;
+  border: 2px dashed #ccc;
+  margin: 15px 0;
+  background: #fff;
+  border-radius: 5px;
+}
+
+.signature-btns {
+  display: flex;
+  gap: 10px;
+  margin-top: 10px;
+}
+
+.btn-signature {
+  padding: 10px 20px;
+  background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
+  color: #fff;
+  border: none;
+  border-radius: 5px;
+  font-size: 16px;
+  cursor: pointer;
+  width: 100%;
+  margin-top: 20px;
+}
+
+.signature-tip {
+  margin-top: 20px;
+  padding: 15px;
+  background: #e8f5e9;
+  border-radius: 5px;
+  text-align: center;
+}
+
+.signature-tip p {
+  margin: 0;
+  color: #4caf50;
+  font-size: 16px;
+  font-weight: bold;
+}
+
+.loading-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 60px 20px;
+  min-height: 300px;
+}
+
+.loading-spinner {
+  width: 50px;
+  height: 50px;
+  border: 4px solid #f3f3f3;
+  border-top: 4px solid rgb(241, 22, 20);
+  border-radius: 50%;
+  animation: spin 1s linear infinite;
+  margin-bottom: 20px;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+  color: #666;
+  font-size: 16px;
+  margin-top: 10px;
+}
 </style>

--
Gitblit v1.9.3