返回列表 发布新帖
查看: 181|回复: 1

[代码技巧] 给你的网页加上一个优雅的弹窗公告

[复制链接]
SunJu_FaceMall
社区贡献

315

主题

190

回帖

1万

积分

等级头衔
Icon组别 : 管理员
Icon等级 :

积分成就
   钻石 : 524 颗
   贡献 : 1849 点
   金币 : 12 枚
Icon在线时间 : 1297 小时
Icon注册时间 : 2024-11-22
Icon最后登录 : 2025-12-9

荣誉勋章

会员LV.1会员LV.2会员LV.3会员LV.4会员LV.5会员LV.6会员LV.7会员LV.8会员LV.9会员LV.10

风云·优秀版主

飞流名人堂成员

1

实名认证 手机认证 vip vip-year FLLTCN发表于 2025-9-18 19:34:25 | 查看全部 |阅读模式 浙江金华

资源无需等待,交易就趁现在,全面资源整合网络大咖云集,让你轻松玩转互联网!

您需要 登录 才可以下载或查看,没有账号?立即注册

×

引用一个JS文件来实现任意页面弹窗公告,弹窗公告代码JS文件本地化可放心使用。
效果展示
image-1024x564.webp

公告能够在不同设备自适应显示
实现方法1.在网站目录创建文件 itjs.js ,并且粘贴以下代码到你刚刚创建的这个JS文件里面。
  1. // 公告弹窗
  2. (function () {
  3.     function showAnnounce() {
  4.         const lastClose = localStorage.getItem('announceLastClose');
  5.         if (!lastClose) return true;
  6.         const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
  7.         return new Date(lastClose).getTime() < oneDayAgo;
  8.     }<p></p>
  9. <p style="line-height: 30px; text-indent: 2em;">    if (!showAnnounce()) return;</p>
  10. <p style="line-height: 30px; text-indent: 2em;">    const cfg = window.announceConfig || {
  11.         title: "公告通知",
  12.         items: [
  13.             {
  14.                 icon: "news",
  15.                 title: "最新公告",
  16.                 content: "本平台新增多项安全验证功能,建议您及时完善个人信息。"
  17.             },
  18.             {
  19.                 icon: "update",
  20.                 title: "功能更新",
  21.                 content: "新版移动端已上线,支持离线模式和数据同步功能。"
  22.             }
  23.         ],
  24.         noShowText: "一天内不再显示",
  25.         laterText: "稍后提醒",
  26.         okText: "我知道了",
  27.         mainColor: "#3b82f6",
  28.         maxW: "500px",
  29.         z: 9999
  30.     };</p>
  31. <p style="line-height: 30px; text-indent: 2em;">    function addStyles() {
  32.         const style = document.createElement('style');
  33.         style.textContent = `
  34.             .announce-mask {
  35.                 position: fixed;
  36.                 top: 0;
  37.                 left: 0;
  38.                 right: 0;
  39.                 bottom: 0;
  40.                 background: rgba(0,0,0,0.5);
  41.                 z-index: ${cfg.z - 1};
  42.                 opacity: 0;
  43.                 visibility: hidden;
  44.                 transition: opacity 0.3s;
  45.                 backdrop-filter: blur(4px);
  46.             }
  47.             
  48.             .announce-mask.show {
  49.                 opacity: 1;
  50.                 visibility: visible;
  51.             }
  52.             
  53.             .announce-box {
  54.                 position: fixed;
  55.                 top: 50%;
  56.                 left: 50%;
  57.                 transform: translate(-50%, -50%) scale(0.95);
  58.                 background: white;
  59.                 border-radius: 10px;
  60.                 max-width: ${cfg.maxW};
  61.                 width: calc(100% - 30px);
  62.                 box-shadow: 0 5px 20px rgba(0,0,0,0.1);
  63.                 z-index: ${cfg.z};
  64.                 overflow: hidden;
  65.                 opacity: 0;
  66.                 visibility: hidden;
  67.                 transition: all 0.3s;
  68.             }
  69.             
  70.             .announce-box.show {
  71.                 opacity: 1;
  72.                 visibility: visible;
  73.                 transform: translate(-50%, -50%) scale(1);
  74.             }
  75.             
  76.             .announce-head {
  77.                 background: ${cfg.mainColor};
  78.                 color: white;
  79.                 padding: 15px 20px;
  80.                 display: flex;
  81.                 align-items: center;
  82.                 justify-content: space-between;
  83.             }
  84.             
  85.             .announce-title {
  86.                 margin: 0;
  87.                 font-size: 1.2rem;
  88.                 display: flex;
  89.                 align-items: center;
  90.                 gap: 10px;
  91.             }
  92.             
  93.             .announce-close {
  94.                 background: none;
  95.                 border: none;
  96.                 color: white;
  97.                 font-size: 1.5rem;
  98.                 cursor: pointer;
  99.                 width: 30px;
  100.                 height: 30px;
  101.                 display: flex;
  102.                 align-items: center;
  103.                 justify-content: center;
  104.                 border-radius: 50%;
  105.             }
  106.             
  107.             .announce-close:hover {
  108.                 background: rgba(255,255,255,0.2);
  109.             }
  110.             
  111.             .announce-body {
  112.                 padding: 20px;
  113.             }
  114.             
  115.             .announce-list {
  116.                 margin: 0;
  117.                 padding: 0;
  118.                 list-style: none;
  119.             }
  120.             
  121.             .announce-item {
  122.                 display: flex;
  123.                 gap: 12px;
  124.                 padding: 15px 0;
  125.                 border-bottom: 1px solid #f1f5f9;
  126.             }
  127.             
  128.             .announce-item:last-child {
  129.                 border-bottom: none;
  130.                 padding-bottom: 0;
  131.             }
  132.             
  133.             .announce-icon {
  134.                 width: 40px;
  135.                 height: 40px;
  136.                 border-radius: 8px;
  137.                 display: flex;
  138.                 align-items: center;
  139.                 justify-content: center;
  140.                 flex-shrink: 0;
  141.             }
  142.             
  143.             .announce-icon.news {
  144.                 background: #e0f2fe;
  145.             }
  146.             
  147.             .announce-icon.update {
  148.                 background: #e6f7ee;
  149.             }
  150.             
  151.             .announce-icon svg {
  152.                 width: 20px;
  153.                 height: 20px;
  154.             }
  155.             
  156.             .announce-icon.news svg {
  157.                 fill: #0284c7;
  158.             }
  159.             
  160.             .announce-icon.update svg {
  161.                 fill: #059669;
  162.             }
  163.             
  164.             .announce-text {
  165.                 flex: 1;
  166.             }
  167.             
  168.             .announce-item-title {
  169.                 margin: 0 0 5px 0;
  170.                 font-size: 1rem;
  171.                 font-weight: 600;
  172.                 color: #1e293b;
  173.             }
  174.             
  175.             .announce-item-desc {
  176.                 margin: 0;
  177.                 font-size: 0.9rem;
  178.                 color: #64748b;
  179.                 line-height: 1.5;
  180.             }
  181.             
  182.             .announce-option {
  183.                 padding: 0 20px 15px;
  184.             }
  185.             
  186.             .announce-check {
  187.                 display: flex;
  188.                 align-items: center;
  189.                 gap: 8px;
  190.                 cursor: pointer;
  191.             }
  192.             
  193.             .announce-checkbox {
  194.                 width: 18px;
  195.                 height: 18px;
  196.                 accent-color: ${cfg.mainColor};
  197.             }
  198.             
  199.             .announce-check-label {
  200.                 font-size: 0.9rem;
  201.                 color: #64748b;
  202.             }
  203.             
  204.             .announce-foot {
  205.                 padding: 15px 20px;
  206.                 border-top: 1px solid #f1f5f9;
  207.                 display: flex;
  208.                 gap: 10px;
  209.             }
  210.             
  211.             .announce-btn {
  212.                 padding: 9px 15px;
  213.                 border: none;
  214.                 border-radius: 6px;
  215.                 font-size: 0.9rem;
  216.                 cursor: pointer;
  217.                 flex: 1;
  218.                 transition: all 0.2s;
  219.             }
  220.             
  221.             .announce-btn.later {
  222.                 background: #f1f5f9;
  223.                 color: #475569;
  224.             }
  225.             
  226.             .announce-btn.later:hover {
  227.                 background: #e2e8f0;
  228.             }
  229.             
  230.             .announce-btn.ok {
  231.                 background: ${cfg.mainColor};
  232.                 color: white;
  233.             }
  234.             
  235.             .announce-btn.ok:hover {
  236.                 background: ${shadeColor(cfg.mainColor, -15)};
  237.             }
  238.             
  239.             @media (max-width: 480px) {
  240.                 .announce-foot {
  241.                     flex-direction: column;
  242.                 }
  243.             }
  244.         `;
  245.         document.head.appendChild(style);
  246.     }</p>
  247. <p style="line-height: 30px; text-indent: 2em;">    function shadeColor(color, percent) {
  248.         let R = parseInt(color.substring(1, 3), 16);
  249.         let G = parseInt(color.substring(3, 5), 16);
  250.         let B = parseInt(color.substring(5, 7), 16);</p>
  251. <p style="line-height: 30px; text-indent: 2em;">        R = parseInt(R * (100 + percent) / 100);
  252.         G = parseInt(G * (100 + percent) / 100);
  253.         B = parseInt(B * (100 + percent) / 100);</p>
  254. <p style="line-height: 30px; text-indent: 2em;">        R = R < 255 ? R : 255;
  255.         G = G < 255 ? G : 255;
  256.         B = B < 255 ? B : 255;</p>
  257. <p style="line-height: 30px; text-indent: 2em;">        R = Math.round(R);
  258.         G = Math.round(G);
  259.         B = Math.round(B);</p>
  260. <p style="line-height: 30px; text-indent: 2em;">        const RR = (R.toString(16).length === 1) ? "0" + R.toString(16) : R.toString(16);
  261.         const GG = (G.toString(16).length === 1) ? "0" + G.toString(16) : G.toString(16);
  262.         const BB = (B.toString(16).length === 1) ? "0" + B.toString(16) : B.toString(16);</p>
  263. <p style="line-height: 30px; text-indent: 2em;">        return "#" + RR + GG + BB;
  264.     }</p>
  265. <p style="line-height: 30px; text-indent: 2em;">    function closeAnnounce(mask, box, noShow) {
  266.         mask.classList.remove('show');
  267.         box.classList.remove('show');</p>
  268. <p style="line-height: 30px; text-indent: 2em;">        if (noShow) {
  269.             localStorage.setItem('announceLastClose', new Date().toISOString());
  270.         }</p>
  271. <p style="line-height: 30px; text-indent: 2em;">        setTimeout(() => {
  272.             mask.remove();
  273.             box.remove();
  274.         }, 300);
  275.     }</p>
  276. <p style="line-height: 30px; text-indent: 2em;">    function createItems(container) {
  277.         const list = document.createElement('ul');
  278.         list.className = 'announce-list';</p>
  279. <p style="line-height: 30px; text-indent: 2em;">        cfg.items.forEach(item => {
  280.             const li = document.createElement('li');
  281.             li.className = 'announce-item';</p>
  282. <p style="line-height: 30px; text-indent: 2em;">            const icon = document.createElement('div');
  283.             icon.className = `announce-icon ${item.icon}`;</p>
  284. <p style="line-height: 30px; text-indent: 2em;">            let svg = '';
  285.             if (item.icon === 'news') {
  286.                 svg = `
  287.                     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  288.                         <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 7h5v5H7zm5 7H7v2h5zm2-4h2v2h-2zm0 4h2v2h-2z"/>
  289.                     </svg>
  290.                 `;
  291.             } else if (item.icon === 'update') {
  292.                 svg = `
  293.                     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  294.                         <path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8zm-2 8v3l4-4-4-4v3H6v2h4z"/>
  295.                     </svg>
  296.                 `;
  297.             }</p>
  298. <p style="line-height: 30px; text-indent: 2em;">            icon.innerHTML = svg;</p>
  299. <p style="line-height: 30px; text-indent: 2em;">            const text = document.createElement('div');
  300.             text.className = 'announce-text';</p>
  301. <p style="line-height: 30px; text-indent: 2em;">            const title = document.createElement('h4');
  302.             title.className = 'announce-item-title';
  303.             title.textContent = item.title;</p>
  304. <p style="line-height: 30px; text-indent: 2em;">            const desc = document.createElement('p');
  305.             desc.className = 'announce-item-desc';
  306.             desc.textContent = item.content;</p>
  307. <p style="line-height: 30px; text-indent: 2em;">            text.appendChild(title);
  308.             text.appendChild(desc);</p>
  309. <p style="line-height: 30px; text-indent: 2em;">            li.appendChild(icon);
  310.             li.appendChild(text);
  311.             list.appendChild(li);
  312.         });</p>
  313. <p style="line-height: 30px; text-indent: 2em;">        container.appendChild(list);
  314.     }</p>
  315. <p style="line-height: 30px; text-indent: 2em;">    function createAnnounce() {
  316.         const mask = document.createElement('div');
  317.         mask.className = 'announce-mask';</p>
  318. <p style="line-height: 30px; text-indent: 2em;">        const box = document.createElement('div');
  319.         box.className = 'announce-box';</p>
  320. <p style="line-height: 30px; text-indent: 2em;">        const head = document.createElement('div');
  321.         head.className = 'announce-head';</p>
  322. <p style="line-height: 30px; text-indent: 2em;">        const title = document.createElement('h3');
  323.         title.className = 'announce-title';
  324.         title.innerHTML = `
  325.             <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor">
  326.                 <path d="M12 2c5.51 0 10 4.49 10 10s-4.49 10-10 10S2 17.51 2 12 6.49 2 12 2zm0 2c-4.41 0-8 3.59-8 8s3.59 8 8 8 8-3.59 8-8-3.59-8-8-8zm-1 3h2v6h-2zm0 8h2v2h-2z"/>
  327.             </svg>
  328.             ${cfg.title}
  329.         `;</p>
  330. <p style="line-height: 30px; text-indent: 2em;">        const closeBtn = document.createElement('button');
  331.         closeBtn.className = 'announce-close';
  332.         closeBtn.textContent = '×';
  333.         closeBtn.addEventListener('click', () => {
  334.             closeAnnounce(mask, box, false);
  335.         });</p>
  336. <p style="line-height: 30px; text-indent: 2em;">        head.appendChild(title);
  337.         head.appendChild(closeBtn);</p>
  338. <p style="line-height: 30px; text-indent: 2em;">        const body = document.createElement('div');
  339.         body.className = 'announce-body';
  340.         createItems(body);</p>
  341. <p style="line-height: 30px; text-indent: 2em;">        const option = document.createElement('div');
  342.         option.className = 'announce-option';</p>
  343. <p style="line-height: 30px; text-indent: 2em;">        const check = document.createElement('label');
  344.         check.className = 'announce-check';</p>
  345. <p style="line-height: 30px; text-indent: 2em;">        const checkbox = document.createElement('input');
  346.         checkbox.type = 'checkbox';
  347.         checkbox.className = 'announce-checkbox';
  348.         checkbox.id = 'noShow';</p>
  349. <p style="line-height: 30px; text-indent: 2em;">        const label = document.createElement('span');
  350.         label.className = 'announce-check-label';
  351.         label.textContent = cfg.noShowText;</p>
  352. <p style="line-height: 30px; text-indent: 2em;">        check.appendChild(checkbox);
  353.         check.appendChild(label);
  354.         option.appendChild(check);</p>
  355. <p style="line-height: 30px; text-indent: 2em;">        const foot = document.createElement('div');
  356.         foot.className = 'announce-foot';</p>
  357. <p style="line-height: 30px; text-indent: 2em;">        const laterBtn = document.createElement('button');
  358.         laterBtn.className = 'announce-btn later';
  359.         laterBtn.textContent = cfg.laterText;
  360.         laterBtn.addEventListener('click', () => {
  361.             closeAnnounce(mask, box, false);
  362.         });</p>
  363. <p style="line-height: 30px; text-indent: 2em;">        const okBtn = document.createElement('button');
  364.         okBtn.className = 'announce-btn ok';
  365.         okBtn.textContent = cfg.okText;
  366.         okBtn.addEventListener('click', () => {
  367.             closeAnnounce(mask, box, checkbox.checked);
  368.         });</p>
  369. <p style="line-height: 30px; text-indent: 2em;">        foot.appendChild(laterBtn);
  370.         foot.appendChild(okBtn);</p>
  371. <p style="line-height: 30px; text-indent: 2em;">        box.appendChild(head);
  372.         box.appendChild(body);
  373.         box.appendChild(option);
  374.         box.appendChild(foot);</p>
  375. <p style="line-height: 30px; text-indent: 2em;">        document.body.appendChild(mask);
  376.         document.body.appendChild(box);</p>
  377. <p style="line-height: 30px; text-indent: 2em;">        setTimeout(() => {
  378.             mask.classList.add('show');
  379.             box.classList.add('show');
  380.         }, 100);</p>
  381. <p style="line-height: 30px; text-indent: 2em;">        mask.addEventListener('click', (e) => {
  382.             if (e.target === mask) {
  383.                 closeAnnounce(mask, box, false);
  384.             }
  385.         });</p>
  386. <p style="line-height: 30px; text-indent: 2em;">        document.addEventListener('keydown', (e) => {
  387.             if (e.key === 'Escape') {
  388.                 closeAnnounce(mask, box, false);
  389.             }
  390.         });
  391.     }</p>
  392. <p style="line-height: 30px; text-indent: 2em;">    if (document.readyState === 'loading') {
  393.         document.addEventListener('DOMContentLoaded', () => {
  394.             addStyles();
  395.             createAnnounce();
  396.         });
  397.     } else {
  398.         addStyles();
  399.         createAnnounce();
  400.     }
  401. })();</p>
