说明
接到了一个小需求,要实现我同意后方可继续一个页面打开后弹窗提示信息,点击,反之退出。
因为公司产品使用的是公司自己的前端框架+自己的组件库,带的Dialog组件并不好用,且不允许导入外部组件,那我想想算了直接拿JS实现算了,于是便有了下面的代码。
基础实现
实现代码
function showModal() {
// 遮罩
const overlay = document.createElement("div");
overlay.className = "ant-modal-mask";
overlay.style.position = "fixed";
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
overlay.style.zIndex = 9999;
// 弹窗
const modalContent = document.createElement("div");
modalContent.innerHTML = `
<div class="ant-modal-content" style="background: white;">
<div class="ant-modal-body" style="padding: 50px;">
<p style="font-size: 18px; text-indent: 2em; color: black">该合同已经XXXXX盖章,客户尚未盖章。为满足客户付款要求,需在客户加盖公章前先行开具增值税专用发票。<br></p>
<p style="font-size: 18px; text-indent: 2em; color: black">本人知悉此事项,并知悉以下事项:<br>
1、未提交双章合同前,本合同项下不能再申请开立专票;<br>
<span style="color: red;">2、在向财务提交双章合同之前,即使款项到账,也无法计入业绩但仍会计入计税收入。</span><br>
</p>
<div style="display: flex; flex-direction: row; justify-content: center; padding-top: 20px;">
<input type="checkbox" id="agreeCheckbox" style="margin-right: 5px;"/>
<label for="agreeCheckbox" style="font-weight: normal; color: black">确认同意</label>
</div>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<button type="button" id="primaryButton" style="transition: background-color 0.3s ease;border:none;background-color:#ccc;padding:7px 15px;border-radius:2px;color:white;cursor:pointer;" onclick="closeModal()" disabled>继续</button>
<span style="margin: 0 10px;"></span>
<button type="button" style="border:none;background-color:#58a0f8;padding:7px 15px;border-radius:2px;color:white;cursor:pointer;" onclick="closeWindow()">关闭</button>
</div>
</div>
</div>
`;
// 添加到body中
document.body.appendChild(overlay);
document.body.appendChild(modalContent);
modalContent.style.position = "fixed";
modalContent.style.top = "50%";
modalContent.style.left = "50%";
modalContent.style.transform = "translate(-50%, -50%)";
modalContent.style.zIndex = 10000;
}
function closeModal() {
const overlays = document.getElementsByClassName("ant-modal-mask");
const modalContents = document.getElementsByClassName("ant-modal-content");
if (overlays.length > 0 && modalContents.length > 0) {
overlays[0].remove();
modalContents[0].remove();
}
}
// 关闭窗口
function closeWindow() {
window.close();
}
function openTest() {
showModal();
// 监听复选框状态变化
document
.getElementById("agreeCheckbox")
.addEventListener("change", function() {
var primaryButton = document.getElementById("primaryButton");
if (this.checked) {
primaryButton.disabled = false;
primaryButton.style.backgroundColor = "#58a0f8";
} else {
primaryButton.disabled = true;
primaryButton.style.backgroundColor = "#ccc";
}
});
}
openTest();
效果展示
⚠注意:如果不同意则会直接退出当前页面
添加阅读完成功能
上面的代码就已经实现了需求,但我又想到,见过很多那种用户协议类的,需要让用户阅读完后才能点击“我同意”,那么下面再来添加这块功能
我的思路就是增加一个可滚动文本区域,监听滚动状态,当滚动条到底时,才可点击“我同意”
实现代码
function showModal() {
// 遮罩
const overlay = document.createElement("div");
overlay.className = "ant-modal-mask";
overlay.style.position = "fixed";
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
overlay.style.zIndex = 9999;
// 弹窗
const modalContent = document.createElement("div");
modalContent.innerHTML = `
<div class="ant-modal-content" style="background: white;">
<div class="ant-modal-body" style="padding: 50px;">
<span style="font-size: 18px; text-indent: 2em; color: black">用户协议</span>
<div style="height: 300px; border: 1px solid #ccc; padding: 10px; overflow-y: auto; position: relative;" id="scrollableDiv">
<!-- 模拟大量文本 -->
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
<p>aaa</p>
</div>
<div style="display: flex; flex-direction: row; justify-content: center; padding-top: 20px;">
<input type="checkbox" id="agreeCheckbox" style="margin-right: 5px;" disabled/>
<label for="agreeCheckbox" style="font-weight: normal; color: black">确认同意</label>
</div>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<button type="button" id="primaryButton" style="transition: background-color 0.3s ease;border:none;background-color:#ccc;padding:7px 15px;border-radius:2px;color:white;cursor:pointer;" onclick="closeModal()" disabled>继续</button>
<span style="margin: 0 10px;"></span>
<button type="button" style="border:none;background-color:#58a0f8;padding:7px 15px;border-radius:2px;color:white;cursor:pointer;" onclick="closeWindow()">关闭</button>
</div>
</div>
</div>
`;
// 添加到body中
document.body.appendChild(overlay);
document.body.appendChild(modalContent);
modalContent.style.position = "fixed";
modalContent.style.top = "50%";
modalContent.style.left = "50%";
modalContent.style.transform = "translate(-50%, -50%)";
modalContent.style.zIndex = 10000;
// 监听滚动条
var scrollableDiv = document.getElementById("scrollableDiv");
scrollableDiv.addEventListener("scroll", function () {
// 当滚动条距离底部小于某个阈值(例如5px)时,认为已滚动到底部
if (this.scrollHeight - this.scrollTop - this.clientHeight <= 5) {
document.getElementById("agreeCheckbox").disabled = false;
}
});
// 监听复选框状态变化
document.getElementById("agreeCheckbox").addEventListener("change", function () {
var primaryButton = document.getElementById("primaryButton");
if (this.checked) {
primaryButton.disabled = false;
primaryButton.style.backgroundColor = "#58a0f8";
} else {
primaryButton.disabled = true;
primaryButton.style.backgroundColor = "#ccc";
}
});
}
function closeModal() {
const overlays = document.getElementsByClassName("ant-modal-mask");
const modalContents = document.getElementsByClassName("ant-modal-content");
if (overlays.length > 0 && modalContents.length > 0) {
overlays[0].remove();
modalContents[0].remove();
}
}
// 关闭窗口
function closeWindow() {
window.close();
}
function openTest() {
showModal();
}
openTest();
效果展示
⚠注意:如果不同意则会直接退出当前页面
结尾
本人并不是前端岗位,前端这块也是才疏学浅,感觉用些好用的组件库应该能更好的实现这种功能,内容仅供自己留档和他人参考,有更好的方案欢迎评论指教。
评论区