给Chevereto游客用户上传文件增加一个弹窗提示

图片[1]-给Chevereto游客用户上传文件增加一个弹窗提示-鼎点&Blog

上图的效果:用户未登录状态时上传文件会提示,登录状态下不提示

这样的效果该怎么实现呢,接下来先讲讲原理,大家可以跟着操作一起整起来!

Chevereto 游客上传提示弹窗完整实现教程:

一、前言

在使用 Chevereto 搭建图片、视频托管站时,如果允许游客直接上传文件,通常需要向游客明确说明:

  • 当前正在以游客身份上传;
  • 游客上传的文件只保留一定时间;
  • 文件到期后会自动清理;
  • 注册账号后可以更加方便地管理自己的文件。

本文介绍一种无需修改 Chevereto 核心程序文件的实现方式,通过后台自定义 JavaScript 动态创建提示弹窗。

最终实现的效果是:

只有游客访问 /upload 上传页面时才显示提示。

同时不会影响正常上传,也不会干扰登录、注册和账户相关页面。

二、最终实现效果

游客访问:

游客访问:

https://你的域名/upload

会显示一个提示弹窗:

┌──────────────────────────────┐
│                              │
│             ☁                │
│                              │
│         游客上传提示          │
│                              │
│   您当前正在以游客身份上传文件。 │
│   游客上传的图片、视频等文件     │
│   仅保留 7 天,到期后将自动清理。 │
│                              │
│   注册账号后可以更加方便地管理文件。│
│                              │
│    登录     注册     知道了     │
│                              │
└──────────────────────────────┘

其中:

  • 登录:进入登录页面;
  • 注册:进入注册页面;
  • 知道了:关闭提示,不进行任何跳转;
  • 右上角 ×:关闭提示;
  • 点击弹窗外部遮罩:关闭提示;
  • 按键盘 Esc:关闭提示。

三、功能规则

本方案的判断规则如下。

