426 lines
10 KiB
Vue
426 lines
10 KiB
Vue
<template>
|
|
<view class="asset-page asset-theme bmt-agree-page">
|
|
<asset-page-shell title="签约协议" />
|
|
|
|
<view v-if="signStatus">
|
|
<view class="bmt-agree-content glass-panel">
|
|
<scroll-view class="bmt-agree-scroll" scroll-y :style="{ height: scrollViewHeight + 'px' }"
|
|
:scroll-with-animation="false" :show-scrollbar="false" @scroll="handleScroll">
|
|
<text class="bmt-agree-title">{{ signData.name }}</text>
|
|
<view class="bmt-agree-desc">
|
|
<text class="bmt-agree-text">{{ signData.content || "暂无协议内容" }}</text>
|
|
<view v-if="!isReachBottom" class="bmt-agree-tip">请阅读到底部后签约</view>
|
|
<view class="bmt-agree-padding"></view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<view class="bmt-agree-bottom">
|
|
<text class="bmt-agree-bottom__hint">{{ isReachBottom ? "已阅读到底部" : "向下滑动阅读签约" }}</text>
|
|
<view class="bmt-agree-bottom__row">
|
|
<view class="bmt-agree-btn bmt-agree-btn--ghost" @click="cancel">取消</view>
|
|
<view class="bmt-agree-btn bmt-agree-btn--primary"
|
|
:class="{ 'is-disabled': !isReachBottom || signing }" @click="toSign">
|
|
{{ signing ? "签约中..." : "确认签约" }}
|
|
</view>
|
|
</view>
|
|
<view class="bmt-agree-copy">
|
|
<image class="bmt-agree-copy__icon" src="https://imgs.agrimedia.cn/copy-icon-sign.png" mode="aspectFit" />
|
|
<text class="bmt-agree-copy__text">易保全在线签约系统</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-else class="bmt-agree-success">
|
|
<image class="bmt-agree-success__image" src="https://imgs.agrimedia.cn/bm-bmt/success.png" mode="aspectFit" />
|
|
<text class="bmt-agree-success__text">恭喜签约完成</text>
|
|
<view class="bmt-agree-success__btn" @click="compute">完成</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import AssetPageShell from "../../components/asset-page-shell.vue";
|
|
import { checkBmtSignCondition, startBmtSigning } from "../../api/bmt";
|
|
|
|
const READ_BOTTOM_THRESHOLD = 15;
|
|
|
|
export default {
|
|
components: {
|
|
AssetPageShell,
|
|
},
|
|
data() {
|
|
return {
|
|
signData: {
|
|
name: "",
|
|
content: "",
|
|
},
|
|
signStatus: true,
|
|
signing: false,
|
|
isReachBottom: false,
|
|
scrollViewHeight: 0,
|
|
scrollTimer: null,
|
|
contractId: "",
|
|
};
|
|
},
|
|
onLoad() {
|
|
this.loadAgreement();
|
|
},
|
|
onReady() {
|
|
this.$nextTick(() => {
|
|
setTimeout(() => {
|
|
this.calcScrollViewHeight();
|
|
}, 100);
|
|
});
|
|
},
|
|
onShow() {
|
|
this.$nextTick(() => {
|
|
setTimeout(() => {
|
|
this.calcScrollViewHeight();
|
|
}, 300);
|
|
});
|
|
},
|
|
onUnload() {
|
|
if (this.scrollTimer) {
|
|
clearTimeout(this.scrollTimer);
|
|
}
|
|
},
|
|
methods: {
|
|
async loadAgreement() {
|
|
try {
|
|
// 协议内容与签约 id 都取自 go_to_sign_check_bmt
|
|
const data =
|
|
(await checkBmtSignCondition({}, {
|
|
showLoading: true,
|
|
loadingText: "加载中",
|
|
})) || {};
|
|
|
|
this.contractId = String(data.id || "");
|
|
this.signData = {
|
|
name: String(data.name || "签约协议"),
|
|
content: String(data.content || ""),
|
|
};
|
|
|
|
this.$nextTick(() => {
|
|
setTimeout(() => {
|
|
this.calcScrollViewHeight();
|
|
setTimeout(() => {
|
|
this.calcScrollViewHeight();
|
|
}, 200);
|
|
}, 100);
|
|
});
|
|
} catch (error) {
|
|
uni.showToast({
|
|
title: (error && error.message) || "获取签约信息失败,请重试",
|
|
icon: "none",
|
|
});
|
|
}
|
|
},
|
|
calcScrollViewHeight() {
|
|
const systemInfo = uni.getSystemInfoSync();
|
|
const windowHeight = Number(systemInfo.windowHeight || 0);
|
|
const query = uni.createSelectorQuery().in(this);
|
|
|
|
query.select(".bmt-agree-content").boundingClientRect();
|
|
query.select(".bmt-agree-desc").boundingClientRect();
|
|
query.select(".bmt-agree-bottom").boundingClientRect();
|
|
query.exec((res) => {
|
|
const contentRect = res && res[0];
|
|
const descRect = res && res[1];
|
|
const bottomRect = res && res[2];
|
|
|
|
const top = contentRect && contentRect.top ? Number(contentRect.top) : 0;
|
|
const bottomHeight =
|
|
bottomRect && bottomRect.height ? Number(bottomRect.height) : 150;
|
|
const available = windowHeight - top - bottomHeight - 16;
|
|
|
|
this.scrollViewHeight = Math.max(available, 200);
|
|
|
|
// 内容不足以滚动时,直接视为已读到底部,避免短协议无法签约
|
|
const descHeight = descRect && descRect.height ? Number(descRect.height) : 0;
|
|
|
|
if (descHeight && descHeight <= this.scrollViewHeight + READ_BOTTOM_THRESHOLD) {
|
|
this.isReachBottom = true;
|
|
}
|
|
});
|
|
},
|
|
handleScroll(event) {
|
|
if (this.scrollTimer) {
|
|
clearTimeout(this.scrollTimer);
|
|
}
|
|
|
|
this.scrollTimer = setTimeout(() => {
|
|
this.checkScrollBottom(event);
|
|
}, 50);
|
|
},
|
|
checkScrollBottom(event) {
|
|
if (this.isReachBottom) {
|
|
return;
|
|
}
|
|
|
|
const detail = (event && event.detail) || {};
|
|
const scrollTop = Number(detail.scrollTop || 0);
|
|
const scrollHeight = Number(detail.scrollHeight || 0);
|
|
const clientHeight = this.scrollViewHeight;
|
|
const scrollPercent = scrollHeight
|
|
? (scrollTop + clientHeight) / scrollHeight
|
|
: 1;
|
|
|
|
if (
|
|
scrollTop + clientHeight >= scrollHeight - READ_BOTTOM_THRESHOLD ||
|
|
scrollPercent >= 0.95
|
|
) {
|
|
this.isReachBottom = true;
|
|
|
|
this.$nextTick(() => {
|
|
setTimeout(() => {
|
|
this.calcScrollViewHeight();
|
|
}, 50);
|
|
});
|
|
|
|
uni.showToast({
|
|
title: "已阅读到底部",
|
|
icon: "none",
|
|
duration: 1000,
|
|
});
|
|
}
|
|
},
|
|
cancel() {
|
|
uni.navigateBack({
|
|
delta: 1,
|
|
});
|
|
},
|
|
async toSign() {
|
|
if (!this.isReachBottom || this.signing) {
|
|
return;
|
|
}
|
|
|
|
this.signing = true;
|
|
|
|
try {
|
|
// 签约 id 取自 go_to_sign_check_bmt
|
|
const result =
|
|
(await startBmtSigning(
|
|
{
|
|
id: this.contractId,
|
|
},
|
|
{
|
|
showLoading: true,
|
|
loadingText: "签约中",
|
|
},
|
|
)) || {};
|
|
|
|
console.log("[BMT签约] 协议页 start_signing_bmt_v2 返回:", result.raw);
|
|
|
|
if (Number(result.status) === 0 && result.saasShortLink) {
|
|
this.navigateToExternalUrl(result.saasShortLink);
|
|
return;
|
|
}
|
|
|
|
this.signStatus = false;
|
|
} catch (error) {
|
|
this.signing = false;
|
|
uni.showToast({
|
|
title: (error && error.message) || "签约失败,请重试",
|
|
icon: "none",
|
|
});
|
|
}
|
|
},
|
|
navigateToExternalUrl(targetUrl) {
|
|
if (!targetUrl) {
|
|
return;
|
|
}
|
|
|
|
if (typeof window !== "undefined" && window.location) {
|
|
window.location.href = targetUrl;
|
|
return;
|
|
}
|
|
|
|
if (
|
|
typeof plus !== "undefined" &&
|
|
plus.webview &&
|
|
plus.webview.currentWebview
|
|
) {
|
|
const currentWebview = plus.webview.currentWebview();
|
|
|
|
if (currentWebview && typeof currentWebview.loadURL === "function") {
|
|
currentWebview.loadURL(targetUrl);
|
|
return;
|
|
}
|
|
}
|
|
|
|
uni.navigateTo({
|
|
url: targetUrl,
|
|
});
|
|
},
|
|
compute() {
|
|
uni.navigateBack({
|
|
delta: 1,
|
|
});
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "../../styles/tokens.scss";
|
|
@import "../../styles/common.scss";
|
|
|
|
.bmt-agree-page {
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.bmt-agree-content {
|
|
margin: 12rpx 24rpx;
|
|
padding: 28rpx 26rpx;
|
|
}
|
|
|
|
.bmt-agree-scroll {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.bmt-agree-title {
|
|
display: block;
|
|
margin-bottom: 30rpx;
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
text-align: center;
|
|
color: $asset-text-main;
|
|
}
|
|
|
|
.bmt-agree-desc {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.bmt-agree-text {
|
|
display: block;
|
|
font-size: 26rpx;
|
|
line-height: 1.8;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
color: $asset-text-muted;
|
|
}
|
|
|
|
.bmt-agree-tip {
|
|
margin-top: 24rpx;
|
|
padding-top: 30rpx;
|
|
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
|
text-align: center;
|
|
font-size: 24rpx;
|
|
color: $asset-text-subtle;
|
|
}
|
|
|
|
.bmt-agree-padding {
|
|
height: 1rpx;
|
|
opacity: 0;
|
|
}
|
|
|
|
.bmt-agree-bottom {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
padding: 22rpx 32rpx calc(22rpx + env(safe-area-inset-bottom));
|
|
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
|
background: #191e32;
|
|
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.18);
|
|
z-index: 30;
|
|
}
|
|
|
|
.bmt-agree-bottom__hint {
|
|
display: block;
|
|
margin-bottom: 20rpx;
|
|
text-align: center;
|
|
font-size: 24rpx;
|
|
color: $asset-text-subtle;
|
|
}
|
|
|
|
.bmt-agree-bottom__row {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.bmt-agree-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: 1;
|
|
height: 80rpx;
|
|
border-radius: 40rpx;
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.bmt-agree-btn+.bmt-agree-btn {
|
|
margin-left: 20rpx;
|
|
}
|
|
|
|
.bmt-agree-btn--ghost {
|
|
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
background: rgba(255, 255, 255, 0.06);
|
|
color: $asset-text-main;
|
|
}
|
|
|
|
.bmt-agree-btn--primary {
|
|
background: linear-gradient(135deg, #7e6cff 0%, #6b56f6 100%);
|
|
box-shadow: 0 14rpx 24rpx rgba(93, 79, 225, 0.22);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.bmt-agree-btn--primary.is-disabled {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.bmt-agree-copy {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-top: 16rpx;
|
|
}
|
|
|
|
.bmt-agree-copy__icon {
|
|
width: 112rpx;
|
|
height: 32rpx;
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.bmt-agree-copy__text {
|
|
font-size: 24rpx;
|
|
color: $asset-text-subtle;
|
|
}
|
|
|
|
.bmt-agree-success {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding-top: 220rpx;
|
|
}
|
|
|
|
.bmt-agree-success__image {
|
|
width: 180rpx;
|
|
height: 180rpx;
|
|
}
|
|
|
|
.bmt-agree-success__text {
|
|
margin-top: 48rpx;
|
|
font-size: 36rpx;
|
|
font-weight: 500;
|
|
color: $asset-text-main;
|
|
}
|
|
|
|
.bmt-agree-success__btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 328rpx;
|
|
height: 80rpx;
|
|
margin-top: 60rpx;
|
|
border-radius: 40rpx;
|
|
background: linear-gradient(135deg, #7e6cff 0%, #6b56f6 100%);
|
|
box-shadow: 0 14rpx 24rpx rgba(93, 79, 225, 0.22);
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #ffffff;
|
|
}
|
|
</style>
|