说明

接到了一个小需求,要实现我同意后方可继续一个页面打开后弹窗提示信息,点击,反之退出。

因为公司产品使用的是公司自己的前端框架+自己的组件库,带的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();

效果展示

⚠注意:如果不同意则会直接退出当前页面

结尾

本人并不是前端岗位,前端这块也是才疏学浅,感觉用些好用的组件库应该能更好的实现这种功能,内容仅供自己留档和他人参考,有更好的方案欢迎评论指教。