场景是否显示
游客访问 /upload✅ 显示
已登录用户访问 /upload❌ 不显示
游客访问首页 /❌ 不显示
游客访问 /login❌ 不显示
游客访问 /signup❌ 不显示
游客访问 /register❌ 不显示
游客访问 /account❌ 不显示
游客访问 /account/*❌ 不显示
游客访问找回密码页面❌ 不显示
点击“知道了”❌ 当前页面不再重复显示
刷新页面✅ 重新显示
离开上传页面后再次进入✅ 重新显示

这里特别需要说明:

“知道了”不会永久记住用户。

本方案不使用:

  • Cookie
  • localStorage
  • sessionStorage

而是使用一个 JavaScript 内存变量记录当前页面是否关闭过弹窗。

因此刷新页面后,状态会自动恢复。

四、核心判断逻辑

整个功能实际上可以归纳为一个非常简单的判断公式:

显示弹窗
=
当前页面是 /upload
AND
当前页面不是排除页面
AND
用户没有登录
AND
当前页面没有关闭过弹窗

也就是:

if (
    是上传页面 &&
    不是排除页面 &&
    没有登录 &&
    没有点击过“知道了”
) {
    显示弹窗;
}

整个程序按照这个顺序进行判断。

五、判断流程

完整流程如下:

页面加载
    │
    ▼
获取当前 URL 路径
    │
    ▼
是否为 /upload?
    │
    ├── 否 → 结束
    │
    ▼
是否属于排除页面?
    │
    ├── 是 → 结束
    │
    ▼
是否已经登录?
    │
    ├── 是 → 结束
    │
    ▼
当前页面是否已经点击“知道了”?
    │
    ├── 是 → 结束
    │
    ▼
显示游客提示弹窗

这种设计的好处是:

先过滤页面,再判断身份,最后判断弹窗状态。

避免不必要地创建弹窗。


六、获取当前页面路径

使用:

window.location.pathname

获取当前 URL 的路径。

例如:

https://img.example.com/upload

得到:

/upload

代码:

function getCurrentPath() {
    var path = window.location.pathname || '/';

    path = path.replace(/\/+$/, '');

    if (path === '') {
        path = '/';
    }

    return path;
}

同时处理了:

/upload
/upload/

两种情况。

最终都会统一为:

/upload

七、判断是否为上传页面

定义:

var NOTICE_PAGE = '/upload';

然后通过:

function isNoticePage(path) {
    return path === NOTICE_PAGE;
}

进行判断。

只有:

/upload

才允许继续执行。

例如:

/

不会显示。

/login

不会显示。

/account

不会显示。


八、排除页面机制

虽然目前弹窗只针对 /upload,但代码仍然保留了一套排除页面机制。

var EXCLUDED_PATHS = [
    '/login',
    '/signup',
    '/register',
    '/account',
    '/account/password-forgot',
    '/account/password-reset'
];

这样以后如果修改功能,例如需要让弹窗同时出现在首页,只需要调整:

NOTICE_PAGE

即可,而不需要重新设计整套判断逻辑。


/account/* 的特殊处理

账户页面可能存在:

/account
/account/profile
/account/settings
/account/password

所以不能只判断:

path === '/account'

程序还会判断:

path.indexOf('/account/') === 0

因此:

/account
/account/xxx
/account/xxx/xxx

都会被认为是账户页面。


九、登录状态判断

本方案没有通过 URL 中是否存在 /login 来判断用户身份。

也没有通过:

a[href="/login"]

或者其他容易受到页面结构变化影响的元素判断。

而是使用 Chevereto 页面中登录用户存在的退出登录表单:

#form-logout

判断代码:

function isLoggedIn() {
    return document.querySelector('#form-logout') !== null;
}

逻辑非常简单:

存在 #form-logout
       ↓
    已登录

如果不存在:

不存在 #form-logout
       ↓
      游客

因此登录用户进入:

/upload

时,程序会直接停止,不会显示游客提示。


十、当前页面临时关闭机制

这是本方案比较重要的一点。

定义:

var noticeDismissed = false;

初始状态:

false

表示:

当前页面还没有关闭过弹窗。

用户点击:

知道了

之后:

noticeDismissed = true;

同时删除弹窗。

以后程序再次执行初始化时:

if (noticeDismissed) {
    return;
}

因此当前页面不会再次显示。


为什么刷新后又会显示?

因为这个变量只存在于当前页面的 JavaScript 内存中。

刷新浏览器后:

网页重新加载
       ↓
JavaScript重新执行
       ↓
noticeDismissed重新初始化
       ↓
false
       ↓
允许重新显示弹窗

因此:

进入 /upload
    ↓
弹窗
    ↓
点击“知道了”
    ↓
当前页面不再弹
    ↓
刷新页面
    ↓
重新弹

这种方式特别适合“本次访问期间不要重复打扰用户,但下次访问仍然提醒”的场景。


十一、完整 JavaScript 代码

下面是最终完整代码。

注意:

这是纯 JavaScript。

如果 Chevereto 后台的自定义 JS 输入框要求填写 JavaScript,直接粘贴下面代码即可。

不要额外添加 <script> 和 </script> 标签。

(function () {
    'use strict';

    /* =========================================================
     * 浮光游客上传提示
     * ========================================================= */

    var NOTICE_PAGE = '/upload';

    var EXCLUDED_PATHS = [
        '/login',
        '/signup',
        '/register',
        '/account',
        '/account/password-forgot',
        '/account/password-reset'
    ];

    /*
     * 当前页面生命周期内的关闭状态
     *
     * 不使用 Cookie
     * 不使用 localStorage
     * 不使用 sessionStorage
     *
     * 刷新页面后重新显示。
     */
    var noticeDismissed = false;


    /* =========================================================
     * 获取当前路径
     * ========================================================= */

    function getCurrentPath() {

        var path = window.location.pathname || '/';

        path = path.replace(/\/+$/, '');

        if (path === '') {
            path = '/';
        }

        return path;
    }


    /* =========================================================
     * 判断是否为排除页面
     * ========================================================= */

    function isExcludedPage(path) {

        var i;

        for (i = 0; i < EXCLUDED_PATHS.length; i++) {

            if (path === EXCLUDED_PATHS[i]) {
                return true;
            }

            if (
                EXCLUDED_PATHS[i] === '/account' &&
                path.indexOf('/account/') === 0
            ) {
                return true;
            }
        }

        return false;
    }


    /* =========================================================
     * 判断当前是否为上传页面
     * ========================================================= */

    function isNoticePage(path) {

        return path === NOTICE_PAGE;

    }


    /* =========================================================
     * 判断登录状态
     * ========================================================= */

    function isLoggedIn() {

        return document.querySelector(
            '#form-logout'
        ) !== null;

    }


    /* =========================================================
     * 判断弹窗是否已经存在
     * ========================================================= */

    function popupExists() {

        return document.getElementById(
            'fg-notice-mask'
        ) !== null;

    }


    /* =========================================================
     * 创建元素
     * ========================================================= */

    function createElement(tag, css) {

        var element =
            document.createElement(tag);

        if (css) {
            element.style.cssText = css;
        }

        return element;
    }


    /* =========================================================
     * 创建弹窗
     * ========================================================= */

    function createPopup() {

        if (!document.body) {
            return;
        }

        if (popupExists()) {
            return;
        }

        if (noticeDismissed) {
            return;
        }


        /* =====================================================
         * 毛玻璃遮罩
         * ===================================================== */

        var mask = createElement(
            'div',

            'position:fixed;' +
            'left:0;' +
            'top:0;' +
            'right:0;' +
            'bottom:0;' +

            'width:100vw;' +
            'height:100vh;' +

            'box-sizing:border-box;' +

            'display:flex;' +
            'align-items:center;' +
            'justify-content:center;' +

            'padding:20px;' +

            /*
             * 毛玻璃
             */
            'background:rgba(15,23,42,0.35);' +
            'backdrop-filter:blur(10px);' +
            '-webkit-backdrop-filter:blur(10px);' +

            'z-index:2147483647;' +

            'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",' +
            '"Microsoft YaHei",Arial,sans-serif;'
        );

        mask.id = 'fg-notice-mask';


        /* =====================================================
         * 弹窗卡片
         * ===================================================== */

        var box = createElement(
            'div',

            'position:relative;' +
            'display:block;' +

            'width:calc(100% - 40px);' +
            'max-width:430px;' +
            'min-height:200px;' +

            'padding:30px;' +

            'box-sizing:border-box;' +

            'background:#ffffff;' +

            'color:#1e293b;' +

            'border-radius:22px;' +

            /*
             * 柔和阴影
             */
            'box-shadow:' +
            '0 25px 70px rgba(0,0,0,0.25),' +
            '0 0 50px rgba(99,102,241,0.18);' +

            'text-align:center;' +

            'opacity:1;' +
            'visibility:visible;' +
            'transform:none;' +

            'overflow:hidden;'
        );

        box.id = 'fg-notice-box';


        /* =====================================================
         * 右上角关闭
         * ===================================================== */

        var closeButton = createElement(
            'button',

            'position:absolute;' +

            'top:12px;' +
            'right:14px;' +

            'width:32px;' +
            'height:32px;' +

            'padding:0;' +
            'margin:0;' +

            'border:0;' +

            'background:transparent;' +

            'color:#94a3b8;' +

            'font-size:24px;' +
            'font-weight:400;' +
            'line-height:32px;' +

            'cursor:pointer;' +

            'text-align:center;'
        );

        closeButton.id = 'fg-notice-x';

        closeButton.type = 'button';

        closeButton.innerHTML = '×';


        /* =====================================================
         * 蓝色云朵图标
         * ===================================================== */

        var icon = createElement(
            'div',

            'width:64px;' +
            'height:64px;' +

            'margin:0 auto 18px;' +

            'border-radius:50%;' +

            /*
             * 蓝色渐变
             */
            'background:linear-gradient(135deg,#4facfe,#1677ff);' +

            'display:flex;' +
            'align-items:center;' +
            'justify-content:center;' +

            'color:#ffffff;' +

            'font-size:30px;' +
            'line-height:64px;' +

            /*
             * 蓝色光晕
             */
            'box-shadow:0 10px 25px rgba(22,119,255,0.25);'
        );

        icon.textContent = '☁';


        /* =====================================================
         * 标题
         * ===================================================== */

        var title = createElement(
            'div',

            'display:block;' +

            'margin:0 0 18px 0;' +

            'color:#111827;' +

            'font-size:24px;' +
            'font-weight:700;' +

            'line-height:1.4;'
        );

        title.id = 'fg-notice-title';

        title.textContent = '游客上传提示';


        /* =====================================================
         * 正文
         * ===================================================== */

        var text = createElement(
            'div',

            'display:block;' +

            'margin:0;' +

            'color:#475569;' +

            'font-size:15px;' +

            'line-height:1.8;'
        );

        text.id = 'fg-notice-text';


        text.appendChild(
            document.createTextNode(
                '您当前正在以游客身份上传文件。'
            )
        );

        text.appendChild(
            document.createElement('br')
        );


        text.appendChild(
            document.createTextNode(
                '游客上传的图片、视频等文件'
            )
        );

        text.appendChild(
            document.createElement('br')
        );


        /* =====================================================
         * 蓝色高亮标签
         * ===================================================== */

        var days = createElement(
            'span',

            'display:inline-block;' +

            'margin:15px 0;' +

            'padding:8px 16px;' +

            'border-radius:999px;' +

            /*
             * 浅蓝背景
             */
            'background:#eef6ff;' +

            /*
             * 蓝色文字
             */
            'color:#1677ff;' +

            'font-size:15px;' +

            'font-weight:700;' +

            'line-height:1.4;' +

            'border:1px solid rgba(22,119,255,0.08);'
        );

        days.id = 'fg-notice-days';

        days.textContent = '仅保留 7 天';

        text.appendChild(days);


        text.appendChild(
            document.createTextNode(
                ',到期后将自动清理。'
            )
        );


        /* =====================================================
         * 提示
         * ===================================================== */

        var tip = createElement(
            'div',

            'display:block;' +

            'margin:10px 0 24px 0;' +

            'padding:10px 14px;' +

            'box-sizing:border-box;' +

            'background:#f5f9ff;' +

            'border-radius:12px;' +

            'color:#64748b;' +

            'font-size:13px;' +

            'line-height:1.7;'
        );

        tip.id = 'fg-notice-tip';

        tip.textContent =
            '注册账号后可以更加方便地管理您的文件。';


        /* =====================================================
         * 按钮容器
         * ===================================================== */

        var buttons = createElement(
            'div',

            'display:flex;' +

            'gap:10px;' +

            'justify-content:center;' +

            'align-items:center;' +

            'width:100%;' +

            'box-sizing:border-box;'
        );

        buttons.id = 'fg-notice-buttons';


        /* =====================================================
         * 登录按钮
         * 蓝色
         * ===================================================== */

        var login = createElement(
            'a',

            'display:inline-flex;' +

            'align-items:center;' +
            'justify-content:center;' +

            'min-width:100px;' +
            'height:44px;' +

            'padding:0 20px;' +

            'box-sizing:border-box;' +

            'border:0;' +

            'border-radius:12px;' +

            /*
             * 蓝色渐变
             */
            'background:linear-gradient(135deg,#4facfe,#1677ff);' +

            'color:#ffffff;' +

            'font-size:14px;' +

            'font-weight:600;' +

            'cursor:pointer;' +

            'text-decoration:none;' +

            /*
             * 蓝色阴影
             */
            'box-shadow:0 8px 20px rgba(22,119,255,0.22);' +

            'transition:all .2s ease;'
        );

        login.id = 'fg-notice-login';

        login.href = '/login';

        login.textContent = '登录';


        /* =====================================================
         * 注册按钮
         * 绿色
         * ===================================================== */

        var register = createElement(
            'a',

            'display:inline-flex;' +

            'align-items:center;' +
            'justify-content:center;' +

            'min-width:100px;' +
            'height:44px;' +

            'padding:0 20px;' +

            'box-sizing:border-box;' +

            'border:0;' +

            'border-radius:12px;' +

            /*
             * 绿色渐变
             */
            'background:linear-gradient(135deg,#34d399,#10b981);' +

            'color:#ffffff;' +

            'font-size:14px;' +

            'font-weight:600;' +

            'cursor:pointer;' +

            'text-decoration:none;' +

            /*
             * 绿色阴影
             */
            'box-shadow:0 8px 20px rgba(16,185,129,0.20);' +

            'transition:all .2s ease;'
        );

        register.id = 'fg-notice-register';

        register.href = '/signup';

        register.textContent = '注册';


        /* =====================================================
         * 知道了按钮
         * 灰色
         * ===================================================== */

        var knowButton = createElement(
            'button',

            'display:inline-flex;' +

            'align-items:center;' +
            'justify-content:center;' +

            'min-width:100px;' +
            'height:44px;' +

            'padding:0 20px;' +

            'box-sizing:border-box;' +

            'border:1px solid #e2e8f0;' +

            'border-radius:12px;' +

            'background:#f1f5f9;' +

            'color:#475569;' +

            'font-size:14px;' +

            'font-weight:600;' +

            'cursor:pointer;' +

            'transition:all .2s ease;'
        );

        knowButton.id = 'fg-notice-close';

        knowButton.type = 'button';

        knowButton.textContent = '知道了';


        /* =====================================================
         * 加入按钮
         * ===================================================== */

        buttons.appendChild(login);

        buttons.appendChild(register);

        buttons.appendChild(knowButton);


        /* =====================================================
         * 组装弹窗
         * ===================================================== */

        box.appendChild(closeButton);

        box.appendChild(icon);

        box.appendChild(title);

        box.appendChild(text);

        box.appendChild(tip);

        box.appendChild(buttons);

        mask.appendChild(box);

        document.body.appendChild(mask);


        /* =====================================================
         * 手机端布局
         * ===================================================== */

        function applyResponsiveLayout() {

            var isMobile =
                window.matchMedia &&
                window.matchMedia(
                    '(max-width: 480px)'
                ).matches;


            if (isMobile) {

                box.style.padding =
                    '26px 20px';

                buttons.style.flexDirection =
                    'column';

                login.style.width =
                    '100%';

                register.style.width =
                    '100%';

                knowButton.style.width =
                    '100%';

            } else {

                box.style.padding =
                    '30px';

                buttons.style.flexDirection =
                    'row';

                login.style.width =
                    '';

                register.style.width =
                    '';

                knowButton.style.width =
                    '';
            }
        }


        applyResponsiveLayout();


        window.addEventListener(
            'resize',
            applyResponsiveLayout
        );


        /* =====================================================
         * 关闭弹窗
         * ===================================================== */

        function closePopup() {

            noticeDismissed = true;


            if (
                mask &&
                mask.parentNode
            ) {

                mask.parentNode.removeChild(mask);

            }


            window.removeEventListener(
                'resize',
                applyResponsiveLayout
            );


            document.removeEventListener(
                'keydown',
                keyHandler
            );
        }


        /* =====================================================
         * ×
         * ===================================================== */

        closeButton.addEventListener(
            'click',
            closePopup
        );


        /* =====================================================
         * 知道了
         * ===================================================== */

        knowButton.addEventListener(
            'click',
            closePopup
        );


        /* =====================================================
         * 点击遮罩
         * ===================================================== */

        mask.addEventListener(
            'click',
            function (event) {

                if (
                    event.target === mask
                ) {

                    closePopup();

                }

            }
        );


        /* =====================================================
         * 阻止卡片内部点击冒泡
         * ===================================================== */

        box.addEventListener(
            'click',
            function (event) {

                event.stopPropagation();

            }
        );


        /* =====================================================
         * ESC
         * ===================================================== */

        function keyHandler(event) {

            if (
                event.key === 'Escape'
            ) {

                closePopup();

            }

        }


        document.addEventListener(
            'keydown',
            keyHandler
        );


        /* =====================================================
         * 控制台
         * ===================================================== */

        console.log(
            '[浮光游客提示] 游客上传提示已显示'
        );
    }


    /* =========================================================
     * 初始化
     * ========================================================= */

    function init() {

        var path =
            getCurrentPath();

        var noticePage =
            isNoticePage(path);

        var excluded =
            isExcludedPage(path);

        var loggedIn =
            isLoggedIn();


        console.log(
            '[浮光游客提示]',
            'path:',
            path,
            'noticePage:',
            noticePage,
            'excluded:',
            excluded,
            'loggedIn:',
            loggedIn,
            'dismissed:',
            noticeDismissed
        );


        if (!noticePage) {
            return;
        }


        if (excluded) {
            return;
        }


        if (loggedIn) {
            return;
        }


        if (noticeDismissed) {
            return;
        }


        createPopup();
    }


    /* =========================================================
     * 启动
     * ========================================================= */

    function start() {

        if (!document.body) {

            setTimeout(
                start,
                100
            );

            return;
        }


        setTimeout(
            init,
            500
        );
    }


    /* =========================================================
     * DOM Ready
     * ========================================================= */

    if (
        document.readyState === 'loading'
    ) {

        document.addEventListener(
            'DOMContentLoaded',
            start
        );

    } else {

        start();

    }

})();

