<template>
|
<div class="bijnm">
|
<div class="headf">
|
<div>
|
<h2>
|
<span class="hbnh"><a class="fan" @click="$router.back()"></a></span>
|
{{ title }}
|
</h2>
|
</div>
|
</div>
|
<div class="hezi" v-show="type == '1'">
|
<img src="@/assets/img/yyzz.png" />
|
<h6>{{ $t("jy321") }}</h6>
|
<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">
|
<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>
|
</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,
|
PdfViewerModern,
|
ImageViewer
|
},
|
created() {
|
var that = this;
|
//接收页面传值
|
console.log(this.$route.query.e);
|
if (this.$route.query.e) {
|
switch (this.$route.query.e) {
|
case "1":
|
this.title = this.$t("jy318");
|
break;
|
case "2":
|
this.title = this.$t("jy546");
|
break;
|
case "3":
|
this.title = this.$t("jy316");
|
break;
|
case "4":
|
this.title = this.$t("jy314");
|
break;
|
case "5":
|
this.title = this.$t("jy192");
|
break;
|
case "6":
|
this.title = this.$t("jy315");
|
break;
|
case "7":
|
this.title = this.$t("jy547");
|
break;
|
default:
|
break;
|
}
|
this.type = this.$route.query.e;
|
}
|
},
|
data() {
|
return {
|
title: this.$t("jy314"),
|
type: 0,
|
userInfo: {},
|
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
|
};
|
},
|
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;
|
}
|
// 获取当前登录用户信息
|
let userData = await api.getUserInfo();
|
if (userData.status === 0) {
|
this.currentUser = userData.data;
|
this.$store.state.userInfo = userData.data;
|
}
|
},
|
initSignaturePad() {
|
this.$nextTick(() => {
|
if (this.$refs.mySignaturePad) {
|
this.signatureInstance = this.$refs.mySignaturePad.signaturePad;
|
}
|
});
|
},
|
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;
|
}
|
},
|
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);
|
}
|
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;
|
}
|
}
|
}
|
};
|
</script>
|
|
|
<style scoped>
|
.agreement-page {
|
padding: 20px;
|
max-width: 800px;
|
margin: 0 auto;
|
}
|
.agreement-content {
|
margin-bottom: 30px;
|
}
|
.agreement-text {
|
height: 200px;
|
overflow-y: auto;
|
padding: 10px;
|
border: 1px solid #eee;
|
margin: 10px 0;
|
}
|
.agreement-check {
|
margin: 10px 0;
|
font-size: 14px;
|
}
|
.signature-area {
|
margin: 20px 0;
|
}
|
.signature-canvas {
|
width: 100%;
|
height: 200px;
|
border: 1px dashed #ccc;
|
margin: 10px 0;
|
}
|
.signature-btns {
|
margin: 10px 0;
|
}
|
.btn-clear, .btn-confirm {
|
padding: 8px 16px;
|
margin-right: 10px;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
.btn-clear {
|
background: #eee;
|
color: #333;
|
}
|
.btn-confirm {
|
background: #409eff;
|
color: #fff;
|
}
|
.btn-confirm:disabled {
|
background: #ccc;
|
cursor: not-allowed;
|
}
|
.signature-preview {
|
margin-top: 20px;
|
}
|
.signature-preview img {
|
max-width: 300px;
|
border: 1px solid #eee;
|
}
|
.modal {
|
position: fixed;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0, 0, 0, 0.8);
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
z-index: 1000;
|
}
|
|
.modal-content {
|
position: relative;
|
max-width: 90%;
|
max-height: 90%;
|
}
|
|
.enlarged-image {
|
max-width: 100%;
|
max-height: 80vh;
|
display: block;
|
}
|
|
.bijnm {
|
background: #fff;
|
min-height: 100vh;
|
width: 100%;
|
max-width: 100%;
|
box-sizing: border-box;
|
}
|
|
.headf {
|
width: 100%;
|
height: 1.1748rem;
|
background: linear-gradient(-55deg, rgb(241, 22, 20), rgb(240, 40, 37));
|
}
|
|
h2 {
|
text-align: center;
|
height: 1.2549rem;
|
width: 100%;
|
position: relative;
|
line-height: 1.2549rem;
|
font-size: 0.4806rem;
|
color: #fff;
|
background: transparent;
|
font-weight: 500;
|
z-index: 3;
|
}
|
|
.hbnh {
|
position: absolute;
|
left: 0.4005rem;
|
font-size: 0.4272rem;
|
font-weight: 500;
|
}
|
|
.fan {
|
width: 0.2403rem;
|
height: 0.4272rem;
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAYAAAAffCjxAAAAAXNSR0IArs4c6QAAAVdJREFUSEut1usqBVEYxvH/c1MuRJJDkhwTEpIkJUlyCEk++CJJckpycw49Gs3Wa+y9Z82ePd/Xr5n38KwRNR7bE0APMK1OHdtTwAWQGZcdQbZngPMc+QImK0O2Z4GzgIxLuqoE2Z4DTgMyJuk6K08yZHseOAnIqKSbRo2TINsLwHFARiTdxkaVQrYXgaOADEu6K3a7LWR7CTjMD2XdaYq0rZHtFWA/Rz6BIUn3reau6RvZXgX28kMfOfLQbnj/QbbXgN380HuOPJZtwB/I9jqwE5ABSc9lyJ8a2d4AtgPSL+klBfmFbG8CWwHpk/SaivxAtjMgg7Inq0mvpLcqSHehTOvKpzU+oSvFDlj99gesOJCDkp7Kip+yIknT3XL7C0tbum9lMbIMHKQkQEqwJWVSKZTPWTElq0dt6GYxt6uHf8DqX0cBq39BBqz+lR2w+j8RAfv9rfkGqF24CUdT9E4AAAAASUVORK5CYII=)
|
no-repeat 50%;
|
background-size: 100%;
|
display: inline-block;
|
margin-right: 0.1335rem;
|
vertical-align: middle;
|
margin-top: -0.0534rem;
|
}
|
|
.hezi {
|
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>
|