复制代码
image-1-1024x669.webp
这里的文本按照你的需求进行更改,其中 icon 为图标名称,小白切勿随意修改,否则图标将无法正常显示。
2.在需要弹窗公告的页面加上以下代码即可实现弹窗公告功能。[size=1.2em]
一般加在主页,也可以加在全局文件实现全部页面弹出公告,具体根据你的实际需求。
  1.   <script src="itjs.js"></script>
复制代码
小白请注意:src后的路径根据实际情况调整!

关于这段代码放在页面哪里比较好:
1.body标签的末尾(推荐)
[size=1.2em]
注意:不是body标签后面!在body标签里面,放在</body>标签前。


优点:此时页面 DOM 加载完成后再执行公告脚本,避免因 DOM 未就绪导致的问题,同时不阻塞页面渲染
缺点:公告弹窗会比放在head中稍晚出现

2.head标签内,配合defer属性
  1. <script src="itjs.js" defer></script>
复制代码
优点:提前加载脚本,但会等待 DOM 就绪后再执行,不阻塞页面渲染
缺点:需要浏览器支持defer属性(现代浏览器都支持)

3.head标签内,不使用任何属性(不推荐)
缺点:会阻塞页面渲染,直到脚本加载并执行完成,影响页面加载速度

[size=1.2em]
综合考虑,推荐放在body标签末尾,这种方式既能保证脚本正常运行,又不会影响页面的加载性能,公告弹窗会在页面内容渲染完成后适时出现,给用户更好的体验。
如果希望公告尽可能早地出现,但又不影响页面加载,可以选择第二种方式(head中加defer)