十二、部署步骤

第一步:进入 Chevereto 后台

进入你的 Chevereto 管理后台。

找到网站的:

自定义 JavaScript / Custom JS

图片[2]-给Chevereto游客用户上传文件增加一个弹窗提示-鼎点&Blog

第二步:删除旧代码

如果之前已经添加过游客提示代码:

先把旧代码全部删除。

不要将新代码追加到旧代码后面。

否则可能出现:

  • 弹窗出现两次;
  • 两套关闭事件同时执行;
  • CSS 样式冲突;
  • 控制台出现重复日志。

第三步:粘贴完整代码

将本文“完整 JavaScript 代码”中的内容全部复制。

直接粘贴到 Chevereto 的自定义 JS 输入框。

特别注意

不要添加:

<script>

也不要添加:

</script>

因为后台的自定义 JS 输入框本身就是 JavaScript 执行环境。

正确:

(function () {
    ...
})();

错误:

<script>
(function () {
    ...
})();
</script>

十三、保存后测试

建议按照下面的顺序进行测试。

测试 1:游客访问上传页面

使用浏览器隐身窗口,或者退出当前账号。

打开:

https://你的域名/upload

应该显示:

游客上传提示


测试 2:点击“知道了”

点击:

知道了

应该立即关闭弹窗。

