| | |
| | | <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; |
| | |
| | | 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"); |
| | |
| | | case "6": |
| | | this.title = this.$t("jy315"); |
| | | break; |
| | | case "7": |
| | | this.title = this.$t("jy547"); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | |
| | | .bijnm { |
| | | background: #fff; |
| | | min-height: 100vh; |
| | | width: 100%; |
| | | max-width: 100%; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .headf { |
| | |
| | | } |
| | | |
| | | .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> |