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