然后正常使用上传功能。

不会跳转登录,也不会跳转注册。


测试 3:刷新页面

在 /upload 页面按:

Ctrl + R

或者:

F5

刷新。

弹窗应该重新出现。

这是因为:

noticeDismissed

只存在于当前页面的 JavaScript 内存中。


测试 4:登录后访问上传页面

登录账号。

然后进入:

/upload

应该:

不显示弹窗。

因为登录用户页面存在:

#form-logout

程序检测到已经登录后直接结束。


测试 5:首页

访问:

/

应该:

不显示弹窗。


测试 6:登录页面

访问:

/login

应该:

不显示弹窗。


测试 7:注册页面

访问:

/signup

应该:

不显示弹窗。


十四、如何使用浏览器控制台排查

如果出现问题,可以按:

F12

打开浏览器开发者工具。

然后进入:

Console / 控制台

正常情况下,可以看到类似:

[浮光游客提示]
path: /upload
noticePage: true
excluded: false
loggedIn: false
dismissed: false

然后:

[浮光游客提示] 游客上传提示已显示

这说明:

当前页面:/upload
页面符合要求:true
没有被排除:false
当前没有登录:false
当前还没有关闭弹窗:false

因此最终显示弹窗。


十五、不同情况下控制台结果

游客 /upload