代码说明
模块化设计:采用立即执行函数表达式 (IIFE) 封装,避免全局变量污染,内部功能划分清晰(样式添加、元素创建、事件处理等)
响应式设计:在移动设备上自动调整布局,支持点击遮罩层、关闭按钮、ESC 键等多种关闭方式。
样式隔离:公告代码通过独特的类名前缀(announce-)避免样式冲突。
有任何问题可在评论区说明,博主随时在线,若你实在不会操作可以联系博主为你操作(有偿)。

路虽远,行则将至;事虽难,做则必成。
社区贡献

27

主题

21

回帖

2237

积分

等级头衔
Icon组别 : 新兵
Icon等级 :

积分成就
   钻石 : 0 颗
   贡献 : 1221 点
   金币 : 0 枚
Icon在线时间 : 17 小时
Icon注册时间 : 2024-11-30
Icon最后登录 : 2025-9-26

荣誉勋章
波斯虎
UID:555
暂无靓号,点击前往开通
发表于 2025-9-26 00:22:01 | 查看全部 广东广州
            
诚信连接交易,资源创造价值。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

飞流广播+ 发布

系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
10-30 17:02
系统消息:柒沐已经连续答对10道难题,逆天学霸谁与争锋?!#每日答题#
10-09 09:07
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
09-24 09:00
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
09-11 11:40
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
09-02 09:17
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
08-27 08:56
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
08-20 15:12
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
08-03 10:22
系统消息:柒沐已经连续答对10道难题,逆天学霸谁与争锋?!#每日答题#
06-30 08:57
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
06-18 09:14
系统消息:清风网络已经连续答对10道难题,逆天学霸谁与争锋?!#每日答题#
04-11 09:40
系统消息:清风网络已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
04-10 09:31
系统消息:IXM77777已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
04-09 13:44
系统消息:清风网络已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
04-09 09:22
系统消息:柒沐已经连续答对10道难题,逆天学霸谁与争锋?!#每日答题#
04-09 08:52
系统消息:清风网络已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
04-08 09:24
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
04-07 09:02
系统消息:柒沐已经连续答对10道难题,逆天学霸谁与争锋?!#每日答题#
02-27 09:35
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
02-26 09:06
系统消息:柒沐已经连续答对3道难题,逆天学霸谁与争锋?!#每日答题#
02-25 08:49
站内通告

提供资源交易、信息共享、靓号交流、技术变现、学习问答、兴趣娱乐等全面服务。

1.丰富功能系统,扩展社区特色玩法,打造最好的互联网聚集圈子。

2.准确信息真实交易,安全快捷又方便,让虚拟交易面对面。

3. 天上不会掉馅饼,话术骗术迷人心,切勿脱离平台线下交易,被骗与平台无关!

4. 欺诈骗钱,违规违法将视情受到警告&禁言&封号甚至检举至👮🏻‍♀️处理!

官方Q群:123129钉推群:BAYR2383 站长QQ:3220000000

投诉/建议/商务合作联系

fl@fllt.cn

严禁私下交易,被骗与本站无关。
违反交易细则,取证立查严惩。
  • 钉钉新帖推送群
  • 官方交流QQ群
  • 站长唯一微信号

👮曝光Ta|🧿小黑屋|📴手机页|飞流网 ( 渝ICP备2025054677号-1|电信增值许可 渝B2-20250789 )|网站地图

GMT+8, 2025-12-10 13:59 , Processed in 0.094818 second(s), 63 queries, MemCached On , Gzip On.

Based on XJ-TX X3.5 Licensed

飞流论坛 HanAnalytics icp Astro vhAstro-Theme

关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表