path: /upload
noticePage: true
excluded: false
loggedIn: false
dismissed: false

结果:

显示弹窗

登录用户 /upload

path: /upload
noticePage: true
excluded: false
loggedIn: true
dismissed: false

结果:

不显示

因为:

if (loggedIn) {
    return;
}

游客首页

path: /
noticePage: false

结果:

不显示

游客点击“知道了”后

状态变成:

dismissed: true

结果:

不再创建弹窗

刷新页面后

重新初始化:

dismissed: false

结果:

再次显示弹窗

十六、常见问题

1. 为什么保存代码后没有效果?

首先确认:

不要添加 <script> 标签。

后台自定义 JS 中应该直接填写:

(function () {
    ...
})();

而不是:

<script>
...
</script>

然后清除浏览器缓存,再重新打开 /upload。


2. 为什么登录用户也出现弹窗?

打开 F12 → Console。

查看:

loggedIn

正常登录用户应该是:

loggedIn: true

如果仍然是:

loggedIn: false

说明当前 Chevereto 版本的登录状态页面结构可能发生了变化,需要重新确认登录用户页面中的退出登录元素。


3. 为什么首页也出现弹窗?

检查:

path

首页应该显示:

path: /

同时:

noticePage: false

如果首页仍然弹窗,通常说明页面中存在旧版游客提示代码。

建议:

  1. 删除所有旧代码;
  2. 只保留本文这一份代码;
  3. 清除浏览器缓存;
  4. 重新测试。

4. 为什么点击“知道了”之后刷新还不弹?

本文代码本身不会持久化关闭状态。

它没有使用:

Cookie
localStorage
sessionStorage

所以刷新以后:

noticeDismissed

一定会重新初始化为:

false

如果刷新后没有弹,应该重点检查:

loggedIn
noticePage
excluded

这三个判断条件。


5. 为什么点击“知道了”以后又马上出现?

如果出现这种情况,通常意味着页面存在其他 JavaScript 再次调用弹窗初始化,或者同时存在旧版本代码。

可以检查:

[浮光游客提示]

是否在控制台出现多次。

如果出现多个版本的初始化日志,建议删除旧代码,只保留当前版本。


6. 点击弹窗外部为什么也可以关闭?

这是代码主动设计的功能。

实现:

mask.addEventListener(
    'click',
    function (event) {
        if (event.target === mask) {
            closePopup();
        }
    }
);

只有点击黑色遮罩本身才会关闭。

点击弹窗内容不会触发关闭。


7. 为什么点击 ESC 也能关闭?

代码监听了:

event.key === 'Escape'

因此用户按键盘:

Esc

也可以关闭弹窗。

关闭后同样会设置:

noticeDismissed = true;

因此当前页面不会再次弹出。


十七、如何修改提示内容?

如果以后需要修改提示文字,只需要修改:

text.appendChild(
    document.createTextNode('您当前正在以游客身份上传文件。')
);

例如改成:

text.appendChild(
    document.createTextNode('游客上传的文件仅保留 7 天。')
);

“注册后”的提示则修改:

tip.textContent =
    '注册账号后可以更加方便地管理您的文件。';

十八、如何修改保留时间?

目前显示:

仅保留 7 天

对应:

days.textContent = '仅保留 7 天';

例如实际策略变成 30 天,只需要修改:

days.textContent = '仅保留 30 天';

需要注意:

JavaScript 这里只负责显示提示文字,并不会改变 Chevereto 实际文件的保存周期。

如果服务器实际设置的是 7 天,而这里只写 30 天,那么只是显示内容与实际策略不一致。

因此提示文字应该和网站实际的游客文件清理策略保持一致。


十九、如何修改弹窗按钮?

目前三个按钮:

登录
注册
知道了

登录地址:

login.href = '/login';

注册地址:

register.href = '/signup';

如果你的站点注册地址不同,可以直接修改。

例如:

register.href = '/register';

二十、为什么推荐动态创建弹窗?

这种方案最大的优点是:

不修改 Chevereto 核心文件

不会直接修改:

PHP
模板文件
核心 JS
核心 CSS

因此 Chevereto 后续升级时,理论上不会因为核心文件被修改而产生冲突。


不需要修改数据库

整个关闭状态只存在于当前页面 JavaScript 内存。

因此不会增加:

  • 数据库字段;
  • Cookie;
  • 用户设置;
  • 服务端 Session。

不影响原有上传功能

弹窗只是一个前端提示层。

用户点击:

知道了

之后:

弹窗消失
       ↓
上传页面恢复正常
       ↓
游客仍然可以上传

它不会修改上传按钮,也不会修改上传接口。


二十一、最终实现总结

整个功能实际上由四个核心模块组成:

① 页面判断
   ↓
判断是否为 /upload

② 登录状态判断
   ↓
判断是否存在 #form-logout

③ 当前页面关闭状态
   ↓
noticeDismissed

④ 动态创建弹窗
   ↓
document.createElement()

最终形成:

游客
 │
 ▼
访问 /upload
 │
 ▼
不是排除页面
 │
 ▼
没有登录
 │
 ▼
当前页面没有关闭过
 │
 ▼
显示游客提示
 │
 ├── 登录 → /login
 │
 ├── 注册 → /signup
 │
 └── 知道了 → 当前页面关闭
                     │
                     ▼
                  刷新页面
                     │
                     ▼
                 再次显示

这种实现方式简单、独立,而且不需要修改 Chevereto 核心程序,比较适合通过后台自定义 JavaScript实现网站前端功能增强。

总结

本教程实现的核心并不是单纯制作一个弹窗,而是建立了一套完整的**“页面 + 用户身份 + 当前访问状态”三重判断机制**:

页面必须正确
+
用户必须是游客
+
当前访问期间没有关闭过
=
显示提示

这样既能够向游客明确说明文件保存规则,又不会反复打扰已经登录的用户,同时也不会让“知道了”变成永久性的关闭设置。

对于允许游客上传文件的图片、视频托管站来说,这种方式能够在用户体验和规则提示之间取得比较好的平衡。

版权声明
站内部分内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供网络资源分享服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请 联系我们 一经核实,立即删除。并对发布账号进行永久封禁处理。在为用户提供最好的产品同时,保证优秀的服务质量。


本站仅提供信息存储空间,不拥有所有权,不承担相关法律责任。
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容